Classify/WorkBench

Handbook

Classify/WorkBench 2.x

Handbook

Version : 2.1

Classify : 2.0

Date : May 1996

Information in this document is subject to change without notice and does not represent a commitment on the part of Calvin Consultancy. The software described in this document is furnished under a license agreement. The software may be used or copied only in accord- ance with the terms of this agreement. It is against the law to copy the software on any medium except as specifically allowed in the li- cense agreement. The purchaser may make one copy of the software for backup purposes. No part of this manual may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording, or information recording and re- trieval systems, for any purpose other than the purchaser’s personal use, without the express written permission of Calvin Consultancy. License Agreement

Calvin Consultancy, further referred to as Licensor, grants licensee a non-exclusive right to use the included software, further referred to as Prod- ucts, for software development under the following conditions: » For Products designated on the package as ‘single user’, Licensor grants to you a limited, non-exclusive license to: · install and operate the copy of the software contained in this package (Products) on a single computer (one central processing unit) and · make archival copies of the Products for back-up purposes only for use with the same computer. » For Products designated on this package as ‘multi user’, Licensor grants to you a limited, non-exclusive license to: · install and operate Products on one multi-user computer (one central processing unit and directly connected terminals) or · install and operate Products on one local area network (LAN) server and operate Products solely on workstation computers physically attached to the LAN server on which Products are installed (but not including a computer having access to the LAN by way of a bridge or gateway) and · make archival copies of Products for back-up purposes only for use with the same multi-user computer or LAN. » Licensee agrees to affix a label to the archival copies which contains the copyright notice printed on the original disks from which the copy is made. Licensor retains all rights to the Products not expressly granted in this agreement. » This license is not a sale of the original Products or any copies thereof. Licensor retains ownership of all software and all copies thereof, re- gardless of the form in which the copies may exist. Licensee only has the right to use the software. He cannot sell or distribute this software in any form, except as part of a compiled program. Selling or distributing this software only as part of a compiled program is only applicable for Pro-ducts which include the source code. » If the Product consists of compiled DataFlex programs, this the licensee has the right to create applications using the Products and sell or distribute these created applications. However, this license will not release licensee from the obligation to purchase a DataFlex runtime li- cense to be able to run the programs provided with the Product. For Products including the source code, licensee has the right to compile programs using the Pro-ducts and sell or distribute these compiled programs. However, if the compiler required to produce these programs requires a separate license, runtime modules, or its license requires the purchase of a runtime license for developed applications, this license will not release licensee from this obligation. » On the identification label, the number of users is stated. This is the maximum number of developers licensed to work with the Products. Working on a piece of source code that will require all or part of the Pro-ducts to (pre)compile, link, run or to gene-rate source code, is con- sidered working with the Products. Using an application compiled using the Products or created with the Products is not considered using the Pro-ducts. » Both software and documentation are copyrighted and might contain valuable tradesecrets and confidential information proprietary to Licen- sor. The software and documentation may not be copied other than under the conditions of this license agreement and for back-up purposes. Licensee agrees to exercise reasonable efforts to protect Licensor’s proprietary interest in the software and documentation and maintain them in strict confidence.

Limited Warranties and limitations of liability

Licensor grants the licensee a limited warning that the media on which the program is distributed are free of material defects. All claims must be made in writing within 10 days after delivery. If the product has been damaged by accident, misuse, abuse or misapplication the warranties do not apply and licensee needs to take full responsibility.

Disclaimer: except as specified above, Licensor makes no warranties or representations, express or implied, oral or written, regarding the Prod- ucts, media or documentation and hereby expressly disclaims all other express and implied warranties, including the implied warranties of mer- chantability and fitness for a particular purpose. Licensor does not warrant the Products will meet your requirements or that its operation will be uninterrupted or error free.

Limitations of liability: Licensor and all parties involved in the creation or delivery of the Products or documentation to you shall have no liability to you or any third party for special, incidental, indirect, exemplary and consequential damages (including, but not limited to loss of profits, goodwill or savings, downtime, damage to or replacement of equipment and property or recovery or replacement of programs or data) arising from claims based in warranty, contract, tort (including neglegence), strict tort or otherwise, even if Licensor has been advised of the possibility or such claim of damage. Licensor’s liability for direct damages shall not exceed the actual amount paid for the Products.

General: this license shall be governed and construed in accordance with the laws of The Netherlands. In the event a provision of this Agreement shall be held unenforceable, it shall be deemed severable from the remaining provisions and shall in no way affect the validity or enforceability of the Agreement. The headings and captions used in this Agreement are for convenience only and are not to be considered in construing or inter- preting this Agreement. Classify Handbook Chapter 1: Introduction

1 Introduction Classify has become the framework of choice for many profes- sional developers world-wide. With over 200 licenses sold and more than 500 active developers, it represents a major methodo- logy for using Object Oriented Development with DataFlex 3.x.

Its emphasis on database consistency and integrity as well as on ease of maintenance and clarity of design has put Classify in its current position as primary 3rd party product for DataFlex. Its pow- erful user interface has made its way into thousands of delivered applications. Its standards approach to application design and naming conventions has enabled developers separated by thou- sands of miles to work together on common project.

With version 2.0 of the Classify class library, Calvin Consultancy puts you in a new dimension of database management. Besides the already well known and appreciated features of multiple rela- tionships to one parent and recursive relationships, we have now added support for multiple relationships sharing one field in the database, support for double linked lists and automatic control of the file modes, so that only those files that will actually be written to will get locked by the database manager.

On the user interface side, Calvin Consultancy has added Classify for Windows to its product range. This class library provides all the Classify functionality with a true Windows GI front-end, while re- taining source code compatibility with the character mode version of Classify. Classify for Windows is available under our cross-plat- form licensing policy. Please contact your distributor for more de- tails.

In this version of the handbook, we have also integrated the docu- mentation for the Classify Workbench into a single manual along with the package documentation.Where appropiate, we have in- cluded descriptions of parts of the WorkBench to illustrate how to set up the described features in the WorkBench. This was initiated by the marketing merge of Classify and WorkBench. These two are no longer available as seperate products but are merged into the Classify/WorkBench product.

This Classify handbook is intended to guide you into Classify de- velopment and to assist you as a reference guide later in the de- velopment process. All messages that you will need for regular tasks are discussed in this handbook. All other messages will be provided in on-line form with the release of the Work-bench ver- sion 2.0. However, these message are grouped based on intended usage. If you use messages not labelled “public”, the functionality of the message might change without official notice. All messages in this handbook are public and we will try to keep them consistent over the various releases of Classify.

Chapter 3 of this handbook provides you with a proposed develop- ment environment. Although Classify does not require a specific environment, many users have found that this set-up fits with their needs and allows a structured approach to multi-project develop- ment.

The next chapter (4) provides an overview of the Classify struc- ture. It provides a good insight in the way Classify programs are structured. This conceptual background is expanded in the next chapter, where we discuss a typical development standard for a Classify project.

() '92 - '95 Calvin Consultancy March 1995 Page 1.1 Chapter 1: Introduction Classify Handbook

The chapters 6 through 9 contain the detailed descriptions of the main Classify packages. All sorts of assorted topics are discussed in the appendices of the manual. These can contain very useful in- formation and we strongly suggest you look at them as a valuable part of the manual.

If you are new to Object Orientation, we suggest you check out ap- pendix C, where we discuss general concepts and methodologies. Appendix E provides documentation on a number of useful system functions.

When you are starting to use Classify, the Classify WorkBench can be an excellent learning tool. It will generate a large percent- age of the code discussed in the manuals. As soon as the next re- vision of the WorkBench is released, we will integrate the Work- Bench manual with this handbook to reflect the effective merger of the two products.

The printed documentation is complemented by white papers. You can find these in the Classify\Doc directory. We also will upload new white papers to the compuserve forum when new paper or versions are available.

For the experienced Data- Even if you are an experienced DataFlex 3.x developer, we Flex 3.x developer strongly suggest you read through the chapters 3, 4 and 5. Clas- sify takes an approach very different from the other DataFlex pro- gramming techniques. The centralised problem domain description (data dictionary) is much more advanced than similar offerings and its importance in the Classify model is greater.

Also, the Classify desktop is a very active part of the framework. It is the backbone of the whole framework and takes care of many of the navigational needs. When you want to expand the Classify functionality, you will find that the Desktop is a core element and a proper understanding of its workings is essential.

A final advice when trying to understand Classify. We have struc- tured the packages in a way that we hope shows an open design. Many times, users who have dared to open the packages in their editors and explored them have commented that “Classify is the best piece of example code available”. So don’t hesitate to look in the packages for hints or examples. In fact, some packages are explicitly build with this in mind: » SELSUB.PKG » SPEC_ML.PKG » GEN_TXT.PKG » CLSERV_N.PKG » CLSERV_W.PKG

You might notice when you browse through the packages that we limit the contents of a package to one class definition.

Page 1.2 March 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 1: Introduction About this manual

11. About this manual This manual is divided into three main parts: » introduction; » discussion of the main classes; » special topics (appendices).

Both a table of contents and an index are supplied for easy access to the information. In the appendices, you will also find additional information, such as: » the Classify user-manual (which you can copy and distribute freely); » introduction to object oriented concepts; » specifications of the system files.

We use several typographic effects to distinguish between the various sorts of information given in the manual. The main text will be printed using this font.

Warning: Very important parts of the manual will be printed using this bold font.

Examples and hints: Examples and hints are printed in a smaller font.

For every message or property, the syntax is specified like this:

Syntax: Send mMessage [Argument] [Argument]

Whatever is displayed between brackets can contain names/vari- ables specific for your situation. If we supply an example code, the variable names are displayed in italics.

Example: Send mMessage My_Argument And_Another

If certain discussions are specific for Classify for Windows, they are printed in Italics. Of course, this does not apply to the appendices spe- cific to Classify for Windows.

(c) '92 - '95 Calvin Consultancy March 1995 Page 1.3 Chapter 1: Introduction Classify Handbook Requirements

12. Requirements This handbook assumes knowledge about object oriented programming in DataFlex 3.x. This means you should at least be familiar with: » message definition; » use of messages and properties; » mechanics of delegation and inheritance; » creation of custom-defined classes.

Classify supports a large number of classes that will tackle a number of common problems. However, every larger application will have some areas where these general classes will not cover the problem. In these cases, you might have to resort to building your own classes. For that, you would also need knowledge about the base classes of DataFlex. But even then, it will be helpful to have knowledge about the base classes of Classify. The more classes you are familiar with, the more chance you have to choose the best class for the job.

We strongly recommend 386sx/25 hardware (at least 4Mb RAM) for end-users and 486 with 8Mb for developers. For developers, we also recommend the latest release of DataFlex (currently 3.05). For Classify for Windows and for the Workbench, version 3.05 is required.

Page 1.4 March 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 1: Introduction Getting in touch

13. Getting in touch Usually, support for Classify is provided through your local dis- tributor. Any questions you have can be directed at him. He will also send you your updates and inform you when your free sup- port period or your support contract expires.

If you have purchased your license directly through Calvin Con- sultancy or you have a support contract directly with Calvin Con- sultancy, the support is done directly through Calvin Consultancy. In this case, the level of support depends on the type of your sup- port contract.

In addition to this support, Data Access has made a special sec- tion in their Compuserve forum (GO DACCESS) available to Classify users. You can get in touch with fellow developers there, in which you can post questions, discuss general principles or find samples from other developers. Calvin support members visit the forum fre- quently as well, so you can rest assured that your problems will be looked into.

In general, we suggest the usage of the forum if you are looking for answers to question to go beyond regular usage or you are looking for input from different sources. Calvin Consultancy also uses CompuServe to distribute additional samples and minor re- leases.

IfyouhaveadirectPremium Support contract with Calvin Consult- ancy, or you are in the first six moths of usage after buying directly from Calvin Consultancy, you can contact our support using the following E-Mail address: » MHS Support @ Calvin » Compuserve >MHS:Support@Calvin >INTERNET:Support@Cal vin.NL » Internet [email protected]

You can contact our sales department at: » MHS Sales @ Calvin » Compuserve >MHS:Sales@Calvin >INTERNET:Sales@Calvin. NL » Internet [email protected]

(c) '92 - '95 Calvin Consultancy March 1995 Page 1.5 Chapter 1: Introduction Classify Handbook Acknowledgements

14. Acknowledgements We want to express our thanks to the people at Abacus in Switzer- land, who started us of at 3.0; Ruud Visser and Leo ‘t Hooft (Hunter Douglas Europe) for helping us to outline the philosophy and for being a patient test site; and of course to Data Access Corporation for the deliverance of the base product that made it all possible.

We also want to thank Kent Frese for being the first supporter we got, Steff McConagle who covered large parts of the support in the United States and our world wide distributors.

Finally, we would like to thank you for your trust in us. It is our aim to keep bringing you better tools for professional system develop- ment.

Calvin Consultancy

DataFlex is a registered trademark of Data Access Corporation Classify is a registered trademark of Calvin Consultancy

Page 1.6 March 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 2: Table Of Contents

Table Of Contents

1 Introduction ...... 1.1 11. About this manual ...... 1.3 12. Requirements ...... 1.4 13. Getting in touch ...... 1.5 14. Acknowledgements ...... 1.6

3. The environment ...... 3.2 3.1. Classify ...... 3.4 3.1.1. Data (DAT) ...... 3.4 3.1.2. Images (IMG) ...... 3.5 3.1.3. Packages (PKG) ...... 3.5 3.1.4. File definitions (DEF) ...... 3.6 3.1.5. Sources (SRC) ...... 3.6 3.1.6. Documents (DOC) ...... 3.6 3.1.7. Environment (Env) ...... 3.6 3.1.8. WorkBench generated (WBG) ...... 3.6 3.1.9. WorkBench special (WBS) ...... 3.6 3.1.10. WorkBench definition (WBD) ...... 3.6 3.1.11. Compiler output (CMP) ...... 3.6 3.1.12. User (USR) ...... 3.6 3.1.13. Miscellaneous (MISC) ...... 3.7 3.1.14. Other configurations ...... 3.7 3.2. The projects ...... 3.8 3.3. Batch files ...... 3.9 3.3.1. Set up Classify (CL_SET) ...... 3.9 3.3.2. Go to a project (GO) ...... 3.9 3.3.3. Run a program (CL_RUN) ...... 3.9 3.3.4. Compile a program (CL_COMP) ...... 3.9 3.3.5. Test a program (CL_TEST) ...... 3.9 3.3.6. Run WorkBench (WB) ...... 3.9 3.3.7. Create new project (CL_NEW) ...... 3.9 3.4. Environments settings ...... 3.10 3.5. Classify INI files ...... 3.11

4. Overview ...... 4.1 4.1. History ...... 4.2 4.2. Database design ...... 4.3 4.2.1. Data dictionary ...... 4.3 4.3. Data entry modules ...... 4.4 4.3.1. Zooms ...... 4.4 4.3.2. Subsystems ...... 4.4 4.3.3. Views ...... 4.4 4.4. Batch processes ...... 4.6 4.4.1. Batch report ...... 4.6 4.4.2. Batch server ...... 4.6 4.5. The desktop ...... 4.7 4.5.1. Communications ...... 4.7 4.5.2. The Swiss army knife ...... 4.7

(c) '92 - '95 Calvin Consultancy June 1995 Page 2.1 Chapter 2: Table Of Contents Classify Handbook

4.6. The program structure ...... 4.8 4.7. The class tree ...... 4.10 4.8. Naming and program style conventions ...... 4.11 4.8.1. Naming conventions ...... 4.11 4.8.1.1. General guidelines ...... 4.11 4.8.1.2. Objects ...... 4.11 4.8.1.3. Classes ...... 4.11 4.8.1.4. Messages ...... 4.11 4.8.1.5. Properties ...... 4.12 4.8.1.6. Variables ...... 4.12 4.8.1.7. Images ...... 4.12 4.8.1.8. Files ...... 4.12 4.8.1.9. Constants ...... 4.12 4.8.2. Drawing conventions ...... 4.12 4.8.3. Programming guidelines ...... 4.13 4.9. Classify is DataFlex ...... 4.14

5. Using Classify ...... 5.1 5.1. Set up Classify ...... 5.2 5.2. The problem domain ...... 5.3 5.3. Data entry & retrieval ...... 5.6 5.4. Batches ...... 5.11

6. Data dictionary ...... 6.1 6.1. The role of the DDO ...... 6.2 6.2. The DDO in the WorkBench ...... 6.3 6.2.1. Creating your data types ...... 6.3 6.2.2. Field templates ...... 6.4 6.2.3. Creating the database definition ...... 6.4 6.2.4. Specifying your messages ...... 6.7 6.2.5. Creating class definitions ...... 6.8 6.3. File dependent information ...... 6.9 6.3.1. Main File ...... 6.9 6.3.2. Main Index ...... 6.9 6.3.3. Add Child File ...... 6.9 6.3.4. No Delete ...... 6.10 6.3.5. Read Only ...... 6.10 6.3.6. May Modify Indirect ...... 6.10 6.3.7. May Modify ...... 6.10 6.3.8. May Create ...... 6.10 6.3.9. May Copy ...... 6.10 6.3.10. May Change Key ...... 6.11 6.3.11. Ok To Delete Check Func ...... 6.11 6.3.12. Ok To Save Check Func ...... 6.11 6.3.13. User hooks ...... 6.11 6.3.14. Version ...... 6.12 6.4. Field related information ...... 6.13 6.4.1. Field Message ...... 6.13 6.4.2. Predefined field messages ...... 6.14 6.4.2.1. Table Validate ...... 6.14 6.4.2.2. Blank or table ...... 6.14 6.4.2.3. Non Blank ...... 6.14 6.4.3. Creating field messages ...... 6.14 6.4.3.1. Local Field Value ...... 6.14 6.4.3.2. Field Buffer ...... 6.15 6.4.3.3. Subsystem ...... 6.16 6.4.3.4. Update State ...... 6.16 6.4.3.5. Error ...... 6.16 6.4.3.6. Parent Field Value ...... 6.17 6.4.3.7. Global Lookup ...... 6.17

Page 2.2 June 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 2: Table Of Contents

6.4.3.8. Simple Lookup ...... 6.19 6.4.3.9. mCustom Index Lookup ...... 6.19 6.4.3.10. Custom Related Lookup ...... 6.19 6.4.4. Prompt Object ...... 6.20 6.4.5. Zoom Object ...... 6.20 6.4.6. Add Option ...... 6.21 6.4.7. Table ID ...... 6.22 6.4.8. Add List Field ...... 6.23 6.4.9. Field Range ...... 6.23 6.4.10. Default value ...... 6.24 6.4.11. Standard Field ...... 6.24 6.4.12. Field information ...... 6.24 6.4.13. Field number ...... 6.24 6.5. Relationships ...... 6.25 6.5.1. Add Foreign Key Field ...... 6.25 6.5.2. Delete children ...... 6.25 6.5.3. The index for a relation ...... 6.25 6.5.4. DF-File relations ...... 6.26 6.5.5. Sharing a foreign key field ...... 6.26 6.5.6. The effect of relations ...... 6.27 6.6. Dependencies ...... 6.28 6.6.1. Create Dependency ...... 6.28 6.6.2. Add Trigger Field ...... 6.29 6.6.3. Pre-defined dependency procedures ...... 6.29 6.6.3.1. Add Number ...... 6.30 6.6.3.2. Subtract Number ...... 6.30 6.6.3.3. Add Integer ...... 6.30 6.6.3.4. Subtract Integer ...... 6.30 6.6.3.5. SpecSerNr ...... 6.30 6.6.3.6. SerNr ...... 6.30 6.6.3.7. SetHighVal ...... 6.30 6.6.3.8. SetLowVal ...... 6.30 6.6.4. Creating dependency procedures ...... 6.30 6.6.4.1. Update Field ...... 6.31 6.7. Synchronisation ...... 6.32 6.7.1. Requirements ...... 6.32 6.7.1.1. Data-files ...... 6.32 6.7.1.2. The system-file ...... 6.32 6.7.1.3. Data dictionaries ...... 6.33 6.7.2. Effects ...... 6.33 6.7.2.1. Adding records ...... 6.33 6.7.2.2. Changing records ...... 6.33 6.7.2.3. Deleting records ...... 6.34 6.7.3. Procedures ...... 6.34 6.7.3.1. Creating update-files ...... 6.34 6.7.3.2. Processing update-files ...... 6.34 6.7.3.3. Purging records ...... 6.34 6.7.3.4. Writing the synchronisation program ...... 6.35 6.7.4. Using synchronisation ...... 6.35 6.7.5. Advanced use ...... 6.35 6.8. Linked lists ...... 6.36 6.9. File modes ...... 6.37 6.10. Retain templates ...... 6.38 6.11. Run time set-up ...... 6.39 6.11.1. Usage ...... 6.39 6.12. Summary ...... 6.40

7. Data entry ...... 7.1 7.1. Zooms ...... 7.2 7.1.1. Creating zooms ...... 7.2 7.1.2. General characteristics ...... 7.2 7.1.2.1. ID ...... 7.3 7.1.2.2. Auto Activate State ...... 7.3

(c) '92 - '95 Calvin Consultancy June 1995 Page 2.3 Chapter 2: Table Of Contents Classify Handbook

7.1.2.3. Button Bar ...... 7.3 7.1.2.4. Location ...... 7.3 7.1.2.5. Version ...... 7.3 7.1.2.6. Create Item ...... 7.4 7.1.2.7. Create DYNPRESS Item...... 7.4 7.1.2.8. Create DYNPRESS Style Item ...... 7.4 7.1.2.9. Displaying other information ...... 7.5 7.1.2.10. Effect ...... 7.6 7.1.2.11. Duplicate fields ...... 7.6 7.1.2.12. Images ...... 7.6 7.1.3. Entry find ...... 7.7 7.1.3.1. Image definition ...... 7.7 7.1.3.2. Summary ...... 7.7 7.1.4. Multi-line find ...... 7.9 7.1.4.1. Number Of Lines ...... 7.9 7.1.4.2. Image definition ...... 7.9 7.1.4.3. Summary ...... 7.9 7.1.5. cSpecial_Multi_Line ...... 7.11 7.1.5.1. Image definition ...... 7.11 7.1.5.2. Summary ...... 7.11 7.1.6. Entry Zoom ...... 7.13 7.1.6.1. Image definition ...... 7.13 7.1.6.2. Summary ...... 7.13 7.1.7. Checkbox Zoom ...... 7.14 7.1.7.1. True ID ...... 7.14 7.1.7.2. False ID ...... 7.14 7.1.7.3. Image definition ...... 7.14 7.1.7.4. Summary ...... 7.14 7.1.8. Radio Zoom ...... 7.15 7.1.8.1. Image definition ...... 7.15 7.1.8.2. Summary ...... 7.15 7.1.9. Entry Memo ...... 7.16 7.1.9.1. Main field ...... 7.16 7.1.9.2. Begin Of Text ...... 7.16 7.1.9.3. Image definition ...... 7.16 7.1.9.4. Summary ...... 7.16 7.1.10. Table Zoom ...... 7.17 7.1.10.1. Main Field ...... 7.17 7.1.10.2. Image definition ...... 7.17 7.1.10.3. Summary...... 7.17 7.1.11. Bitmap zoom ...... 7.18 7.1.11.1. Main Field ...... 7.18 7.1.11.2. Image definition ...... 7.18 7.1.11.3...... 7.18 7.1.12. Special Zoom ...... 7.19 7.1.12.1. Special Proc...... 7.19 7.1.12.2. Redirect Errors ...... 7.19 7.1.12.3. Image definition ...... 7.19 7.1.12.4. Summary:...... 7.19 7.1.13. General Text Memo ...... 7.21 7.1.13.1. Image definition ...... 7.21 7.1.13.2. Summary:...... 7.21 7.2. Subsystems ...... 7.22 7.2.1. Index selector SBS ...... 7.23 7.2.2. Option group ...... 7.23 7.2.3. Properties and messages ...... 7.25 7.2.3.1. ID ...... 7.25 7.2.3.2. Main File ...... 7.25 7.2.3.3. Constraint Msg ...... 7.25 7.2.3.4. Find Mode ...... 7.26 7.2.3.5. Key_Nr ...... 7.26 7.2.3.6. Index ...... 7.26 7.2.3.7. Auto Activate State ...... 7.26 7.2.3.8. Local_Field_Value ...... 7.26 7.2.3.9. Ok To Delete Check Func ...... 7.27 7.2.3.10. Ok To Save Check Func ...... 7.27 7.2.3.11. User hooks ...... 7.27 7.2.3.12. Version ...... 7.28 7.2.3.13. Update State ...... 7.28 7.2.3.14. Data dictionary ...... 7.29 7.2.3.15. May Change Parent ...... 7.29 7.2.3.16. Rights ...... 7.29 7.2.4. Image definition ...... 7.29 7.2.5. Summary ...... 7.29 7.3. Views ...... 7.31 7.3.1. Properties and messages ...... 7.31 7.3.1.1. pID ...... 7.31

Page 2.4 June 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 2: Table Of Contents

7.3.1.2. pMay_Destroy_Function ...... 7.31 7.3.2. Complex views ...... 7.31 7.3.3. Data dictionaries ...... 7.32 7.3.4. Images ...... 7.32 7.3.5. View classes ...... 7.33 7.3.5.1. View ...... 7.33 7.3.5.2. View Panel ...... 7.33 7.3.6. Summary ...... 7.33

8. Batches ...... 8.1 8.1. The Batch report ...... 8.2 8.1.1. Properties and messages ...... 8.2 8.1.1.1. ID ...... 8.2 8.1.1.2. Main File ...... 8.2 8.1.1.3. Constraint Msg ...... 8.2 8.1.1.4. Detail Message ...... 8.3 8.1.1.5. Minimum Detail Lines ...... 8.3 8.1.1.6. Error handler ...... 8.3 8.1.1.7. Key_Nr ...... 8.3 8.1.1.8. Index ...... 8.3 8.1.1.9. Local Field Value ...... 8.3 8.1.1.10. Ok To Delete Check Func ...... 8.4 8.1.1.11. Ok To Save Check Func ...... 8.4 8.1.1.12. User hooks ...... 8.4 8.1.1.13. Version ...... 8.5 8.1.2. Breakpoints ...... 8.5 8.1.3. Writing a detail message ...... 8.6 8.1.3.1. Printing information ...... 8.6 8.1.3.2. Report Write Image ...... 8.6 8.1.3.3. Report Write Image Wrap ...... 8.6 8.1.3.4. Raw output ...... 8.6 8.1.3.5. Check Page ...... 8.6 8.1.3.6. Buffer access ...... 8.6 8.1.3.7. Save ...... 8.7 8.1.3.8. Save all ...... 8.7 8.1.3.9. Request delete ...... 8.7 8.1.3.10. Request purge ...... 8.7 8.1.4. Writing subheaders and subtotals ...... 8.7 8.1.4.1. Display_Subtotal ...... 8.8 8.1.4.2. At Top Of Page ...... 8.8 8.1.5. New Page ...... 8.8 8.1.6. Headers and Footers ...... 8.8 8.1.7. Summary...... 8.8 8.2. The Batch_Server ...... 8.10 8.2.1. Properties and messages ...... 8.10 8.2.1.1. Report State ...... 8.10 8.2.1.2. Selection Message ...... 8.10 8.2.1.3. Output file ...... 8.10 8.2.1.4. Headers and footers ...... 8.10 8.2.1.5. Filler Image ...... 8.11 8.2.1.6. Page number ...... 8.11 8.2.1.7. ID ...... 8.11 8.2.2. Complex batches ...... 8.11 8.2.3. Summary...... 8.12 8.3. Batch subsystem ...... 8.13 8.3.1. pID ...... 8.13 8.3.2. Redirect Errors ...... 8.13 8.3.3. pBatch_Procedure ...... 8.13 8.3.4. Summary...... 8.13

9. Programs ...... 9.1 9.1. The desktop ...... 9.2 9.2. Groups ...... 9.3 9.3. Other programs ...... 9.4 9.3.1. The menu file ...... 9.4 9.3.2. Coding menu options ...... 9.4 9.4. cView_Group ...... 9.5

(c) '92 - '95 Calvin Consultancy June 1995 Page 2.5 Chapter 2: Table Of Contents Classify Handbook

9.4.1. ID ...... 9.5 9.4.2. Pull down number ...... 9.5 9.4.3. Menu item ...... 9.5 9.4.4. Summary ...... 9.7 9.5. Demo versions ...... 9.8 9.5.1. Demo limit ...... 9.8 9.5.2. Demo version ...... 9.8

10. Classify relationships ...... 10.1 10.1. The key of a file ...... 10.2 10.2. Foreign keys ...... 10.3 10.3. The DataFlex approach ...... 10.5 10.4. The Classify solution ...... 10.6 10.4.1. How Classify reacts ...... 10.6 10.4.1.1. The Data Dictionary ...... 10.6 10.4.1.2. The subsystem ...... 10.6 10.4.1.3. The report ...... 10.7 10.4.2. Relation-commands ...... 10.7 10.4.2.1. Attach ...... 10.7 10.4.2.2. Relate ...... 10.7 10.5. Advanced usage ...... 10.10 10.5.1. Recursive relationships ...... 10.10 10.5.2. Multiple relationship from one field ...... 10.10 10.6. Dependencies ...... 10.11

11. File handling ...... 11.2 11.1. The local file buffer ...... 11.3 11.1.1. When to use the local buffer ...... 11.3 11.1.2. Local buffers outside the subsystem ...... 11.3 11.1.2.1. Request save ...... 11.4 11.1.2.2. Request clear ...... 11.4 11.1.2.3. Request clear all ...... 11.4 11.1.2.4. Find ...... 11.4 11.1.2.5. Init object ...... 11.4 11.2. The DataFlex file buffer ...... 11.6 11.2.1. Clear File ...... 11.6 11.2.2. Special Clear ...... 11.6 11.2.3. Save File ...... 11.6 11.2.4. Delete File ...... 11.6 11.2.5. Field Buffer ...... 11.6 11.2.6. Find File ...... 11.7 11.2.7. File Scan ...... 11.8 11.2.8. When to use the DataFlex buffer ...... 11.8 11.2.9. Other use of the file buffer ...... 11.8 11.3. Classify Intelliwrites ...... 11.10 11.3.1. Enabling and disabling Intelliwrites ...... 11.10 11.3.2. Handling errors during intelliwrites ...... 11.10 11.3.3. Saving in dependency procedures ...... 11.11 11.3.4. Bypassing Intelliwrites ...... 11.11 11.3.5. Summary ...... 11.11 11.4. The Classify Save ...... 11.12 11.4.1. Pseudo code ...... 11.13 11.4.1.1. View ...... 11.14 11.4.1.2. Subsystem ...... 11.14 11.4.1.3. Data_Dictionary ...... 11.15 11.5. The Classify delete ...... 11.16 11.5.1. Pseudo code ...... 11.16 11.5.2. Subsystem ...... 11.16

Page 2.6 June 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 2: Table Of Contents

11.5.3. Data_Dictionary ...... 11.16 11.6. File modes ...... 11.17

A. Classify user manual ...... A.1 A.1. Program activation ...... A.2 A.1.1. The main Classify screen ...... A.2 A.1.1.1. Title bar ...... A.2 A.1.1.2. Action bar ...... A.3 A.1.1.3. Button bar ...... A.4 A.1.1.4. Help Line ...... A.4 A.2. Data entry ...... A.6 A.2.1. Activation ...... A.7 A.2.2. Deactivation ...... A.7 A.2.3. Finding records ...... A.8 A.2.4. Advanced find functions ...... A.10 A.2.5. Editing records ...... A.10 A.2.6. Deleting records ...... A.10 A.2.7. Creating records ...... A.11 A.2.8. Changing key values ...... A.11 A.2.9. Copying ranges of information ...... A.11 A.2.10. Support functions ...... A.12 A.2.10.1. Prompt ...... A.12 A.2.10.2. Zoom ...... A.14 A.2.10.3. Toggle retain ...... A.14 A.2.10.4. Retain all ...... A.15 A.2.10.5. Retain none ...... A.15 A.2.10.6. Picklist (Viewlist) ...... A.15 A.2.10.7. Version information ...... A.15 A.3. Errors & Warnings ...... A.17 A.3.1. Errors ...... A.17 A.3.2. Warnings ...... A.17 A.4. Help system ...... A.19 A.5. Desktop features ...... A.21 A.5.1. Calculator ...... A.21 A.5.2. Calendar ...... A.21 A.5.3. Logfile ...... A.21 A.5.4. Login ...... A.21 A.5.5. Password ...... A.21 A.5.6. Save Windows ...... A.21 A.5.7. Editor...... A.22 A.5.8. Externals ...... A.22 A.6. Batches ...... A.23 A.7. Exiting the program ...... A.24

B. Enhancing and modifying Classify ...... B.1 B.1. Picking the correct package ...... B.2 B.2. Compiling a “limited” version ...... B.3 B.3. Adding your own services ...... B.5 B.4. Using the minimal desktop ...... B.6 B.5. Changing the actionbar ...... B.7

C. Introduction to Object Oriented Concepts ...... C.1 C.1. The object ...... C.2 C.2. Nested objects ...... C.4 C.2.1. Primitives ...... C.4

(c) '92 - '95 Calvin Consultancy June 1995 Page 2.7 Chapter 2: Table Of Contents Classify Handbook

C.3. Encapsulation ...... C.5 C.4. Messages and methods ...... C.8 C.5. Polymorphism ...... C.9 C.6. Delegation ...... C.10 C.7. Classes ...... C.12 C.8. Class inheritance ...... C.13 C.9. Event driven user interface ...... C.14

D. Language additions ...... D.1 D.1. Extensions ...... D.2 D.1.1. Field ...... D.2 D.1.2. FileField ...... D.2 D.1.3. Exp ...... D.2 D.2. New commands ...... D.3 D.2.1. Dynamic_Image ...... D.3 D.2.2. Extract_Field_Nr ...... D.3 D.2.3. FGet ...... D.3 D.2.4. Fill_Wrap ...... D.3 D.2.5. Default_Output ...... D.3 D.2.6. Indirect_File_Size ...... D.3 D.2.7. Push_Parameter ...... D.3 D.2.8. Indirect_Reread ...... D.3 D.2.9. Indirect_File_Mode ...... D.3 D.2.10. Transaction ...... D.4 D.2.11. Use_Extend ...... D.4 D.2.12. Use_Extend_Img ...... D.4 D.2.13. Use_File ...... D.4 D.3. Compiler directives ...... D.5 D.3.1. Framework ID ...... D.5 D.3.1.1. Classify version ...... D.5 D.3.2. DataFlex version ...... D.5 D.3.3. Runtime access ...... D.5

E. Global functions ...... E.2 E.1. String operations ...... E.3 E.1.1. Last pos ...... E.3 E.1.2. Right justify ...... E.3 E.1.3. Left justify ...... E.3 E.1.4. Left pad string ...... E.3 E.1.5. Capitalize ...... E.3 E.1.6. String type ...... E.3 E.2. Numeric functions ...... E.4 E.2.1. Round ...... E.4 E.3. Date functions ...... E.5 E.3.1. Date Type ...... E.5 E.3.2. Today ...... E.5 E.3.3. Year ...... E.5 E.3.4. Month ...... E.5 E.3.5. Day ...... E.5 E.3.6. Date DMY To String ...... E.5 E.3.7. Compose date ...... E.5 E.3.8. Day number ...... E.5 E.3.9. Week number ...... E.5 E.3.10. Date to string ...... E.5

Page 2.8 June 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 2: Table Of Contents

E.4. Desktop functions ...... E.6 E.4.1. I/O channel management ...... E.6 E.4.1.1. Request Channel ...... E.6 E.4.1.2. Release Channel ...... E.6 E.4.1.3. Open device ...... E.6 E.4.1.4. Close Device ...... E.7 E.4.2. Showing a “busy” status ...... E.7 E.4.2.1. Start Busy Object ...... E.7 E.4.2.2. Stop Busy Object ...... E.8 E.4.2.3. Kill Busy Object ...... E.8 E.4.2.4. Update Busy Description ...... E.8 E.4.2.5. Update Busy Detail ...... E.8 E.4.2.6. Set Busy Counter ...... E.8 E.4.2.7. Update Busy Counter ...... E.8

F. Windows considerations ...... F.1 F.1. Source compatibility ...... F.2 F.2. Screen design ...... F.3 F.3. INI settings ...... F.5 F.3.1. Windows ...... F.5 F.3.1.1. Calendar ...... F.5 F.3.1.2. Editor ...... F.5 F.3.1.3. Calculator ...... F.5 F.3.1.4. Icondir ...... F.5 F.3.1.5. PromptIcon ...... F.5 F.3.1.6. ButtonBarSize ...... F.5 F.3.1.7. DesktopHeight & -Width ...... F.5 F.3.1.8. DesktopRow(Column)Location ...... F.5 F.3.2. Windows spacing ...... F.5 F.3.2.1. Horizontal spacing ...... F.5 F.3.2.2. Vertical spacing ...... F.5 F.3.2.3. Item spacing ...... F.5 F.3.2.4. Column spacing ...... F.6 F.3.2.5. Line spacing ...... F.6 F.3.2.6. Prompt spacing ...... F.6 F.3.3. User styles ...... F.6 F.4. Resource files ...... F.7 F.5. CFN files ...... F.8

A. Dynamic use of the filelist ...... A.1 A.1. Using standard Classify pre-compiles ...... A.2 A.2. Using pre-compiles ...... A.3 A.3. Special notes ...... A.4

I. WorkBench & ClassDoc ...... I.1 I.1. Setup ...... I.2

II. Class documentation ...... II.1 II.1. Message base ...... II.2 II.2. Classes ...... II.3 II.3. Automated procedures ...... II.5 II.3.1. Generating Packages ...... II.5 II.3.2. Reading packages ...... II.5 II.3.3. Reader directives ...... II.5 II.4. Suggestions for use ...... II.6

III. File definition ...... III.1 III.1. Types ...... III.2 III.2. Templates ...... III.3

(c) '92 - '95 Calvin Consultancy June 1995 Page 2.9 Chapter 2: Table Of Contents Classify Handbook

III.3. File and field information ...... III.4 III.3.1. Field information ...... III.5 III.3.2. Extra file information ...... III.5 III.3.3. DEF-Files ...... III.7

IV. The change log ...... IV.1

Page 2.10 June 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 3: The environment

3. The environ- This chapter contains a suggestion on how to structure your files involved with Classify and Classify projects. Although Classify lets ment you set up your own directory structure and relies fully on DFPATH settings, we strongly suggest you stick to this structure until you are thoroughly familiar with Classify. This will both help you (Classify will create more files than you are used to in 2.3 environments) and it will also help our support staff in assisting you.

\

Language

DF3.01b

DF305.DOS

DFWin305

DF305.OS2

Develop

Classify Project

Dat Dat

Img Img

Src Src

Pkg Pkg

All All

Win Win

CM CM

Doc Doc

Env Env

Def Def

WbS WbS

WbG WbG

WbD WbD

Cmp Cmp

32c 32c

32w 32w

16c 16c

Usr Usr

Cl_user User_A

User_B

(c) '92 - '95 Calvin Consultancy March 1995 Pag. 3.2 Chapter 3: The environment Classify Handbook

The figure on the previous page shows a suggested directory struc- ture. You will notice that the structures for “Classify” and “ProjectA” are similar. We treat Classify as just another project. Per project we create a new “project” directory.

This structure also allows you to work with several different versions of DataFlex in a common environment. In the picture we have outlined the full structure as used by us in-house.

Optionally, you can choose to install the examples, which will again create a similar project structure. We provide the following example programs: » Classify Maintenance The Classify maintenance programs (SYSTEM and CLSYSTEM) are provided in source. Even though this is an actual part of Classify, it is also an excellent example program. » Songs The songs project shows a number of Classify structures using a CD and record database as the example. » Sample II A small “artificial” project that illustrates a number of techniques such as: ° Activating/deactivating zooms “on command” based on contents of the database ° One to one relationships ° Read ASCII file to create records in the database using back- ground subsystems

The next paragraph will discuss in detail which files go into which directories.

Pag. 3.3 March 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 3: The environment Classify

3.1. Classify The main Classify directory contains all the files needed to (pre)com- pile Classify. This paragraph gives you a quick run down on the file to expect in the separate directories.

3.1.1. Data (DAT) This directory contains the filelist and all data files for Classify (including the TAG files). Classify reserves 20 files for system-use, in the range of 230 to 250. Although this might seem much, espe- cially the normal table file (the table concept will be discussed in detail in the chapter about the data dictionary) will save you a lot of other lookup files.

In the Classify System Maintenance Handbook, you will find more information about these files, here we will just list them briefly. » Errors Classify has its own error file. This file includes both errors and warnings and contains all DataFlex errors as well. HDSERR, number 250 » Limited tables This file contains the limited tables HDSLMT, number 249 » User file This file contains a list of user ID’s. If you have multiple applica- tions with the same users, you might want to place this file in a ‘central’ directory where everybody can access it. HDSUSE, number 248 » File access This file specifies the access rights to data files per user HDSRGT, number 247 » Help descriptions This is the file with short help-text. This file is also necessary for normal operation. HDSDES, number 246 » Help references This is the cross-reference file for the help system. Only required if you use the help system. HDSREF, number 245 » Help text The actual help texts. This file is compressed and only needed if you activate the help system. HDSTXT, number 244 » Normal tables The file holds the header for normal tables. HDSTBL, number 243 » Normal table contents This file contains all the entries in normal tables. HDSTBC, number 242 » System file This file contains information for the synchronisation feature of Classify. HDSSYS, number 241 » Configuration file This file holds configuration information for zooms and views. HDSCFG, number 240 » Zoom location The user-specified zoom-locations are stored in this field. HDSZM, number 239 » External programs The programs showed in the ‘Externals’ option of the Desktop pull down are specified here. HDSAPP, number 238 » Buttons & Menus Classify stores all the button-and menu-information in this file. If needed, both buttons and menus can be specified per user. HDSMEN, number 237

(c) '92 - '95 Calvin Consultancy March 1995 Pag. 3.4 Chapter 3: The environment Classify Handbook Classify

» General text file Classify has a special class that allows you to link a text-field to any existing file using a special zoom class. This means that you can use this file to replace a number of text-field definitions in different files, which will result in a decrease of memory usage. HDSINF, number 236 » Log file This file contains log information (usage is optional, see appen- dix G). HDSLOG, number 235 » Constrain set details This file is used by the alternate constrain system, found in the MISC directory. It is not used for regular Classify operations. HDSCOND, number 234 » Constrain set Also used by the alternate constrain system HDSCONS, number 233 » Device information This file contains data for the output selector implemented in Classify. HDSDEV, number 232 » Printer information This file contains the printer definitions used by the output selec- tor. HDSPRN, number 231

3.1.2. Images (IMG) In the image directory, you will find two types of files. First of all, you will find all Classify specific images here (.IMG). Secondly, you will find a number of include files (.INC). The reason to place include files in this directory is because these include files will contain language specific information, just like the images.

All constant strings used in Classify are contained in separate include files. These files contain statements like

#REPLACE @_Cancel “Cancel”

Whenever we need to specify “Cancel” (like in a button bar), we will use @_Cancel instead. So if you want to replace “Cancel” with “Abort” in your application, you should change the above line to:

#REPLACE @_Cancel “Abort”

And of course, you would need to do a full re-compile.

3.1.3. Packages (PKG) In this directory you will find all Classify packages. In the installation notes, you will find directions as to which files you should pre-com- pile to get the main part of the Classify functionality. In this manual, you will also find a number of references to packages.

A lot of the packages found in this directory contain classes that are either used internally or are meant only for subclassing. After follow- ing the installation notes, this directory will also contain the Classify pre-compiled files.

You will also find a number of include files in this directory. This include file contains some new commands and a number of con- stants we use in the classes.

The packages are distributed over three separate sub-directories: » All All packages common for both character mode and GUI versions of Classify » WIN All packages specific to the GUI versions of Classify.

Pag. 3.5 March 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 3: The environment Classify

» CM All packages specific to the charactermode versions of Classify.

Important: Classify does not require any FMAC modifications. However, the Classify macros do implement a couple of new key words, specifically: » Field » FileField » Exp

3.1.4. File definitions (DEF) We will supply only the .FD files for all system files. If you want to have the .DEF files as well, you can create them using DFMAINT.

3.1.5. Sources (SRC) This directory will contain any source files.

3.1.6. Documents (DOC) This directory will include any available documentation files. These will consist of the readme files, upgrade notes and in the subdirec- tory VENTURA the electronic form of the en-user manual.

3.1.7. Environment (Env) This directory should contain the configuration files for the applica- tion. More specifically, this directory will contain the INI-fiels.

3.1.8. WorkBench generated If you use the WorkBench to generate your source code, you can (WBG) use directory as the destination directory for the generated pack- ages. If the majority of the code will be generated by the Workbench, you could also use the specific directories to keep down the directory size. But if you will have a larger number of files that are coded manually, it will be more convenient to store all “standard” generated filesinthisdirectory.

3.1.9. WorkBench special If there is some need to modify the generated files, you can move (WBS) these files into this directory before making the alternations, to avoid accidental loss of changes when you regenerate.

3.1.10. WorkBench definition This directory can hold the actual WorkBench files for this project. (WBD) These data files are part of the WorkBench and should not be confused with the data files for the project in DATA.

3.1.11. Compiler output (CMP) With the introduction of DataFlex 3.05 Data Access also introduced a new FLX file format. This was necessary to accommodate the new capabilities of the runtime (higher limits). This did mean that as a developer, we needed to start working with two different types of FLX files. The Windows product again introduces its own FLX files.

This means that we need to deal with up to four different compiler outputs. To make this easy to manage, we have created a separate directory per “DataFlex sex”, grouped inside this directory. We have designated the pre-3.05 versions as “16" and the 3.05 versions as ”32", while the “c” indicates character mode and “w” indicates the GUI version.

All compiler output files (FLX, PRN, PKI, FLP and PRP) should be placed in this directory. We also have stored the USAGE.INC file in this directory since this file can be different for the different versions of DataFlex.

3.1.12. User (USR) This directory is a container for development directories per users. We will always copy any part of the system to a separate directory per user. Only if the part is finished and tested, the new code/file is distributed to the appropriate directory.

(c) '92 - '95 Calvin Consultancy March 1995 Pag. 3.6 Chapter 3: The environment Classify Handbook Classify

Initially, this directory is empty, but you will need it in order to follow the installation instructions.

In USER itself, we never have any files. Just subdirectories per user (John, Kees, Peter). We will copy any files we are working on (or which will be affected) to this directory and than distribute them back to their original directories once we have tested them. This allows all users to keep on working with a “stable” version while testing for new features is going on.

3.1.13. Miscellaneous (MISC) This directory can be found in the installed CLASSIFY directory, but it is not listed in the diagram because it is not an “official” part of the Classify directory structure. We use it to store some “goodies” that are not an official part of the (supported) Classify packages but can help you in developing your applications.

Currently, we have the following things stored in the MISC directory: » MEMAC This subdirectory contains a set of Multi-Edit macro’s to create classes, objects and procedures / functions. » TOOLS A set of small classes with several uses. One of the more convenient packages is TREES.PKG (pronounce: trace). This file can be “used” inside the desktop object and will replace the Ctrl-F1 version info with a prompt object displaying information about the current data entry object. » CONSTR This subdirectory contains an alternate constrain subsystem that utilises an extra data file to function as a sort of “batch index” with build in constrain options. This is expecially nice if you occasionally need to select a small percentage of a large data- base or need to sort on “special” criteria. » BATCH.DOS This directory contains a number of DOS files you can use as a template to setup your own development environment. The files are discussed in a seperate chapter. » BATCH.OS2 The same batch files, but now written for OS/2.

3.1.14. Other configurations The above structure is a recomendation. You are free to use any directory structure you want. You can also avoid the use of relative locations and design a batch file that references a specific project directory.

Pag. 3.7 March 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 3: The environment The projects

3.2. The projects The project directories follow the same structure and contain roughly the same information. The data directory will contain the filelist, system (classify) files and application files. The package directory will contain the data dictionaries, zooms, views etc. The image directory will contain all image definitions.

If you start a new project, you will have to decide which ‘Classify files’ you’ll want to copy to the project area, and which files you want to store in a common area.

In general, we will keep the externals and the user file in a central location (along with HELPSYS.FLX, all INI files, the CID files and SYSTEM.FLX). All other files are kept local to a project. However, you could also decide to create one large set of system files. Both the table files and the error file contain a ‘grouping’ mechanism. And the helpsystem is based on pID (which you can assign freely) and filename. If possible, keep them unique over all your applications: it might actually cut down on maintenance costs and makes it easier to share data files (and classes) over multiple projects.

And as always, it is also quite possible to make a mix of these approaches. This is just another one of these situations where carefull planning will pay off.

There is no need to copy the Classify DEF-files into the DEF direc- tory. All files are opened in the pre-compile. Only if you should decide not to pre-compile (not recommended), you would need those files.

If you use the Workbench as well, you should copy the “empty” WorkBench project to the WB_Def directory.

Important: You can also decide to use a different structure for your projects. Classify does not rely on a particular structure.

(c) '92 - '95 Calvin Consultancy March 1995 Pag. 3.8 Chapter 3: The environment Classify Handbook Batch files

3.3. Batch files We have provided a number of example batch files.You can modify these batch files to fit your own requirements, or you can use them as examples for your own files. The batch files can be found in Classify\Misc\Batch.Dos and Batch.OS2

All batch files assume a structure as listed on the first page of this chapter. They will not work “out of the box”. You will have to adapt them to your own environment.

The two files you need to modify are CL_SET and GO. Look for the text “MODIFY HERE” to find the place to make your modifications.

The files require an environment variable “USER” to be set to the initials of the current user.

3.3.1. Set up Classify (CL_SET) This file sets up the main environment settings. It identifies the location of Classify, the development environment, the WorkBench and DataFlex.

In this file, you will have to specify the directories where your DataFlex and Classify files are located. If you are working in DOS, youwillhavetouseSUBST or MAP to map these directories to a single drive. Otherwise, the DFPATH statement will not fit in the space allocated by DOS.

3.3.2. Go to a project (GO) This batch file will change the current directory to the user directory in the project specified. In DOS, it will also create a mapping for the project. In OS/2, this is not necessary.

3.3.3. Run a program (CL_RUN) Runs a program. The batch will setup the path for runtime operations and then start dfrun.

3.3.4. Compile a program This program sets up the environment for the compiler and specifies (CL_COMP) the specified program. No extension is required.

3.3.5. Test a program (CL_TEST) This program compiles a program and runs it if the compilation is succesfull.

3.3.6. Run WorkBench (WB) This batch files runs the Classify workBench. The first argument is the name of the project. If the second argument is “RPT”, it will run the report program for the WorkBench

3.3.7. Create new project This batch file will create a new project of the specified name and (CL_NEW) copy the necessary files into it.

Pag. 3.9 March 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 3: The environment Environments settings

3.4. Environments Before you can start using Classify, you will need to set up your environment. How you should do this depends on your operating settings system. However, we have a set of guideline that will help you to configure your system. » If you use relative path-names, it will be able to switch projects just by changing directories. We always base all path-settings on the fact the we work in a user-directory. » Please take care to include the following directories in your path in the correct order: ° current directory; ° other directories of the current project (relative); ° Classify PKG directory; ° Common directory for data and system files (HDSUSE, SYS- TEMA); ° DataFlex directories; ° if you don’t intend to use the help-system of the standard DAC utilities, you can omit the Help path. » If your path is too long, you might be able to use aliasses or drive substitution (SUBST, MAP) to shorten it. » If you have a ramdrive available, you might want to copy CLASS- IFY.PKI, CLASSIFY.FLP, FLEX.CFL, DFCOMP.EXE and DFRUN.EXE to the ramdrive and insert a reference to the ram- drive just before the reference to CLASSIFY\PKG. DFPROG should point to the ramdrive. This will increase performance considerably, especially for the compiler. » All development and testing should be done from the individual user directories. All sources and/or packages to be changed must be copied to this directory. Only when all is tested and approved, it can be distributed to the appropriate directories. » We suggest you always compile using both the S and the F options. This will provide you with readable error messages and with an output file that is real handy to track down errors.

(c) '92 - '95 Calvin Consultancy March 1995 Pag. 3.10 Chapter 3: The environment Classify Handbook Classify INI files

3.5. Classify INI files Classify uses a number of INI files for system and user configuration. The following INI files are used: » CL_MAIN.INI This file contains the general setup of the environment. The name of this file is fixed and cannot be changed. » CL_COLOR.INI This file contains all color palettes. The name of the file can be changed by altering a setting in the CL_MAIN.INI file » [USER].INI Every user can have its own INI file. The name of the INI file is specified in the standard Classify user file. If you do not specify an INI file, it will use the first 8 characters of the username by default.

The INI-file maintenance program (in SYSTEM, under reports) dis- plays on-line documentation for the settings. These definitions are specified in the CL_MAIN.CID, and USER.CID files, so you can easily translate or extend the files.

We have decided against documenting the INI files in this manual because the main reason to move towards INI files is the ability to extend them quite easily. We wanted it to be as easy to extend the documentation.

Pag. 3.11 March 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 4: Overview

4. Overview This chapter will give you a global overview of Classify and how applications will be built using Classify. If you are not familiar with the terminology we use (key, foreign key) we strongly suggest you to go over the Glossary as well.

We will give you a graphical layout of a Classify program with its main elements and the files they are stored in, as well as a short outline of the naming conventions we have used.

(c) '92 - '95 Calvin Consultancy March 1995 Page 4.1 Chapter 4: Overview Classify Handbook History

4.1. History Classify was initially conceived as a set of corporate development guidelines. But it turned out that just defining the standards was not enough. We also needed to supply a set of classes that would make it very easy to comply with these standards.

As the work on these standards progressed, we came to the conclu- sion that a lot of “common sense programming” had been put into these classes. Given the Object Oriented (OO) principles of encap- sulation and information hiding, we felt that we could make a lot of our work available to other .

We, therefore, extended the standards until they were complete enough to be marketed to others as a front-end developer’s platform.

Classify represents about 3 years of programming efforts and about an equal amount of manpower of designing. Although we use a number of high-end techniques (such as creation and destruction of objects), all code is 100% standard DataFlex 3.x There are no FMAC changes or runtime modifications.

Because of this, we will be able to port Classify to other platforms as Data Access ports DataFlex 3.x to them. We will also be able to comply with all changes in upcoming releases. Currently Classify 2.0 has been tested with: » DataFlex 3.04 on OS/2 and » DataFlex 3.01b on DOS » DataFlex 3.05 on DOS, OS/2 and Unix » DataFlex 3.05 For Windows » DataFlex Server Edition » DataFlex For BTrieve

Page 4.2 March 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 4: Overview Database design

4.2. Database design The database is, in general, the backbone of any large scale DataFlex application. After all, DataFlex has been famous for its reliable database manager for over the past ten years .

The contents of a mission-critical database usually is the most valuable asset of an end-user. If he has a bug in a program, he will be upset. But bad data in the database will get him really angry.....

4.2.1. Data dictionary So in the design of Classify, the foremost requirement always has been the consistency and integrity of the database. Based on this integrity requirement, we will usually start a project describing the “data dictionary”, even before we define any data entry functions.

Classify will allow you to create specific objects containing all of the information usually found in the data dictionary. Only file and field descriptions are stored directly in DF-File. Relationships can be indicated in DF-File, but can also be specified in the data dictionary.

The data dictionary objects are not “actively” involved in the file management. They are just acting as “monitors”, providing (valida- tion) services when needed. This is why there can be only one data dictionary object per file (note: this is quite different from the Data_Set from Data Access Corporation).

As was stated earlier, database integrity was one of our foremost concerns when we constructed Classify. So naturally, the data dictionary takes an important part in the design. But there are three other major components that we will discuss later on.

From an conceptional point of view, the DDO is more than just a “data dictionary”. We internally often refer to it as the “problem domain description”. All the rules and logic that has to do with the specifics of your problem domain will be specified in the DDO, not just file and field validations and options.

By doing this, the user interface modules become pure “interface descriptions” and can be easily modified. It is now also feasable to offer different interfaces to the same data (e.g. beginners and advanced), since the interface does not contain any rules or logic and adding a secondary interface does not add any maintenance effort over the maintenace of the interface itself.

From an OO-design point of view, the DDO can be viewed as the “class definition” that is found in the analysis phase. The subsystems (discussed later) can be looked upon as the “true life” objects based on these classes. However, this analogy is not reflected in the code (the DDO is an objects and subsystem are not based on the data dictionary class).

Data dictionary information is stored in objects, specified within seperate DDO files.

(c) '92 - '95 Calvin Consultancy March 1995 Page 4.3 Chapter 4: Overview Classify Handbook Data entry modules

4.3. Data entry modules We have divided data entry objects into three seperate types of “building blocks”. We will discuss these three types bottom up: from modules with the most detailed functionality to modules with a more global function.

4.3.1. Zooms A zoom is the smallest and most detailed data entry element. Most zoom objects will have an image attached to them. We will define a class for every zoom we need. This allows us to use the same zoom at several places without duplicating the code.

Every “zoom class” will also get a reuseable image definition. The zoom becomes the smallest building block in our data entry model. A zoom will normally consist of a selected group of fields from one file. This zoom will be “as small as sensible”. For instance, one zoom will contain address-fields, another will contain financial information (date last invoice, credit limit, outstanding invoices). The object of zooms is to allow the end-user to “design” his screen at runtime by selecting specific zooms.

It is possible to design multiple zooms containing the same fields (e.g. sales information could contain date of the last sale-contract, but also a credit limit, which was also in the financial zoom). Classify will automatically detect duplicated fields and “link them”, meaning a change in one of them will automatically result in the change of the other.

In our opinion, it is best to create zooms “as small as sensible” and without any additional white-space. This way of screen design is reflected in most of our system maintenance and example programs. However, nothing stops you from creating “full-screen-zooms”.

Zooms are stored in small files as class definitions (*.FND and *.ZM). Per zoom, an image definition is created and stored in an .IMG file.

4.3.2. Subsystems Zooms are only used for display purposes. The subsystem is a grouping mechanism and, at the same time, it takes care of the file handling. A subsystem always handles one file. Thus it will contain only zooms for that specific file.

A subsystem can contain as many zooms as you want. Usually there will be one subsystem that contains all the zooms (or at least a set of zooms that will present all fields). This subsystem will be referred to as the “maintenance subsystem”. The main reason to create other subsystems is to provide a different look (e.g. use zooms that have no parent information; offer less zooms). In principle you could use the “maintenance subsystem” all the time, the end-user could still select the needed zooms and thus restrict screen usage to a mini- mum, while having all other information “at his fingertips”. While this is nice during the early development stages (when still testing the data dictionaries), the final release will usually contain a number of specially tailored subsystems.

The subsystems are also created as classes and are stored in the *.SBS files. The image definitions for the subsystem (consisting of an enumeration of the zoom-images) is stored in an .IMG file.

4.3.3. Views The view is our equivalent of an “old style” program and offers the functionality to fullfill a specific task or retrieve a specific set of information. It gives you access to one or more files. Views are automatically “listed” in the function pull down. A view is a grouping mechanism for subsystems.

Page 4.4 March 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 4: Overview Data entry modules

Again, we will usually define one “maintenance view” for every file. This means that this view will only contain one subsystem: the maintenance subsystem for that file. Quite often, this view will not be delivered to the customer, but it will prove to be very handy for testing purposes.

Most views will consist of a complex group of multiple subsystems. You can mix as many related files into one view as you want (and think the end-user can still understand). In grouping subsystems, you can use both parent-child and child-parent relationships (both directions are supported).

All views are created as seperate classes and stored in .VW files. Theenumerationofthesubsystemimagesisstoredinan.IMGfile.

We look upon the views as the building blocks of our application. When we install the system, we try to build programs by combining all the views that one user might need throughout the day in one program. This will result in “custom programs” per user. But because these programs hardly contain any code, they can easily be build and they need no maintenance. At the same time, it will allow the end-user to perform all his tasks in a non-modal fashion without ever exiting the program.

(c) '92 - '95 Calvin Consultancy March 1995 Page 4.5 Chapter 4: Overview Classify Handbook Batch processes

4.4. Batch processes The next important category is batch processes. In Classify, we do not make a distinction between a report and a “true batch”. Very often, you will need to update a field in the file while printing the report, or you will print a processing list while doing batch updates.

A very important point in the design of our batch-oriented classes was that we still wanted the data dictionary to control all file updates. Another point was to make “intelligent” use of the multiple I/O channels in DataFlex. After all, with an event-driven user-interface, one can never be sure that a certain channel is, or is not, in use. For batches we currently have two building blocks as shown below.

4.4.1. Batch report This class will replace the report macro. It will process reports based on one main file.

The batch_report resembles the subsystems in many ways. The main difference is that the “parts” (header, subheaders, detail) are implemented as procedures instead of child objects (zooms).

4.4.2. Batch server Again, this is the grouping mechanism for batches. When there will be more “one file batches” than “one file views”, it is still possible to create complex, multiple file reports just by nesting batch_reports in the same way you would do with subsystems. Again, the only restriction when nesting batch_reports is that there should be some relation between the files.

All batch_servers will automatically be listed in the report pull down.

Both batch servers and batch reports are stored as classes in .BTC files.

Page 4.6 March 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 4: Overview The desktop

4.5. The desktop The last area of interest that we will discuss is the desktop. We created our own desktop class and we will require a desktop object to be defined for every program since we use the desktop both as communications officer and as swiss army knife.

4.5.1. Communications Obviously, subsystems and batches must have a way to communi- cate with data dictionaries. Also, data dictionaries must be able to communicate with each other (if one file affects the other). Since we wanted to have a modular design, specifying the names of these objects was out of the question. The desktop object takes care of the task of setting up communications between all these objects. However, once a communication path is established, we will use direct communication for speed reasons.

4.5.2. The Swiss army knife If you ever used a Swiss army knife, you will know that you can take apart a car and put it back together again without any additional tools (although you will need a good memory to reassemble it). The desktop is our equivalent of the Swiss army knife. It will take care off all kinds of jobs. Some of the tasks which are taken care of by the desktop: » Error handling (including error logging). » Generation of the action bar and pull down menus (based on views and batch servers). » User authorisation and configuration. » Mouse buttons. » Picklist (taskmanager). » Management of output channels. » All general pop-ups. » Helpsystem. » Title. » Context-sensitive helpline. » Execution of external programs. » Editor, calculator and calendar.

Most of the actions of the desktop are totally transparent. Other functions can be called by the developer (e.g. the error handler).

The desktop is created in the .SRC file and will contain the object definition for the desktop, the views and the batches.

(c) '92 - '95 Calvin Consultancy March 1995 Page 4.7 Chapter 4: Overview Classify Handbook The program structure

4.6. The program The following diagram gives you an overview of the structure of structure Classify programs.

Desktop (PKG)

Data dictionaries (DDO)

Views (VW)

Subsystem (SBS) Subsystem (SBS)

Find (FND) Find (FND)

Zoom (ZM) Zoom (ZM)

Subsystem (SBS) Zoom (ZM)

Batchserver (BTC)

Batch report (BTC)

Batch report (BTC)

Batch report (BTC)

Batch report (BTC)

Mostoftheelementsinthispicturecanoccurmultipletimes.The average program will contain multiple data dictionary objects and usually either multiple views or multiple batches. In principle, you can combine both batches and views but most people prefer to keep them in seperate programs.

The structure shown is the object structure. In brackets, we have indicated the file-extension of the file where the classes are speci- fied. This also means that a one program is “assembled” from a large number of source files. Classify projects will use many very small source files. This will help you in keeping modules easy to maintain and to eliminate duplication of sources.

The next page shows the same object structure, but now drawn as a tree structure and listing the base classes to use. The dotted lines show automaticly created child objects (e.g. the entry base, which actually is only used in Windows). There are other automatic child objects as well, but these are not relevant for the program structure (e.g. arrays, errorhandler).

Page 4.8 March 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 4: Overview The program structure

1 Desktop

2 View

3 Subsystem

8 63 4 Batch Server Dummy zoom Zoom

9 Batch Report 7 5 3d textbox Entry base

10 Data Dict.

As you can see, both batch reports and subsystems can be nested withing objects of the same type.

(c) '92 - '95 Calvin Consultancy March 1995 Page 4.9 Chapter 4: Overview Classify Handbook The class tree

4.7. The class tree Classify is a class library with a total of over 100 classes. Luckily, as a developer you will only be dealing with a relatively small set. The following two diagrams show the class hierachy for both the character mode producted (including many of the Windows classes) and a set of Windows specific classes. Both diagrams concentrate

Character mode & Common classes

18 29 55 Entrylist DFEntryList Common zoom

cter mode ws

20 Zoombase 19 Dummy zoom

21 30 Field base Tabsel

23 22 Table zoom Entry memo

24 49 Zoom form Bitmap Zoom

28 26 25 Entry_Zoom Entry find Entry_Base

27 Multi line find

Classify 4 Windows classes

56 54 59 fxClient DF Dialog Base dialog Mixin

57 58 Zoom dialog Common zoom mixin

50 Zoom Dialog

51 52 53 Field base Entry zoom Entry find

61 62 60 Table zoom Bitmap zoom Multi line entry

on the data entry related classes, since these have the highest level of complexity in the class hierachy.

We have listed these diagrams both to give you insight in the internal structures of Classify and to provide you with an example of a class hierachy.

Page 4.10 March 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 4: Overview Naming and program style conventions

4.8. Naming and Classify does not require you to use any naming conventions. Also, there are no special requirements about program layout. However, program style while you are working with Classify, work through this manual and conventions maybe look through the source, you are bound to run into our naming conventions and styles.

To make you feel familiar with these conventions, we have included them in this chapter.

4.8.1. Naming conventions The most obvious part is of course our naming conventions. In this paragraph we will discuss the different names and the conventions we use for them.

4.8.1.1. General guidelines All names should be english and comprehensive. The use of cryptic names should be avoided. If the name requires multiple words, the words are seperated using underscores (“_”).

If a prefix is required, there will be no seperator between the actual name and the prefix. The prefix will always be lowercase. All other names and key words will have one capital and undercast for the rest of the word.

4.8.1.2. Objects Object names have the prefix “o”. The object name should be descriptive for the object. In general, the name of the class will not be repeated in the object name, unless this is necessary for the name to be descriptive.

Good: Object oCustomer_List is a cGlobal_Lookup_List Object oOrder_Entry_View is a cOrder_Entry_View Object oCriteria_Selector is a Form

Bad: Object oCustomer_Global_Lookup_List is a cGlobal_Lookup_List Object Order_Entry_View is a cOrder_Entry_View Object oCrit_Sel is a Form

4.8.1.3. Classes Class names will always have the “c” prefix. Like object names, the name should be descriptive and will in general not include the name of the parental class.

Good: Class cCustomer_List is a cGlobal_Lookup_List Class cOrder_Entry_View is a cView Class cCriteria_Selector is a Form

Bad: Class cCustomer_Global_Lookup_List is a cGlobal_Lookup_List Class Order_Entry_View is a cView Class cCrit_Sel is a Form

4.8.1.4. Messages DataFlex supports three types of messages: service requests, re- trieval of values and setting values. These messages are sent by respectively SEND, GET and SET. The prefix we use for these message types are “m” for service requests and “p” for both retrieval and storage of values.

If a service request needs to return an errorcode, it is treated as the retrieval of a value (in this case: the errocode) and will be named accordingly.

The name should be descriptive for the functionality of the message.

Good: mAdd_Option mDisplay_Prompt pValidate_All_Fields pCurr ent_Date

Bad: mCurrent_Date pMove_Down mDo_It mCPCT

(c) '92 - '95 Calvin Consultancy March 1995 Page 4.11 Chapter 4: Overview Classify Handbook Naming and program style conventions

4.8.1.5. Properties We treat properties as a combination of a functions and a procedure set. Hence, the naming is identical to that of the get & set messages (p-prefix).

4.8.1.6. Variables Variables have no particular prefix or naming convention, except for the general guideline that the name should be descriptive for the contents.

4.8.1.7. Images If images get named, the name of the image will always be the same as the name of the object that will get attached to the image.

4.8.1.8. Files The naming conventions for the package files are discussed in the chapters concerning the specific types of files.

4.8.1.9. Constants All constants have the at-sign (“@”) as a prefix. String constants, essential for translation have only the at-sign. Symbolic constants have an underscore as well (“@_”). Names should be descriptive.

Good: @Please_Wait @_Capslock

Bad: @_Scanning @Start_Of_Data @_SOF

4.8.2. Drawing conventions We have standarized on ABC-Flow Charter as drawing tool. The reasoning behind this is that it allows great freedon in the design and does not constrain you by its internal definition of “allowed” relation- ships. It also provides a low-cost solution suitable for smaller com- panies and medium sized projects. In special situations we also use other design tools.

In the following diagrams, we have listed the standard drawing conventions we use for your convenience.

68 69 Normal Data file table

70 74 75

Many (>= 0) Many (>=0) Many (>0)

71 73 76

One Zero or one One

81 79 89

Zero or one One

dency Dne ep 82 80 90

One One

87 88 84 85

One One One One

tional relation tional relation d iC d n on 86 83

Many (> 0) Many (> 0)

Page 4.12 March 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 4: Overview Naming and program style conventions

31 35 Class Object

46 Mixin Class

32 33 64 Parent 1 Parent 2 Container object

34 65 Conditional Child object inheritance

36 37 66 Super class MI-Class Container object

38 67 Inherit Class Automatic child protocol All (class defined)

36 37 Super class MI-Class

38 Inherit Class protocol Some

47 Parent class

48 Regular inheritance

4.8.3. Programming guidelines Guidelines are just guidelines. Especially when it comes to program- ming style it is very hard to set fixed rules. Nevertheless, we formu- lated a couple of guidelines: » Indentation: 4 spaces. » The only valid command after an IF or ELSE statement is BEGIN. If a begin/end construct is not required, we will put a semicolon (“;”) after the IF or ELSE and put the command on the next line (indented). » Put only one class in a package. » Use one FUNCTION_RETURN or PROCEDURE_RETURN per procedure or function. The only general exception to this is when the procedure or function ends with a simple if statement and each branch contains a diffrent return statement. » Never use globals. If globals are necessary (e.g. the FOUND indicator), the value of the global should be used in the line immediately following the line determining the value. If the value needs to be preserved, it should be stored in a local. » If you need string constants, specify them using the #REPLACE syntax and put the replace statements in a seperate file in the IMG directory. » If two or more message have the same name, the functions should provide the same functionality and the type and number of arguments should be the same (of course this also applies to augmentation). » All functions should be typed (RETURNS TYPE). » Objects can only be addressed when it is a child of the current object or through indirect access. » Objects should not contain procedures and or functions. A gen- eral exception to this is the data dictionary object because by design, there can only be one data dictionary object.

(c) '92 - '95 Calvin Consultancy March 1995 Page 4.13 Chapter 4: Overview Classify Handbook Classify is DataFlex

4.9. Classify is DataFlex As a final chapter in this overview, we would like to stress one important fact: Classify is DataFlex

This might sound a bit obvious, but we find that many people think that “standard” programming techniques no longer apply once they start using Classify. This is not true!

Classify just adds new classes to the set of pre-defined class definitions. All other classes are still available. All properties and messages inherited by the Classify packages are still available.

So if you would like to initialize a zoom object whenever the user enters the zoom, you can still use the ENTERING procedure as you would with an ordinary form. If you want to change the color of a specific window, you can use WINDOW_COLOR as documented in the reference guide.

If you feel you need a class that isn’t provided by DAC or Classify, you can just create a new class and base it on any predefined class (internal, packages or Classify).

Page 4.14 March 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 5: Using Classify

5. Using Classify This chapter contains some essential information about using Class- ify. Even if you are an experienced DataFlex 3.0 , please take the time to read through this chapter. It will help you to start building your first Classify application.

This chapter will not give you code examples, you can find these in the Classify Handbook. It is meant as a guide line how to get to a working application. At the end of each chapter you will find a “checklist” of steps to perform.

Classify is a extensive class library. Most of the classes provided witin this library are designed to provide an . This means that there are a number of classes designed to provide a specific functionality for a certain aspect of an application (e.g. data entry, menu’s, batches) and that all these classes work to- gether. This also means that you can use these classes seperately, but that they will not provide the full functionality in that case. There even might be cases where they do not work at all without the necessary interaction with other classes.

On the other hand, it also means that you can use any other base class together with Classify. However, if you want them to work together with the other Classify classes (like having a “vanilla” view appear automatically in a Classify menu), you will have to provide some additional communication messages.

All the “standard” messages you can use to build a system using only Classify classes can be found in the upcoming chapters of this handbook. In the reference guide you will find all the other messages as well (including the messages supporting the framework commu- nications).

(c) 1992, 1993 Calvin Consultancy June 3, 1996 Page 5.1 Chapter 5: Using Classify Classify Handbook

5.1. Set up Classify While Classify installs in a particular directory structure, it is not mandatory to keep this structure. There are no pathnames in any part of Classify and all the files are located by means of the DFPATH environment variable.

We do not want to force you in using a particular structure, but we have found that the suggested structure works very well. The biggest advantage we found is that by using relative path settings, we can easily switch projects as well as swicth from actual development to the Classify WorkBench just by changing the current directory.

We very strongly suggest that you follow the suggestions given in chapter 3 untill you are more familar with Classify and you can set up a structure to match your own preferences.

To start a new project, you must create a new set of subdirectories, similar to the structure Classify is installed in (see chapter 3) and copy the contents of the DATA directory from the Classify area to the DATA directory of the new project.

This will give you a private environment for this project. You might consider to not copy the user and externals files (HDSUSE.* and HDSAPP.*) and keep them common for all your projects. In that case we suggest you first move them from the Classify DATA directory to the Classify FLX directory. The latter is always accessable if you follow the path recommendations and you will not have to exclude them manually every time when you create a new project environ- ment.

Step by step » Install Classify » Setup a path as recommended in chapter 3 using relative paths » Create a new project environment » Copy all the files from the Classify DATA directory to the project DATA directory

Page 5.2 June 3, 1996 (c) 1992, 1993 Calvin Consultancy Classify Handbook Chapter 5: Using Classify

5.2. The problem domain If you do an analysis of a particular problem domain, you will come up with a set of class definitions for that problem domain. For instance, the analysis for a sales system might produce the following classes: » Customer » Salesperson » Article » Sales information » Sales details

For each class, you will have a list of attributes, such as: » Customer ° Customer Code ° Name ° Address ° Credit limit ° Discount » Sales details ° Sales number ° Product code ° Nr of products ° Standard price ° Invoiced price

All of these classes will have a set of standard operations such as: » Create new » Delete » Update

And some classes will have specific additional characteristic such as: » A customer can only be deleted of all related information can be deleted as well » Sales information can only be deleted nine months after final payment » There is a relationship between sales information and customer through the Customer Code attribute in sales information » The standard price from sales details is retrieved from the current price stored in the product information. » The invoiced price can be specified by the sales person but the default is calculated by subtracting the standard discount stored in the customer information from the standard price.

In your analysis, these should be grouped by class like this:

Customer class The customer class reprsents the collection of entities that purchase products from the organisation for which this analysis is done. Customers can purchase all sort of articles. Apart from the obvious order-flow, there can be several other contacts with customers, such as support calls, mailings, special offers and after sales service. » The customer class provides us with the following information about a customer: ° Customer Code ° Name ° Address ° Credit limit ° Discount » The customer is uniquely identified by customer code. » The customer code should be capslocked at all times. » Credit limit should be a positive number. If a figure over 100.000 is specified, the user should have “manager level”. » Duiscount should be between 0 and 99 percent.

(c) 1992, 1993 Calvin Consultancy June 3, 1996 Page 5.3 Chapter 5: Using Classify Classify Handbook

» Customers can be created, deleted and the information can be changed. To delete a customer one should be possible to delete all related information as well. » The customer has a relationship with sales information. » There should be a special function to provide “Check credit” which will have one argument (amount) and that should return true or false to indicate whether the specified amount falls within the specified credit limit. To determine this, all the outstanding invoices should be totalled and compared with the specified credit limit. If the remaining limit is less than the specified amount, the return value shopuld be “false”.

Once you have a full description of all the classes, you are ready for the first step in the construction of your application. Note that it is not necessary to specify screen layouts, menus or program struc- tures at this point. At this stage, we are only dealing with a descrip- tion of the actual problem domain. The big advantage of this is that usually, the description of the problem domain is more stable over a long period of time than the data-entry and presentation require- ments.

The data dictionary class provided by Classify offers you a “tem- plate” that can be used to describe the problem domain. This means that you will create one object based on the data dictionary class that acts as a “role model” for the real life objects as found in the problem domain. So for instance, you will create one “customer data dictionary object” listing all the characteristics of the above descrip- tion of the customer class.

The attributes needed for the class (or rather those attributes that needs to be stored) will be specifieds as fields in a file that will be linked to this particular data dictionary object (DDO). Attributes such as “credit available” which is merely a calculation using “credit limit”, “outstanding orders” and “outstanding invoices” will not be specified as fields (redundant information) but rather as functions within the DDO.

The two most important settings for the DDO are the link with the data file (pMain_File) and the index that contains the key (pMain_In- dex). If there where no special conditions or rules involved, this would be the complete DDO.

Next, you must take all the additional requirements from your analy- sis document and implement them in the DDO. Some can be imple- mented quite easily; just by setting some properties. For instance, setting up relationships and orphan-control can be done just be setting some pre-defined properties (pDelete_Range and pOk_To_Delete_Range) and sending a pre-defined message (mAdd_Child_File). Other requirements might result in the need for custom written functions. Usually these new functions should be linked to a trigger by setting pre-defined properties (pOk_To_Delete, pOk_To_Save, pAfter_Save_Msg etc.).

Inside the DDO, you can also specify attribute specific requirements that go beyond the standard field definitions (type and size). These additional characteristics include features such as entry options (mAdd_Option), field related messages (pField_Message) and table validation (pTable_ID). The field messages again might require you to build custom functions to perform the validations.

The final part of the DDO is the setup of the “dependencies”. A complete discussion of this concept can be found in paragraph ### but in short it concerns the automatic updating of redundant infor- mation.

Page 5.4 June 3, 1996 (c) 1992, 1993 Calvin Consultancy Classify Handbook Chapter 5: Using Classify

The DDO’s are the core of your application. They represent the business rules and specific characteristics involved with the problem domain being automated. Once the DDO’s are finished, the main part of the programming is done.

In general, there are two ways of building DDO’s: » Build all DDO’s before you start on data entry and batches This follows the way you will design the system. After you com- plete the analysis, you will further formalize the analysis by creating the file definitions and the DDO’s for them. You can setup all the inter-class relationships and besically complete the core of the system. The only disadvantage is that there is no way to “test” the DDO’s seperately. » Build DDO and data entry per class and testdrive it first Especially if you are not yet very experienced, you might prefer this approach. You first build a “basic DDO” and than build a simple data entry module for that class. Now you can extend the DDO with all the field-related specifications and test them in- stantly. Once you have finished DDO and test programs for related classes, you add the code to the DDO to specify the relationships and test these. While this strategy reuires some going back-and-forth between the DDO’s and also requires early construction of data entry modules, many people find it a good way to get acquinted with the features of Classify.

In general it pays to specify all the error messages and validation tables as soon as they are used. Also, if you value documentation, you will find that it is good to enter the file & field information into the help system right away.

Step by step » Do an object oriented analysis » Create a file definition per class, containing all the attributes that can not be derived (or can be derived but need to be accessed immediately while derivation would cost to much time like total- outstanding-invoices). » Create the base DDO » Novice ° Build a data entry module (see next paragraph) ° Test base DDO ° Extend DDO with field & record characteristics ° Specify error messages (if necessary) ° Specify validation tables (if necessary) ° Continue with DDO’s for related files ° Add & test specification for inter-class relationships once seperate DDO’s are tested ° Enter the file & field information in the help system » Advanced ° Complete the DDO by specifying ° record-specific characteristics ° inter-class relationships ° field characteristics ° Specify error messages and warnings (if necessary) ° Specify validation tables (if necessary) ° Enter the file & field information in the help system

(c) 1992, 1993 Calvin Consultancy June 3, 1996 Page 5.5 Chapter 5: Using Classify Classify Handbook

5.3. Data entry & retrieval While the description of a problem domain is a constant in an organisation, the way data is presented differs from person to per- son. While there will always be a realtionship between an orderline and a bill of material, this might not be relevant to the sales person. Lets assume the following structure of classes:

Order

Customer

Product

Invoice

Payments

A customer can place orders and receive invoices. So obviously, there is a relationship between them. While in general all order will relate to a customer, we still don’t perceive the order to be a part of the customer object. This means that in this case we have a rela- tionship between two independent objects.

If we look at the definition for order, we will find that the orderline is modelled as a part of the order. The same holds true for invoice line within invoice and bill of materials in product.

One order relates to one or more products, as well to one or more invoices. Payments will always relate to a customer, and usually to an invoice as well, but that is not necessary. Since it is impossible to have a relationship from order to multiple product records, we will have to specify the relationship from orderlines to product. So make this more visable, we will draw a slightly adjusted diagram (see next page).

This diagram shows one level of detail inside the objects: a breach of encapsulation made necessary by the relational model in which thedataisstored.

Once we have defined this structure, it holds true for the whole application. Its formal description will consist of 8 file definitions and 8 DDO’s describing them.

But once we come to data entry and data retrieval, we will notice that the same information needs to be presented in different formats. For instance, a sales person might be interested in “Customer informa-

Page 5.6 June 3, 1996 (c) 1992, 1993 Calvin Consultancy Classify Handbook Chapter 5: Using Classify

Order

Order lines

Customer Product

BOM

Invoice

Payments Invoice lines

tion”, consisting of the information about the customer object, order informartion (including the orderlines) and invoices (just the head- ers). His primary entry point in this will be the customer information. Graphically, the sales-customer view could be presented like this:

Customer screen Name Orderheader screen Address Order date City Order total Telephone

Orderdetail screen Product Amount

The whole structure (dark grey) is devided in a customer screen (white) and a sub-structure for orders (light grey). This is devided in the orderheader screen and another sub-structure for orderlines, which has one part: the orderline screen.

If we look at this data entry module as an object, the display objject for the orderheader is a part of the whole customer-information object, while the order information is no part of the customer object in the problem-domain descriptions.

Also, the person in the financial department will request “Invoice information” containing information of invoices, payments and cus- tomers. We see the structure for that view in the following diagram. Note that it contains two “payment” screens: one showing only the payments relating to this invoice and one showing all payments related to the customer that is related to the invoice.

(c) 1992, 1993 Calvin Consultancy June 3, 1996 Page 5.7 Chapter 5: Using Classify Classify Handbook

Invoice screen Date Orderline screen Amount Amount orderline

Customer screen Payment Screen Name Payment Date Address Date Amount Telephone Amount

So for this data entry object, customer is a child of invoice, and payment is both a child of invoice and of customer.

We see that the object model of the “application” is not a one-on-one representation of the problem domain. You will also find that the requirements for these objects change more rapidly than the object model of the problem domain.

We also see that the same elements are used over and over again. But they are used in different ways. For the sales person, customer is his main interest and the orders and invoices attached to this customer are secondary information to customer. For the financial department, the invoice is the primary information while the cus- tomer is only of secondary important. The production manager works with the same orderlines as the sales person and in both cases they are sencodary information. But in the first case, the orderline is used to show why something should be produced, while in the second case is displaying what some customer ordered.

These building blocks of information are called subsystems in Classify. And like the above drawings, Classify allows you to place subsystems inside each other. The subsystems will determine this contents and automatically act out the “correct role” displaying the right sort of information.

The combination of a set of subsystems presenting a specific view of the information stored in the system is called a view.

Obviously, subsystems must be constructed before a view can be constructed, although usually the views will be designed first.

Subsystems in Classify again are not build as one solid block. Instead, they are compositions of smaller components as well. Lets assume customer information for instance. It can be devided in several parts: » Customer identification (Code, Name, Debtor number, City) » Name (full name, pre- and suffix) » Address (street, city, state, country, zipcode) » Sales information (discount, sales representative, payment terms, last order, next contact, telephone number, fax number) » Financial information (credit limit, outstanding invoices, out- standing orders) » General information (legal status, number of employees, esti- matedturnover) » Telecommunications (telephone, fax, telex, modem)

Page 5.8 June 3, 1996 (c) 1992, 1993 Calvin Consultancy Classify Handbook Chapter 5: Using Classify

These parts are called zooms in Classify. Note that the same items can occur in multiple zooms (e.g. telephone number occurs both in tellecommunications and in sales information; city occurs in address and customer identification).

The subsystem containing all the zooms is called the “maintenance subsystem” because it always you to change any attribute of a customer. But you could create multiple customer subsystems mak- ing different combinations of zooms. This depends on the require- ments of the views you need to build. Since the construction of zooms, subsystems and views is very easy, we tend to taylor them to each end user or task.

The key benefit of a framework approach like Classify is that the zooms, subsystems and views will automatically communicate with the DDO’s. This means that a zoom will be merely a list of attributes, a subsystem is a list of zooms and a view is a combination of subsystems. All the rules about how they should work together, what validations should be performed, what other files should be updated are all taken care of by the DDO’s.

The benefits are obvious: » the builder of the data entry modules doesn’t have to worry about these topics nor can he accidently corrupt the database; » the code for these modules is ultimately simple and can be changed easily to fit changing requirements; » modules can easily be taylored for maximum userfriendlyness, almost up to a module-per-user level without decreasing main- tainability.

We would even expect this part of the application to become end- user driven in the future. The DDO’s would still control all the data, but the user should be able to design his own data-entry programs.

Again, obviously a zoom needs to be constructed before the subsys- tems can be build, although again the design will first identify the subsystems (customer-information-subsystem; full-customer-sub- system; financial-customer-subsystem) before the zooms will be identified.

So for our data entry programs, we find a programming approach that is reversed when compared to the design: design is top down while construction is bottom up. Again, this illustrates how close object orientation matches the real world. Almost any other task will be tackled by doing the global design first, but once we need to start building, we first need to construct the smallest components.

You will also find that identifying subsystems and zooms almost comes naturally from using natural language in your design: no- body will talk about “street, zipcode, state, country”, but everybody will talk about “address information”.

The final step is to combine a number of views into a program so that every person has all the views he needs at his fingertips. Usually, the list of “required views” can also be deduced from the interviews with the potential users. And again, we tend to almost build the programs to the specification of each individual user so we can give him exactly the funmctionality he needs without using unnecassary resources. And again, this hardly compromises main- tainability because a program is merely a list of views.

Step by step » Identify the views needed » Identify the subsystems needed in each view » Make a list of all the subsystems » Identify the zooms needed in each subsystem

(c) 1992, 1993 Calvin Consultancy June 3, 1996 Page 5.9 Chapter 5: Using Classify Classify Handbook

» Makealistofallthezooms » List the fields needed in each zoom » Create the zooms » Create the subsystems » Create the views » Create the programs

Page 5.10 June 3, 1996 (c) 1992, 1993 Calvin Consultancy Classify Handbook Chapter 5: Using Classify

5.4. Batches Many large application also require a lot of batches. These batches can consist of “simple” reports, complex reports or batch processing of data (changing, creating and/or deleting data). Classify does not realy distinguish between them because quite often even a simple report might update a status flag, while complex batch processing might produce a list of changed records.

Since many batches are procedural in nature, object oriented analy- sis might not be sufficient for batches and “traditional” design-tech- niques might be needed. Classify provides facilities for two main types of batches: » Classify supported batches » Free-form batches

The Classify supported batches are supported by the batch server and batch report classes. They provide a mechanism similar to that of views (server) and subsystem (report), where every report class processes every record in the file and for that record performs a specified action.

If you update records in a batch report class, all the DDO control will be maintained (so a batch deleting all customers will only delete customers that can be deleted according to the rules in the DDO and for those customers, all related information will be deleted as well. If you nest reports, the nested batch will be performed for every record of the container.

For free-form batches, Classify offers just a bare container. What you do within the container is completely up to you and could be fully procedural. However, in the free form batches, Classify cannot retain the data dictionary control, so the programmer must be aware of validations and relationships!

Because of the large variety in requirements for batches, there are no fixed guidelines for this.

(c) 1992, 1993 Calvin Consultancy June 3, 1996 Page 5.11 Classify Handbook Chapter 6: Data dictionary

6. Data dictionary In general, a data dictionary is a set of rules that fully describe anything that has to do with the database, such as: » file information; » field size and type; » validation of field contents; » validation of record contents; » relationships between files; » data entry options for fields; » prompt for fields.

Example: Some examples of these rules are: » No records of the invoice file may be deleted if there is still an outstanding amount. » Whenever the ‘amount’ field in order-line is changed, it should be totalled in the order header. » If a customer record is deleted, all child records should be deleted as well. If this is not possible, the record should not be deleted (nor any children). » The field “Gender” should only accept “M” or “F” as entry. If a user presses the prompt-key, he should get a prompt list with “Male” and “Female”. » The field “Maiden name” should only be entered if Gender equals “F”. » Zipcode should always be caps-locked. » Whenever a date is entered, it should be converted to a date with a 4-digit year number.

In Classify, a data dictionary is specified per file. So, all rules concerning a particular file are grouped together. This is done in a so called “data dictionary object”. The data dictionary object con- tains all information about a particular file. It also contains informa- tion about the relationships this file has to other files.

Since DataFlex has its own file-definition utility (DF-File), the data dictionary will always inspect the file-definition and ‘inherit’ all the information specified in DF-File. But the information you can specify in DF-File is very limited, so you will find that in most cases, you want to expand the data dictionary to contain more specific informa- tion.

If all relevant information can be specified in DF-File, a data diction- ary object for a system file will look like this:

Example: Object oSystemfile is a cData_Dictionary No_Image Set pMain_File To SysFile.File_Number Set pMain_Index To Recnum End_Object

Please note that this object contains only the two mandatory prop- erties for the cData_Dictionary class.

In order to set-up all the rules, you will have to set a number of (field-related) properties and you will have to send a number of messages. You might even need to create a number of “custom procedures” for validation or for checking if a record can be deleted.

In the next paragraphs, we will first explain the use of the Classify WorkBench to setup DDO’s, after which we will discuss the most important messages and properties available to you and we will give you some examples of how to incorporate your rules into the data dictionary. For a full list of all properties and messages available in the data dictionary, please refer to the technical documentation.

Since the WorkBench settings and the DDO-messages and proper- ties are very much interrelated, you will find that in the WorkBench description we will not go to deep into these property as they are discussed later on in greater detail.

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.1 Chapter 6: Data dictionary Classify Handbook The role of the DDO

6.1. The role of the DDO The data dictionary will act as a “quality control department”. This means that it is not directly involved in any file manipulations that go on in the program. Only when a particular module tries to modify information in a file, it will first pass on any changes to the data dictionary for validation. After the data dictionary approves, the module will request the saves or deletes from the data dictionary. This is a two-phase activity since you need to be able to first validate information from several files and than save them only if all validate. A data entry module will also request information from the data dictionary which data entry options should be set as soon as it is activated.

It is very important to note that the data dictionary is not aware of what goes on in the program until its service is requested by a data entry module or a batch process.

DAC-package comparison: The data dictionary does not compare to the Data Set because of this. The Data Set class is very actively involved in the retrieval and saving of records. Even though there can be some integrity rules set up in data sets, they do not relate to the data dictionary, but rather to the subsystem class.

Data dictionary objects can be placed in separate source files. We suggest using the extension “DDO” for this file. A typical DDO file would look like this:

Example: Open Custom // Actually OPEN the main file Use_File Invoice // There is no need to actually open this file, but we // need to include the definition in order to make // reference to it

Object oCustomer_DDO is a cData_Dictionary No_Image Set pMain_File To Custom.File_Number Set pMain_Index To Index.1 Send mAdd_Child_File Invoice.File_Number End_Object

Please note that the above example is a very simple data dictionary that just lists the fact that the invoice file is a child to customer and relies on default behaviour for delete protection.

You would include this data dictionary in your source code by using the command:

Syntax: Use_Extend Custom.DDO

This would normally replace the OPEN command in your source code.

Warning: All data dictionary objects should be a child of the Classify desktop object. So this statement should be placed inside the object/end_object for that object. If you include view-defini- tions inside the desktop object, the best place to put the USE_EXTEND would be in the view package.

Page 6.2 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary The DDO in the WorkBench

6.2. The DDO in the The WorkBench is the design, documentation and generation tool for Classify. It allows you to design and document your application WorkBench without the need to code. Once the design and documentation is finished, large parts of the code will be generated for you.

Many of the WorkBench settings translate directly into Classify messages and properties. If that is the case, we will just make the reference to that message or property. The resulting syntax, usage and samples are provided in the following paragraphs.

The main views for the specification of the data dictionary are:

6.2.1. Creating your data types The Classify WorkBench offers you a special feature that is not found in the packages: creation of your own datatype for the file definitions.

You can create as many datatypes as you want. The advantage of using datatypes is that it will become very easy to make sure all fields based on this data type always are treated the same.

For every data type you can specify its “internal” data type (the data types available in Classify), a length and a set of validation-related characteristics.

Once you create a field based on this type, anything you have specified here will be “inherited” by the new filed. This information cannot be changed on the field level. So if you specify a length in the Classify Type, you can no longer change the length of a field specified as being of this type. If you specify a minimum and maximum value (e.g. percentage), you will not be able to modify the minimum and maximum values per field.

Alternately, if you leave a characteristic “open”, you can enter that piece of information on the field level.

When you decide to change any settings in a Classify type, these changes are propagated throughout the WorkBench. And again the same logic applies: blank fields will not be propagated (so removing a validation will leave all the “old” validations in place), but

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.3 Chapter 6: Data dictionary Classify Handbook The DDO in the WorkBench

whereever a field is entered, all the field-definitions based on this Classify type will be updated.

It will be clear that this is a very powerfull mechanism to make sure data integrity rules are implemeneted consistently over the entire database.

6.2.2. Field templates Another “convinience item” in the WorkBench is the field templates (previously know as default fields). This option allows you to set up generic field descriptions, complete with end-user documentation, default values, entry options and all the other things you can usually specify per field.

Next, when you create new fields in the database-definition, you can use these templates to give you the base set of information. Contrary to the Classify types, templates fields can be changed without effecting already entered data. The template is only used when creating a new field or explicitely to update an existing field.

The settings are similar to what you can specify per field in the database definition, so we will not get into that at this point.

Hint: Specification of classify data types and field types and templates is not necessarily done up front. While some of the types and templates might be clear from the initial design, it is very important that you go back to these functions whenever you encounter a field that is likely to be used in multiple files.

6.2.3. Creating the database The next step is, of course, the specification of the actual data files definition and the fields therein. This can be done in the “File and field definition” view of the WorkBench. As you can see in the screenshot, this presents you with a full view of the datafile definition. In the upper half of the screen, you can see the file-characteristics; in the lower half you will find the field specifications.

The filename is obvious. This is set at 7 characters to allow for the use of the standard Classify naming convention. The class name will usually be left blank, derived should be set to “N”. We will revisit these settings later in a chapter on “advanged use of Class Hier- achies”.

The base class will be cData_Dictionary for “ordinary” data diction- aries. However, as soon as you need to create custom functions or procedures (such as validations), you will need to create a special

Page 6.4 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary The DDO in the WorkBench

subclass of the cData_Dictionary class that contains these functions and than base your file definition on this custom-build class rather than on the standard cData_Dictionary.

We will discuss how to specify new classes in the WorkBench later.

Next, you can specify the main file characteristics such as compres- sion, synchronisation, linked list-settings and user rights (default, can be changed per user at runtime). The next table provides you with the “extra file settings”. This list can contain several functions that are triggered during file-processing. The current list (which can be extended with source changes) contains: » Ok to save check » Ok to delete check » All user hooks for save & delete operations

Finally, you can specify the end-user texts on a per-language basis (use [Alt][F6] to move from the extra settings to the languages and than from languages to field information).

When you get to the field information, you might notice the lack of a fieldnumber.TheWorkBenchusesalinkedlisttomaintainafixed order of the fields. This means they will remain in the order in which you enter them.

If you press [F4] on the field name, you will be prompted with a list of available field templates. If you select a template, the template settings will be copied into the (new) field definition. This means you can use templates to create new fields, but also to update existing fields.

If you want to see a list of available fields in alfabetical order, you can press [Shift][F4]. You can now select a field and the table will automatically rebuild to show this field.

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.5 Chapter 6: Data dictionary Classify Handbook The DDO in the WorkBench

you can use upper and lowercase characters in the fieldnames as well as spaces. Since the fieldname is also used as the default form-description for the field, we strongly suggest you use this facility and pick “natural” names for the fields.

After specifying the field name, you must specify the field type. This automatically establishes the dataflex data-type. Whether you can enter the field length depends on whether the field length was specified in the Classify type-definition.

You can now continue to specify entry options, validations, minimum and maximum values and defaults. Once that is finished, you can specify additional field messages, such as prompt, entering and exiting messages.

The final pieces of information you can provide are the language- specific descriptions for the field.If you do not specify a form descrip- tion, Classify will use the field name; if you do not specify a table desciption, Classify will use the form description.

Once you have completed this screen with basic file & field informa- tion, you can continue to the “Extra file information” view.

In this view, you can specify all the extra information such as index-definitions, relationships, dependencies and the contents of the prompt list.

The first thing you can specify are the foreign keys. The field “Rel#” is the relation-identifier used throughout your source code. The name is provided for easy of reference and could contain descrip- tions like “responsable person” and “handling person”.

The foreign key fields must match order, size and type with the key fields of the parent file.

Page 6.6 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary The DDO in the WorkBench

In the index definition, agaiin there is room to enter a “name” for an index, making it a bit easier to identify the index in other stages of the program definition. There is no need to append “Recnum” to the file definition; just deselect the “unique” check box. This will auto- matically result in recnum being appended in the DataFlex file definition.

When you specify the dependencies, you can use the relation name rather than the id. Of course, a prompt is available listing the relationships.

6.2.4. Specifying your mes- On several occasions in the file definition, you have the option to sages specify message names. To avoid typing errors, the WorkBench will require you to enter these messages prior to usage. This can be done in the “Method specification” view.

This view allows you to specify the message and its arguments, independent of the class(es) in which the message will be imple- mented. This allows you to build a “message base” with the generic descriptions for the messages you have. This will help you in making proper use of polymorphism.

The first thing you need to specify is the message name, followed by the message type. Please note that we have 3 “generic” types (procedure, procedure set, function) and a large nbumber of “Class- ify typical types”. If you select one of the three generic types, you are allowed to specify the arguments. When you select the Classify types, the arguments cannot be entered since they are determined by the WorkBench based on the type. When you specify a generic function, you can enter the return type as well.

The first description you can enter is a general description that should specify the action of the message, independent of the class in which the messages are implemented. So the description for “Construct object” could contain a reference like “this message will create the properties specific for the class”, it should not list the properties since these will be difference depending on the imple- mentation per class.

When you specify a generic message, you can specify the argu- ments (type, name and description).

The third part can be used to specify the implmentation of a message in a given class, along with implementation specific comments.

Important: The WorkBench will check the message type to determine whether you can use a a certain message for a given proce- dure. If you specify a generic message with the correct argu- ments, the WorkBench will still not accept it.

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.7 Chapter 6: Data dictionary Classify Handbook The DDO in the WorkBench

6.2.5. Creating class defini- You can not only create classes, but also class-definitions. This is tions done in the classes & packages view. You can specify the class, it’s parent, mixin definitions, class header code as well as the messages implemented in the class.

Currently, the WorkBench does not validate that a selected record actually exist in a class but we intend to implemented this in the future.

If you want to base a data dictionary on a custom sub class, you will have to specify the class in this view. The “Type” needs to be set to “DATADIC”.

For a fuller explanation of the class (and method) definition, please refer to the dedicated chapter.

Page 6.8 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary File dependent information

6.3. File dependent Information in the data dictionary can roughly be divided into two main sections: file dependent information and field dependent infor- information mation. In this paragraph we will discuss the properties and mes- sages that work on file level.

6.3.1. Main File The file number of the main file of the data dictionary. This property can only be set once. If it is set for the second time this will generate a fatal error.

By setting this property, you instruct the data dictionary class to read all the information specified in DF-File. This means the file must be opened.

Warning: This property is mandatory.

Syntax: Set pMain_File To [File_Number]

Note: You can specify the file number by Filename.File_Number (recom- mended).

Default: None

6.3.2. Main Index The number of the main index for a file. The fields in this index should also define the key1 for the file.

Warning: This property is mandatory. If there is no index for the file, you should set it to RECNUM or 0.

Syntax: Set pMain_Index To [Index_Nr]

Note: Index numbers can be specified by either the number or by INDEX.# as is used in DataFlex find commands.

Default: None

6.3.3. Add Child File For each file that relates to the main file of the data dictionary, this message must be sent. It must be sent because the list of child-files built by this message is used to determine if records may be deleted from the main file. This message works with the pDelete_Range property to check whether a record may be deleted or not. Please see the example supplied for pDelete_Range.

If there is more than one child file, all child files must be specified. Sending this message multiple times will add all files to the internal child list.

Warning: This message is mandatory when any file relates to the main file. If you do not send this message for every child file, the data dictionary will not automatically retain integrity for child- files when a record is deleted. The data dictionary will not require the file to be open all the time. If you try to delete a record and one or more of the specified child files are not open, an error is generated and thedeleteisaborted.

Syntax: Send mAdd_Child_File [File_Number]

Default: None

1 The key of a file is that set of fields that will uniquely identify a record. The key is used in relationships. Any file relating to a file will have fields with the same type and length in it which will match the information in the key of the parent record.

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.9 Chapter 6: Data dictionary Classify Handbook File dependent information

6.3.4. No Delete If this property is set to true, no deletes from this file are permitted. If you want to set this property depending on the user, you should set this property to True and use the user-rights to control the deletion.

Syntax: Set pNo_Delete To [True|False]

Default: False

6.3.5. Read Only If the file is marked read only by setting this property, no updates can be made, so no delete or save operation is allowed. Please see the notes on pNo_Delete regarding user-dependent setting of the property.

Warning: This property is not related to the flags or to the file-mode option in the open command.

Syntax: Set pRead_Only To [True|False]

Default: False

6.3.6. May Modify Indirect If dependencies are specified between files, there is a chance that files need to be updated without the user actually changing this file. In that case, this property is checked rather than the pRead_Only.

Example: If you have a ‘total sales’ file, in which you want to keep a total of all sales, you would problabe specify a dependency between the sales-file and the total file.If you modify or create a sales-record, this will automatically enforce an update of the total file. Prior to this, the pMay_Modify_Indirect property for the total files is checked to see if you may update this file. So if you would want to inhibit direct changes, you could set pRead_Only to true and this property to true as well. Any attempt to edit the file directly will now generate an error, but updating sales (and thus totals) is permitted.

Syntax: Set pMay_Modify_Indirect To [True|False]

Default: True

6.3.7. May Modify If this property is set, records can only be retrieved, deleted and created, but not modified.

Syntax: Set pMay_Modify To [True|False]

Default: True

6.3.8. May Create If this property is set to false, it is not allowed to create new records.

Syntax: Set pMay_Create To [True|False]

Default: True

6.3.9. May Copy If this property is set, copying a record and all of its children is allowed. This property is only checked for the file originating the copy.

Example: If Invoices relates to Customer, and pMay_Copy for customer is set to TRUE, but it is set false for Invoice, it will be allowed to copy a customer with all invoices and invoice lines, but it is not allowed to copy an invoice with invoice lines.

The copy feature will always include all child and grandchild records (to any depth).

Syntax: Set pMay_Copy To [True|False]

Default: False

Page 6.10 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary File dependent information

6.3.10. May Change Key If this property is set to TRUE, it is allowed to change the key of a record, which will automatically change all child records as well.

As with the pMay_Copy property, it is only checked for the file initiating the change.

Syntax: Set pMay_Change_Key To [True|False]

Default: False

6.3.11. Ok To Delete Check This property can hold the ID of a function that should be executed Func whenever a request to delete a record is received. If this message returns a non-zero value, the deletion is aborted.

Warning: Do not generate an error message yourself since this will prompt user input while the database is locked. Classify will generate an error for you once the database is unlocked.

Warning: If you are creating your own data dictionary class, you should not set this property but augment pOk_To_Delete_Check. Otherwise you have the risk that a programmer can set this property and thus overwrite your setting.

Syntax: Set pOk_To_Delete_Check_Func To GET_[Function_Name]

Default: None

6.3.12. Ok To Save Check Func This property can hold the ID of a function that should be executed whenever a request to save a record is received. Any non-zero value will result in an error and the save command will be aborted.

If you want, you can generate an additional error message to explain the exact nature of the error.

Syntax: Set pOk_To_Delete_Save_Func To GET_[Function_Name]

Default: None

Warning: If you are creating your own data dictionary class, you should not set this property but augment pOk_To_Save_Check. Otherwise you run the risk that a programmer can set this property and thus overwrite your setting.

6.3.13. User hooks To provide maximum flexibility, Classify offers a number of ‘hooks’ that allow you to perform specific actions during save and delete actions. These hooks are provided in the form of properties that can contain message id’s. The following properties are provided: » pBefore_Validate_Msg The message stored here is send prior to the validation of all the fields. This message is only send when a save is requested, not when the fields are validated during data entry. All field references should be to the local buffer1. » pAfter_Validate_Msg The message specified here is sent after the validations are finished. However, if an error has occurred during validation, this message is never executed since the process aborts as soon as an error occurs. All field references should be to the local buffer.

1 The cSubsystem class maintains a local file buffer which can be accessed by the pLocal_Field_Value message. The global file buffer can be accessed using pField_Buffer. Please refer to the documentation on file-handling in Classify for more information.

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.11 Chapter 6: Data dictionary Classify Handbook File dependent information

» pBefore_Save_Msg This message is sent at the start of the save procedure even before the buffer gets updated or the backout dependencies get executed. However, the file buffer has been repositioned and the database is locked. This message is the best hook if you want to compare old and new values. You can retrieve the new information from the local buffer, while the old information can be retrieved from the file buffer. » pBefore_Update_Msg This message is sent after the backout procedures but before the information from the local buffer is transferred to the file buffer. » pAfter_Update_Msg This message is sent after the transfer from the local buffer to the file buffer. All field references should be to the global file buffer. » pAfter_Save_Msg This message is sent after all the saves are completed. If any errors occur during the saves, this message will never be sent. All references should be to the global file buffer. » pBefore_Delete_Msg This message is sent before a record is deleted. » pAfter_Delete_Msg This message is sent after the record is deleted.

Warning: If you are creating your own data dictionary class, you should not set these properties but augment the corresponding mes- sages1. Otherwise you run the risk that a programmer can set this property and thus overwrite your setting.

Warning: You cannot abort a save or delete operation by returning non-zero values from these procedures.

Syntax: Set pBefore_Save_Msg To [Message_ID] Set pBefore_Validate_Msg To [Message_ID] Set pAfter_Validate_Msg To [Message_ID] Set pBefore_Update_Msg To [Message_ID] Set pAfter_Update_Msg To [Message_ID] Set pAfter_Save_Msg To [Message_ID] Set pBefore_Delete_Msg To [Message_ID] Set pAfter_Delete_Msg To [Message_ID]

Default: 0

6.3.14. Version This is a general property that can be used for version control. It is available in every major class and can be retrieved by an end-user using the Version Information function [Ctrl][F1].

Syntax: Set pVersion To [Number]

Default: 0.0

1 Please refer to the technical manual for more information

Page 6.12 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary Field related information

6.4. Field related informa- After you specified the file-specific rules, you can set the field-re- lated rules. Part of these rules might be specific for data entry and tion might not actually describe integrity rules for the database. The reason this information is stored here is to provide a consistent user interface. The cSubsystem class will check with the data dictionary to determine which options should be set for every field. It is not possible to by-pass the validations set in the DDO. However, it is possible to ‘add’ options at subsystem level.

Example: If you want to allow data entry of the field credit-limit in some programs and not in others, you should specify the NOENTER entry option in the actual date entry module (zoom) rather than in the data dictionary.

If you want the credit limit to be always a positive number, you should specify this in the data dictionary. If you would like to check in certain programs that the amount does not exceed $100.000 while in other programs any amount can be specified, the check for $100.000 should again be in the data entry program, not in the data dictionary.

6.4.1. Field Message For every field a number of messages can be specified that will be sent at specific moments during data entry. The following messages can be specified (when references are made to the field, it might mean ‘the entry-item representing the field’): » @_Validation This function is sent whenever the fields needs to be validated. A non- zero return value indicates that the field failed to validate correctly. The validation function should generate an appropriate error. If the error is detected during the save, the subsystem will position the cursor at the field causing the error and pop-up the zoom if necessary. Validation is triggered in the following situations: ° the focus switches from one item to another item with a higher item number (any object except for find objects); ° the focus switches from one item to another item with a higher item number and the field is not blank (find objects); ° whenever the focus leaves the object but remains in the same view; ° whenever a record gets saved. » @_Entering This function is sent whenever this field is ‘entered’. A non-zero return value will cause the focus to ‘skip’ this field. This function is especially useful if you want to enter fields conditionally. » @_Exiting This function is executed whenever the focus leaves the field. Although a non-zero value can keep the focus in this field, it is not recommended since it would also prevent the user from navigating backwards. This function is usually used for layout, calculation or initialisation purposes. » @_Prompt This function is executed whenever the user presses the prompt key while on this field. A non-zero return value indicates failure to perform a pop-up and will initiate the default pop-up (if any). Please be referred to the documentation on the subsystem for the default prompts Classify provides for you. » @_Zoom This function is executed whenever the user presses the zoom key while on this field. Please note that the default behaviour for ‘zooming’ a text field is ‘exploding’ the field to screen-size. » @_Field_Update_Function This function is executed whenever the field is changed. It is executed even before the exiting and the validation, so it is excellent for formatting purposes. This field message works different than the other messages. While its arguments are the same, the return value for this field message should not be an error status, but the “up-

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.13 Chapter 6: Data dictionary Classify Handbook Field related information

dated” value of the field. If the field message does not modify the value, the passed value should be returned.

The function can be either a pre-defined field-function (all predefined trigger functions are specified in the cData_Dictionary_Procedures class), or a custom written function.

Syntax: Set pField_Message [Trigger_Type] [Field_Number] To Get_[Function_name]

Alternate use: Set pField_Message [Trigger_Type] Field [FileName.Fieldname] To ; Get_[Function_Name]

Default: None

6.4.2. Predefined field mes- Classify provides a number of predefined field messages. This list sages will probably grow constantly, so check your release notes for the most current list.

6.4.2.1. Table Validate This message will validate any field that has its pTable_Id set. It will determine the type of table (@_Limited, @_Normal, @_Relation) and perform the validation based on this.

Syntax: Set pField_Message [Trigger_Type] [ Field_Number] To Get_pTable_Validate

6.4.2.2. Blank or table This validation message checks whether the value of the field is either blank or in the table/related file associated with this field. This validation can be used on a foreign key field where you want to allow null-relationships.

Syntax: Set pField_Message [Trigger_Type] [ Field_Number] To Get_pBlank_Or_Table

6.4.2.3. Non Blank This message produces an error if a field is blank. We suggest you use this message instead of the “required” field option.

Syntax: Set pField_Message [Trigger_Type] [ Field_Number] To Get_pNon_Blank

6.4.3. Creating field messages You can quite easily create your own functions to specify with the pField_Message. The syntax for such a function definition is:

Syntax: Function [Name] Integer [Field_number] String [Field_value] Returns Integer

All these parameters are passed automatically. The return value should be “0" to indicate success, or an integer to indicate failure.

Important: The only exception to the above statement is the field update value, which is not used to determine a success or failure, but it should return the “updated” value of the field

Hint: It is good practice to make as many field functions as global as possible. This can be done by placing these functions in a new sub-class of the data dictionary or in a special mix-in class. Also, you should take care to use the passed arguments (if possible) instead of referencing field-numbers. If a validation function is contained in the class definition, the code lines will be included in the program once, whether this procedure is used once or many times. If the procedure is defined inside the object, the code is included for every object using this validation. This not only leads to extra maintenance problems, but also increases program size and thus decreases performance. As a rule, try to make every function global. Only very specific functions should be left in the object definition.

In the next couple of sub-paragraphs, we will list a number of messages that you might use in writing a custom field-message.

6.4.3.1. Local Field Value The file-buffer is a global concept. Therefore it is not permitted to access information in the file-buffer. Neither can you access the information stored in a data entry object, since this will violate object oriented principles. We provided the pLocal_Field_Value property to transparantly access all field information. This message will retrieve

Page 6.14 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary Field related information

or update the latest contents of the specified field. If the field is displayed in one of the zooms, setting this property will immediately effect the displayed value. If you get this property, you will always get the latest version (just entered).

Syntax: Set pLocal_Field_Value [Field_Number] To [Val] Get pLocal_Field_Value [Field_Number] To [Var]

Alternate use: Set pLocal_Field_Value Field [File_Name.Field_Name] To [Val] Get pLocal_Field_Value Field [File_Name.Field_Name] To [Var]

Default: None

Warning: Although the syntax with the optional Field keyword might suggest otherwise, the value will always be retrieved for the main file of the data dictionary!

Example: Suppose you want to check whether the field COMPANY.NAME is not blank. Rather than setting ‘required’ which will also inhibit navigation past the field in find objects, you could do the following:

Register_Function pCheck_Not_Blank Integer Field_Number String Field_Value ; Returns Integer

Object oCompany_DDO is a cData_Dictionary No_Image Set pMain_File To Company.File_Number Set pMain_Index To Index.1

Set pField_Message @_Validation Field Company.Name To Get_pCheck_Not_Blank

Function pCheck_Not_Blank Integer Field_Number String Field_Value ; Returns Integer Local Integer RetVal

If Field_Value Eq “” ; Get pError Of Program_Desktop “HDS3" 45 ”" 0 To Retval Else ; Move 0 To Retval Function_Return Retval End_Function End_Object

Example: If you want to allow entry for the field COMPANY.PHONE only if the COM- PANY.AREA_CODE has information in it, you could do this as follows:

Register_Function pCheck_Area_Code Integer Field_Number String Field_Value ; Returns Integer

Object oCompany_DDO is a cData_Dictionary No_Image Set pMain_File To Company.File_Number Set pMain_Index To Index.1

Set pField_Message @_Entering Field Company.Phone To Get_pCheck_Area_Code

Function pCheck_Area_Code Integer Field_Number Integer Phone Returns Integer Local Integer RetVal Local Integer Area_Code

Get pLocal_Field_Value Field Company.Area_Code To Area_Code If Area_Code eq 0; Move 1 To Retval Else ; Move 0 To Retval Function_Return Retval End_Function End_Object

Please note that the above function could have been coded as:

Function pCheck_Area_Code Integer Field_Number Integer Phone Returns Integer Local Integer Area_Code

Get pLocal_Field_Value Field Company.Area_Code To Area_Code Function_Return (Not(Area_Code)) End_Function

This syntax makes use of the fact that a zero value is considered ‘False’ and any non zero value is considered ‘True’.

6.4.3.2. Field Buffer The pLocal_Field_Value retrieves values from the local buffer. This will be sufficient in most cases. But there are some instances where you need to get your information from the global file buffer. This can be done using pField_Buffer.

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.15 Chapter 6: Data dictionary Classify Handbook Field related information

Syntax: Get pField_Buffer [Filenumber] [Field_Number] To [Var] Set pField_Buffer [Filenumber] [Field_Number] To [Val]

Alternate: Get pField_Buffer [Filename].File_Number Field [Filename.Fieldname] To [Var] Set pField_Buffer [Filename].File_Number Field [Filename.Fieldname] To [Val]

Warning: This message should only be used in a procedure where you know 100% sure that the global buffer is up to date.

Example: You could use pField_Buffer in: » Constrain procedures. Whenever a constrain procedure is executed, the global buffer will contain the record needed to be evaluated. The local buffer will still contain the values from the last valid record. » Several user-hooks allow the use of the global buffer » All dependency procedures » If you performed a find yourself (for instance to do a special sort of validation). Please check the chapter about the file-handler class as well.

6.4.3.3. Subsystem This property stores the ID of the subsystem or batch requesting the trigger message. This property is set prior to sending the trigger message and reset after that.

Warning: This property will only hold a valid ID during specific mes- sages, such as these trigger messages.

Retrieving the subsystem might be necessary to gain access to information stored in the subsystem or for specific prompts.

Syntax Get pSubsystem To [Var]

Warning: This property can not be set.

6.4.3.4. Update State This is a property of the subsystem. Yet we felt it would benefit to discuss it here. This property indicates whether a new record is being created (False) or an existing record is edited (True).

Syntax: Get pUpdate_State Of (pSubsystem(Current_Object)) To [Var]

Warning: This property can only be accessed if the pSubsystem pro- perty holds a valid value. If not, the above syntax will generate an error.

Warning: This property can not be set.

Example: If you want to put a default value in a field only when creating a new record, you should create the following entering procedure:

Register_Function pSet_Default Integer Field_Number String Field_Value

Set pField_Message @_Entering Field Cust.City To Get_pSet_Default

Function pSet_Default Integer Field_Number String Field_Value If (Not(pUpdate_State(pSubsystem(Current_Object))) ; Set pLocal_Field_Value Field_Num To “New York” End_Function

This function could also be coded as:

Function pSet_Default Integer Field_Number String Field_Value Local Integer Subsystem Local Integer Update_State

Get pSubsystem To Subsystem Get pUpdate_State Of Subsystem To Update_State

If (Not(Update_State)) ; Set pLocal_Field_Value Field_Num To “New York” End_Function

6.4.3.5. Error If you want to generate an error or warning during a validation (or any other field message), you should use the pError message:

Page 6.16 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary Field related information

Syntax: Get pError Of Program_Desktop [ErrorGroup] [Errornumber] [Extra_Text] ; [Linenr] [Extended_Text] To [Var]

The“OfProgram_Desktop”asstatedinthisexample,isneededto make sure the error always reaches the desktop object. DataFlex turns of delegating during broadcast and this might result in an error not popping up if you do not specify this constant.

If you don’t know the line-number, pass 0 and the error object will omit the keyword “Line” as well. The value returned to Var is determined by the choice made by the user. For errors this will not be important, but for warnings it is significant.

To display “File.Fieldname” in an error, you can pass this either as a constant string in Extra_Text, or you can pass a string containing “|FNx,y” where “x” is the file number and “y” is the field number. The Classify error handler will automatically convert this to the filename and fieldname. However, in order to be able to determine the field- name, the .TAG file should be available.

The Extended_Text can be omitted for most errors, however, if you pass this, it will be displayed on a second error line.

6.4.3.6. Parent Field Value If you want to perform a validation based on some value in a parent record, the obvious thing to do is to perform a relate and check your values based on that. But, if you are creating the parent record at the same time as the child record, this would work. The only way this could happen would be if you have a complex view with two subsys- tems, one for the parent file and one for the child file. In that case you would want to validate on the values in the parent subsystem.

Even though this can easily be coded manually, we provided a standard function that checks whether a complex view matching the given situation is used and if so, retrieves the value form there. In all other cases, it will perform a relate and get the value from the parent file.

Syntax: Get pParent_Field_Value [Relation number] [Parent file] [field] To [Var]

Alternate: Get pParent_Field_Value [Relation number] FileField [File.Field] To Var

6.4.3.7. Global Lookup This message is one of the messages provided for easy customising the prompt lists. Although you could basically do anything in a function used for pop-up (up to and including creation and destruc- tion of your own objects), we have provided a couple of messages that allows you to gain a certain amount of control over the standard Classify look-up list.

This particular message allows you to pop-up a prompt list on any file using any index.

Syntax: Send mGlobal_Lookup [Main_Filenumber] [Index] [ Constrain_Function] ; [Constrain_Object] [Invoking_Object] [Invoking_Item] ; [Invoking_Field] [Line_Contents]

Alternate: Send mGlobal_Lookup [Filename].Filenumber Index.[Nr] [ Constrain_Function] ; [Constrain_Object] [Invoking_Object] [Invoking_Item] ; Field [Filename.Fieldname] [Line_Contents] » Main_Filenumber is the number of the file you want to have in the prompt. » Index is the index to be used. » Constrain_Function is an optional function to constrain the finds; 0 means no constrain1.

1 Please refer to the chapter on subsystems for an example of a constrain

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.17 Chapter 6: Data dictionary Classify Handbook Field related information

» Constrain_Object is the ID of the object the constrain procedure is located in (0 = Current_Object). » Invoking Object is the object where the invoking item is located. If you want to pass the object that has the focus, you can retrieve the object ID by specifying (Focus(Desktop)). » Invoking_Item is the number of the item inside the invoking object which value you want to use to seed the first find used to build the list. The value of this is item is moved into the Invoking_Field of the main file before the pop-up is started and the records are found. » Invoking_Field is the field in the specified prompt file you want to use to initiate the search. After the file is cleared, the contents of Invoking_Item is placed in this field and then the list is started by a find greater or equal. » Line_Contents is a string that might contain a formula that can be interpreted by EVAL1. Depending on the contents of this formula, DataFlex might require you to include the symbol table in the .FLX file. If you specify an empty string, Classify will assume the standard contents for a global lookup list for the specified file. Instead of specifying a string, you can also specify the expres- sion without quotes, but precede it with the keyword EXP. This will force a compile-time translation, eliminating the need for the symbol table.

Warning: In order for EVAL to work correctly, you will usually need to specify the -S compiler option or you have to prefix the ex- pression with the EXP keyword..

Example: Suppose you have a persons file in which you want to enter a car. However, to validate this, you have a special file which is not related. As a special selection, per person there is a field ‘stick’ to indicate manual or automatic gearing. The car file has a field ‘stick’ as well to indicate whether they have a model with manual gearing or not.

Register_Function pConstrain_On_Gear Returns Integer Register_Function pPrompt_Cars Integer Field_Number String Field_Value

Set pField_Message @_Prompt Field Person.Car To Get_pPrompt_Cars

Function pPrompt_Cars Integer Field_Number String Field_Value Send mGlobal_Lookup Cars.File_Number Index.1 Get_pConstrain_on_Gear 0 ; (Focus(Desktop)) (Current_Item(Focus(Desktop))) ; Field Cars.Stick ; Exp (String(Cars.Code) * Cars.Name) Function_Return 0 End_Function

Function pConstrain_On_Gear Integer Find_Mode Integer IndexNr Returns Integer Local String Preference Local String Available Local Integer Retval

Move 0 To Retval Get pLocal_Field_Buffer Field Person.Stick To Preference If Preference Eq ‘M’ Begin Get pField_Buffer Cars.File_Number Field Cars.Stick To Available If available eq “N” ; Move 1 To Retval End Function_Return Retval End_Function

The pop-up function could also have been coded as:

1 See also the appendix about our special expression handler

Page 6.18 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary Field related information

Function pPrompt_Cars Integer Field_Number String Field_Value Local Integer Invoking_Object Local Integer Invoking_Item

Get Focus Of Desktop To Invoking_Object Get Current_Item Of Invoking_Object To Invoking_Item

Send mGlobal_Lookup Cars.File_Number Index.1 Get_pConstrain_on_Gear 0 ; Invoking_Object Invoking_Item Field Cars.Stick ; “(String(Cars.Code) * Cars.Name)” Function_Return 0 End_Function

Remember that although in this example we determined a lot of the informa- tion based on the current focus, you can specify almost anything. So you could have a prompt object that would work on any field and always pop-up the same list by ignoring all the focus stuff and “hard-code” the value, or you could perform several validations before the pop-up.

6.4.3.8. Simple Lookup This is a function rather than a procedure and it allows the largest flexibility of all the prompt-related messages.

Syntax: Get pSimple_Lookup [Main_Filenumber] [Index] [Constraint_Function] ; [Constraint_Object] [Line_Contents] To [Var]

The function will start building the prompt from the current record, so you should either clear or initialise the main file “manually” before sending this procedure.

If the user makes a selection, this function will return a value of 1 (one) and it will make sure the selected record is in the global file-buffer. Please be referred to the documentation on the file handler class as well. What you do with the information in the buffer is once again up to you.

6.4.3.9. mCustom Index Lookup Classify provides an automatic prompt list for every index field. This message is provided to allow you to “customise” these prompts. This message will, just like the standard prompt, start with a ‘find greater equal’ based on the data in the form. And after selection, it will display the entire record (and display child records if needed)

The difference is that with this message you can specify the index and line contents and add additional constraints. Constraints applied to the system will automatically be applied to this message as well (so the constrain needs only to check for the additional information, not for the constrains supplied in the subsystem). If you do not specify the index (0) and/or line_contents (“”), the default values will be used. So you can change the index and retain the original line contents, or change the contents but still always use the correct index automatically.

Syntax: Send mCustom_Index_Lookup [Invoking_Subsystem] [Index] [ Constraint] ; [Constrain_Object] [Line Contents]

Example: Suppose you want to pop-up the customer list, but instead of using the index on the code field you want to use a different index. You also wanted the table to display name as the first field. You would have to create the following prompt message:

Register_Function pPrompt_Customer Integer Field_Number String Field_Value; Returns Integer

Set pField_Message @_Prompt Field Customer.Cust_Nr To Get_pPrompt_By_Name

Function pPrompt_By_Name Integer Field_Number String Field_Value; Returns Integer Local Integer Subsystem

Get pSubsystem To Subsystem Send mCustom_Index_Lookup Subsystem Index.1 0 0 ; “(Customer.Name * (String(Customer.Cust_nr)) )” Function_Return 0 End_Function

6.4.3.10. Custom Related Lookup This message is designed to customise the standard pop-ups for the related-file prompts. Much like the above message, again you can specify index, line contents and additional constraints (or specify

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.19 Chapter 6: Data dictionary Classify Handbook Field related information

them as blank/zero and we will use the default values). And again much like the above, this message will initialise the list like the standard pop-up for related fields and display the related information if a record is selected.

Syntax: Send mCustom_Related_Lookup [Invoking_Subsystem] [Invoking_Field] ; [Index] [Constrain] [Constrain_Object] ; [Line_Contents]

Example: If you want to display a customer list sorted by name if the user hits the prompt-key from Order.Cust_Nr, you could do the following:

Register_Function pPrompt_Customer Integer Field_Number String Field_Value; Returns Integer

Set pField_Message @_Prompt Field Order.Cust_Nr To Get_pPrompt_By_Name

Function pPrompt_By_Name Integer Field_Number String Field_Value; Returns Integer

Local Integer Subsystem

Get pSubsystem To Subsystem Send mCustom_Related_Lookup Subsystem Field Order.Cust_nr Index.1 0 0 ; “(Customer.Name * (String(Customer.Cust_nr)) )” Function_Return 0 End_Function

6.4.4. Prompt Object In this property the ID of a prompt object for a field can be specified. If the user presses the prompt key while on this field the specified object will pop up. Because the pop-up message is sent to the object its Popup_state must be set to true!

This property is not very frequently used since it is often more powerful to use the pField_Message @_Prompt syntax. This allows you to use a single object for several pop ups or to use C/D1 techniques for complex prompts.

Warning: Classify will automatically provide a number of prompt func- tions. The order of evaluation for the actual prompt is de- scribed in the cSubsystem documentation. Please be referred to this section before setting this property.

Warning: If you set both this property and the pField_Message @_Prompt are set, the latter will take priority. If a prompt object is specified at the zoom, that will take precedence.

Syntax: Set pPrompt_Object [Field_Number] To [Object_Id]

Alternate: Set pPrompt_Object Field [FileName.FieldName] To [Object_ID]

Default: None

6.4.5. Zoom Object In this property the ID of a zoom object for a field can be specified. If the user presses the zoom key while being on this field, the zoom object will pop-up. Because the pop-up message is sent to the object, its Popup_state must be set to true!

You could also specify the pField_Message @_Zoom to send a message instead of specifying an object. The first is usually easier and more powerful. Warning: If you set both this prop- 1 erty and the pField_Mes- Company sage @_Zoom, the latter will take priority. 2 4

Employee Position

1 Creation and destruction of objects is not officially supported by Data Access but some excellent articles3 emerged in FlexLines and D-News. Jobs

Page 6.20 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary Field related information

Warning: Since there can only be one zoom per field, a zoom object specified at data entry level will overrule this zoom object.

Syntax: Set pZoom_Object [Field_Number] To [Object_ID]

Alternate: Set pZoom_Object Field [FileName.FieldName] To [Object_ID]

Default: None

6.4.6. Add Option In this property the entry options per field can be defined. A field can have several options, however, some options exclude each other. Please be referred to the DataFlex manuals for more information on entry options. Just send multiple messages with different options to set several optionsforthesamefield.

The following options are available: » @_Autoclear » @_No_Calc » @_Modal_Insert » @_AutoBack » @_AutoReturn » @_Capslock » @_Required » @_Autofind_Ge » @_ForcePut » @_Retain » @_Retainall » @_Displayonly » @_Skipfound » @_NoEnter » @_NoPut » @_FindReq » @_Autofind » @_Zero_Suppress » @_Infrequent_Field » @_Auto_Prompt

The option “Infrequent field” will set the field to “no enter” in all zooms, except for those of the class cInfrequent_Field_Zoom. This option is intended for use with fields that need to be shown, but are usually not entered.

If this option is set, the prompt for this field will be shown automat- ically when the field is entered, regardless of the overall auto prompt setting which will cause all prompts to appear automatically.

Warning: The Retain option can be set by the user on runtime. The setting provided here is merely a default.

Important: Zero suppress will also work in data-entry modules. If en- abled, all numeric fields containing the value “0" will be dis- played as blanks (you will still create the images specifying them as numeric fields).

If a field has several options, these options can be set by multiple send commands:

Syntax: Send mAdd_Option [Field_Number] [Option_ID]

Alternate: Send mAdd_Option Field [Filename.Fieldname] [Option_ID]

However, you can also use the bitwise Or to set all options at once:

Syntax: Send mAdd_Option [Field_Number] [Option_ID] Ior [Option_ID]

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.21 Chapter 6: Data dictionary Classify Handbook Field related information

Default: None

6.4.7. Table ID A table can be assigned to a field. If this is done, only values specified in the table are accepted by the system. This is a specific kind of validation. Not only will the field be validated but also a prompt object is provided automatically so the user can make a choice from the table.

A table is specified by its ID and a type. The following types are supported: » @_Limited_Table This table will allow a single select, one character choice out of a list of nine choices maximum. The table ID is an 8 character code. The convention is four characters project ID and 4 digits table number. However, this is not mandatory. The field using this table type should be a one byte ASCII. The capslock option is automatically set for any field validated by a limited table. » @_Normal_Table This table is more powerful and supports an “unlimited” number of possibilities. It furthermore supports both multi- and single-se- lect. The table ID is also 8 characters. The field using this table should adjust its type and length to the table. If it is a single-select table, the field can be date, numeric or ASCII, depending on the value returned by the table. Also the length will depend on the table. Aside from a description and a return value this table can hold up to ten additional values per table entry. There are two types of multi-select modes available: sortable and non-sortable. For sortable normal tables, you need to specify an ASCII field with it fields length equal to ( (nr_of_Choices / 8) + 1). We suggest you use this type for all new tables. The non-sort- able table type is provided for compatibility with older systems and will require a numeric field to be created with the following length: ° 1 - 6 choices: 2 positions ° 7 - 13 choices: 4 positions ° 14 - 19 choices: 6 positions ° 20 - 26 choices: 8 positions » @_Relation_Table This type is used internally to validate related fields. It should not be used explicitly except for expert use. The table ID is the DataFlex file number.

The contents of these tables can be edited by the System program, included in the Classify tools. The table code can be eight charac- ters. We recommend you use the first four as a project-identifier.

Syntax: Set pTable_ID [Field_Number] [Table_Code] [Table_Type]

Alternate: Set pTable_ID Field [Filename.Fieldname] [Table_Code] [Table_Type]

Default: None for non-related fields, Filenumber and @_Relation_Table for related fields.

Important: You can specify whether tables should be editable by the end-user or not.

Example: If you had a field PERSON.GENDER this would be an ideal candidate for a limited table. For the data entry, you could use a standard field and the user could use the prompt key to get a list with valid choices. There is no risk that the number of choices will expand beyond 9 and a single character will always be enough.

Page 6.22 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary Field related information

A field like ADDRESS.STATE would be an ideal choice for the normal table using an ASCII return value. You could have the full list of states with their names and abbreviations in the table. The user would again get a standard form with the full list as a pop-up. Since the normal table allows multiple-char- acter return value, it is easy to return FL or even Florida (if you just want to check for consistency in spelling).

The field SONGS.MUSIC_TYPE is an ideal candidate for the multi-select normal table. Instead of entering the field in a form and using the pop-up, we could use a zoom of the cTable_Zoom class. This will display all options in the table with check-boxes and set/reset the check boxes based on the contents of the field (and vice versa).

Finally, the field LETTERS.TYPE would be an ideal candidate for normal table again. This might ‘fit’ in a limited table (Fax, Letter, Confirmation of appoint- ment), but the additional fields now enables you to specify additional informa- tion for every type of letter (like directory, default document etc.

Warning: There is a very thin line between normal tables and defining additional files. The main concern should be the fact that Classify will make sure you do not accidentally delete a parent record and thus create ‘orphans’. This protection does not exist for values in a normal table. They can be deleted while there are still references to. Also, in most situations the normal tables will be managed by system-operators rather than end-users. Additional tables could more easily be maintained by end-users. And again with separate files you would have more (flexible) ways to control and validate entries and access rights to the files. With normal tables a person just can edit all tables or he can edit none. No way to distinguish between different tables.

6.4.8. Add List Field This message adds the specified field to the list of fields to be displayed when the user calls a look-up list using the prompt key.

Multiple fields can be selected for this list by sending this message multiple times. The fields will be displayed in the order of the sets. The fields indicated here will always be preceded by the fields contained in the index used to display the list. If the pList_Field property is set for a field in the index, the field will be displayed only once.

The list field message accepts an extra (optional) argument for the display width of the field in the column. Using this argument, you can for instance display only the first 20 characters of a 60 character name field.

Syntax: Send mAdd_List_Field [Field_Number] {Width}

Alternate: Send mAdd_List_Field Field [Filename.Fieldname] {Width}

Default: None

6.4.9. Field Range This property allows you to specify a range of valid entries for a field. You can specify both upper and lower limits, but you can also specify only one of them (e.g. minimum is 0 will force positive numbers).

Syntax: Set pField_Range [Field_Number] [Boundary_Type] [Boundary_Value] ; [Boundary_Type] [Boundary_Value]

Alternate: Set pField_Range Field [File_Name.Field_Name] [Boundary_Type] ; [Boundary_Value] [Boundary_Type] [Boundary_Value]

The valid Boundary types are: » @_Minimum_Inclusive » @_Minimum_Exclusive » @_Maximum_Inclusive » @_Maximum_Exclusive

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.23 Chapter 6: Data dictionary Classify Handbook Field related information

Examples of use: Set pField_Range Field Person.Salary @_Minimum_Inclusive 0 Set pField_Range Field Item.Discount @_Minimum_Inclusive 0 ; @_Maximum_Exclusive 100

6.4.10. Default value You can specify default values for fields by using expressions. The expression can contain anything that the DataFlex expression evalu- ator can handle, from constants to the calling of custom-defined functions.

Syntax: Set pDefault_Value [Fieldnumber] To [Expression]

The expression should either be in quotes (requires symbol table) or preceded by the EXP keyword (see appendix D).

Example: Set pDefault_Value Field Order.Type To Exp (“S”)

Example: Function pDefault_Price Returns Number Local Number Price Get pParent_Field_Value @_Df_Relation FileField Product.Price To Price Function_Return Price End_Function

Set pDefault_Value Field Orderline.Price To ; Exp (pDefault_Price(Current_Object))

6.4.11. Standard Field This field-related property (True/False) indicates whether the default value can be used as a standard value or not. If you set this property to TRUE, the default value will be used as a standard value during the save if no other value was entered. If it is FALSE (default), the default value is only used as a default during data entry.

Syntax: Set pStandard_Field [Fieldnumber] To [True|False]

Default: False

6.4.12. Field information This message can be used to retrieve information about the field. The following arguments are supported: » @_Field_Name » @_Field_Display_Length » @_Field_Entry_Name » @_Field_Table_Name

Syntax: Get pField_Information [Info_Type] [Field_Number] To [Var]

The field name, entry name and table name are retrieved from the TAG and CFN files. The CFN file is a file with fieldnames, much like the TAG file, except that per line, you can specify the entry name and then the table name, separated separated by a comma.

IfyouhavenotelectedtoloadtheCFNandTAGfilesduringprogram load (see the INI file settings), you can load them by sending mRead_Tag and mRead_CFN to the DDO.

6.4.13. Field number This function will determine the number of the field. The argument passed is the name as specified in the TAG file.

Syntax: Get pField_Number [Field_Name] To [Var]

Page 6.24 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary Relationships

6.5. Relationships Classify provides a very strong relational model. This allows you to define complex relationships using multiple-field keys and even using multiple relations to the same parent file.

Any relation specified in the relating file should point towards the key in the other file. Please see the glossary for explanation of some concepts.

6.5.1. Add Foreign Key Field A relation is based on a key in the parent file and a matching foreign key in the child file. In order to maintain relationships, Classify needs to know both key and foreign key. The key of a file is specified by the pMain_Index property.

The foreign key should be identified using this message. This mes- sage will define one segment of the foreign key at a time. This means that if you use a multiple-field relationship, you will have to issue multiple mAdd_Foreign_Key_Field messages. The order in which you specify the fields should match the order of the fields in the key of the parent file.

Since Classify allows you to set up multiple relationships from one child file towards the same parent file, you will need to assign a unique identifier to each relation. This identifier should be an integer in the range 1 to 200.

Syntax: Send mAdd_Foreign_Key_Field [Fieldnumber] [Parent_Filenumber] [Identifier]

Alternate: Send mAdd_Foreign_Key_Field Field [Filename.Fieldname] [Parent_Filenumber] ; [Identifier]

Warning: This function should be placed in the mInit_DDO procedure.

Example: Procedure mInit_DDO Forward Send mInit_DDO Send mAdd_Foreign_Key_Field Field Order.Invoice Customer.File_Number 1 End_Procedure

6.5.2. Delete children The settings controls how Classify should treat children based on this relations ship. If you set this to False, Classify will not allow you to delete the parent record as long as there are child records. If you set delete child to True, Classify will attempt to delete the child records. If this cannot be done, Classify will not allow the parent to be deleted.

Compatibility If you have been Classify for a longer time, you will find that this one setting replaces the old “Ok_To_Delete_Range” And “Delete_Range” settings. This newer setting provides you more control, up to the relation level. If you do set these “old” properties, we will “translate” them to this newer structure. However we encourage you to move away from the old properties and into the new structure.

Syntax: Set pDelete_Children [Parent_Filenumber] [Identifier] To {True|False]

Default: False

6.5.3. The index for a relation If you want to display child-records based on a current parent record, there must be an index defined for the child file that has the foreign key as first elements of this index. Of course, there will be additional fields in this index, otherwise you could only enter one child record.

If Classify tries to find child records, it selects the index used by determining the main index as specified in DF-File for the first field in the foreign key. However, in general you will be able to overrule this default index selection on the programming level.

Warning: The most common error that causes child-information not to display is a wrong setting of the main index in DF-File.

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.25 Chapter 6: Data dictionary Classify Handbook Relationships

It is not necessary to define an index in order to get delete-checking. If no index is available, Classify will go through the file sequential to check for existing children. However, this will probably take a bit more time.

6.5.4. DF-File relations If you set up relationships in DF-File, Classify will detect these and automatically convert them to Classify relations. In doing this, Class- ify will assume that only one relation per parent file is defined in DF-File. So, if two fields relating to the same parent are found, Classify assumes that they are both part of one foreign key, being made up of two fields.

Classify will assign identifier 255 to this relationship.

If you want to tell Classify to ignore these relationship, you can set the pUse_DF_File_Relations property to False. This can be espe- cially useful if you have legacy relationship using overlap fields. You can now set use DF file relations to false and define the multi-field relation in Classify (make sure you assign a number other than 255).

Warning: You don’t have to send mAdd_Foreign_Key for DF-relation- ships.

6.5.5. Sharing a foreign key The Classify ability to have multiple field keys, also leads to the field concept of re-using one field in multiple relations ships. Let’s con- sider the following files: » Company ° Company_Id ° Name » Employee ° Company_Id ° Employee_Nr ° Name » Positions ° Company_Id ° Position_Id ° Description » Jobs ° Company_Id ° Position_Id ° Employee_Id ° Start date ° End date

It is obvious that we want to allow every company to define its own employee and position numbers,. so the key to the employee file will be company + employee, and for the positions it will be company + position. Since a person can hold multiple positions (especially over an extended period), the jobs file needs to be a bridge file between position and employee. The diagram shown here represents this structure.

Obviously,itwouldbenicetobeabletousethecompanyIDfieldin jobs to be related both to positions and to employee. Especially since this would implicitly constrain the jobs file to only allow employees of a given company in positions with the same company. Further- more, it would be nice to add another relationship from jobs directly to company for prompt reasons.

Classify will allow you to set up these relationships and will take care of the proper validations automatically (based on both or all three relationships). However, when the user hits the prompt key on the company ID field in the jobs file, Classify will pick the file for the

Page 6.26 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary Relationships

prompt “at random”. To explicitly specify the relationship to be used in the relationship prompt for a given field, you can set the pPrompt_Relation property.

Syntax: Set pPrompt_Relation [Fieldnumber] [Parent_File] [Relation_Number

Example: Set pPrompt_Relation Field Jobs.Company_Id Company.File_Number 255

6.5.6. The effect of relations Classify will automatically maintain the database integrity. This results in the following tests: » If you try to enter a child record, Classify checks whether the parent exists. » If you delete a parent, Classify will check if all child records can be deleted. » Classify will automatically provide a prompt list for all fields in the foreign key. » In data entry and batch systems, Classify will detect the relation- ships and automatically constrain finds. » Classify will automatically prevent key changes if there are any child records.

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.27 Chapter 6: Data dictionary Classify Handbook Dependencies

6.6. Dependencies Dependencies can be specified between fields in one file (inner file dependencies) and between files (inter file dependencies). Classify does not distinguish between these dependencies.

DAC-packages comparison: The dependent_item concept of DataFlex has nothing to do with these dependencies. The dependent_item is used to synchronise a set of items on screen (which Classify will do automatically). The dependencies defined in the data dictionary define dependencies in database contents. Classify dependencies are “related” to the backout and update procedures in data sets (although these are specified per file, while dependencies are specified between fields).

6.6.1. Create Dependency Through this message functional relationships (dependencies) can be specified. It can be used for inter- and inner file relations. Most of the time it will be used for fields that contain redundant information but are included in the record because of performance reasons. Typical relations are: keeping a total of the amounts specified in child records; giving a counter to a child record (on creation) to make it unique.

A dependency is established between two fields. The nature of the dependency can be specified by the programmer in procedures that are performed during a save or delete operation on the record from which the relation starts. The procedures specified can either be standard (see the next section) or user-defined.

Syntax: Get pCreate_Dependency [From_Fieldnumber] [To_Filenumber] [To_Fieldnumber] ; [Relation_ID] [Purge_Proc_ID] [Create_Proc_ID] ; [Delete_Proc_ID] [Backout_Proc_ID] [Update_Proc_Id] ; To [Var]

Alternate: Get pCreate_Dependency Field [From_Filename.Fieldname] [To_Filenumber] ; Field [To_Filename.Fieldname] [Relation_Id] ; [Purge_Proc_ID] [Create_Proc_ID] [Delete_Proc_ID] ; [Backout_Proc_ID] [Update_Proc_Id] To [Var]

» From_fieldnumber is the field in the current file (pMain_file) from which the relation starts. The provided procedures will only be executed when this field is changed. We also refer to this as the trigger field. Instead of a field number, you can also specify @_Any_Field. This will cause the dependency to be executed whenever any field in the record changes. » To_file number is the file to which the relation points (can be the same as pMain_file). » To_fieldnumber is the field to which the relation points. » The relation_ID identifies which foreign key pointing to the speci- fied parent should be used. For standard DF-File relations, this should be 255. If there is no relation between the files, you can specify a 0 (also with inner file relations). » Create_Proc_Id is the procedure performed when a record is created. » Delete_Proc_Id is the procedure performed when a record is deleted. » Backout_Proc_Id is the procedure performed when an update is made to an existing record. This procedure is executed with the old values in the record buffer. It should be the inverse of the update procedure. » Update_Proc_Id is the procedure performed when an update is made to an existing record. Now the record buffer contains the new values. It should be the inverse of the backout procedure. When creating a new record, Update_Proc_Id is executed as well as the Create_Proc_Id. When deleting a record, both De- lete_Proc_Id and Backout_Proc_Id are executed. So, the Cre- ate_Proc_Id and Delete_Proc_Id procedures should contain ac- tions that are valid only when creating or deleting the record.

Page 6.28 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary Dependencies

» The Purge_Proc_Id will be executed when you purge a record. This can only be done in batches and should be used if you want to delete “old” mutations without updating the grand total. When doing a purge, only this message will be sent.

Example: The standard set-up for an inventory/sales file would be that every sale would effect the inventory. But when deleting all sales over five year old, this shouldn’t raise the current inventory. In this case the purge function would be used.

When specifying the dependency, the first four parameters must have a valid value. If you don’t want to use one of the procedures you can pass 0. Often only the backout and update parameters will be used.

The return value for this function is an integer specifying the Depen- dency_ID. This can be used with mAdd_Trigger. If you need this number, you should place the Get pCreate_Dependency in mInit_DDO before the forward send.

Example: Procedure mInit_DDO Local Integer Dependency_ID Get pCreate_Dependency ...... To Dependency_ID Send mAdd_Trigger Dependency_ID Field [File.Field] End_Procedure

If you have no need for the dependency ID, you could specify the get at the object level, specifying VOID as the destination for the return value.

Example: Get pCreate_Dependency ...... To VOID

Default: None

6.6.2. Add Trigger Field A dependency as specified by pCreate_Dependency is triggered by the “from” field. But sometimes, a dependency should actually be triggered by a changes in any of a group of fields.

Example: A dependency between order-header amount and total-ordered at customer level is obviously specified from the amount field. However, if the customer ID changes, this dependency should also be triggered (subtract the amount from the total in the ‘old’ customer and adding it to the new one).

A dependency from orderline amount to the total header will problaby be triggered by change in price or in number of items as well.

If you want to keep a date-stamp for changes, you could use mAdd_Trigger to set up a list of fields that should cause a date stamp to be placed. Any other field could be changed without a date stamp being placed. An example of this would be in a customer file where you would want to keep track of changes in ‘important’ information like credit-limit, but would not care about let’s say address.

You can specify additional fields to trigger a dependency using the dependency ID returned by pCreate_Dependency.

Syntax Send mAdd_Trigger_Field [Dependency_Id] [Field_Number]

Alternate: Send mAdd_Trigger_Field [Dependency_Id] Field [File_Name.Field_Name]

6.6.3. Pre-defined depend- A number of standard procedures are supplied for easy definition of ency procedures dependencies. These procedures are described below in the follow- ing paragraphs.

Warning: The paragraph names are the procedure names without the prefix (m) and underscores, as is the convention throughout this manual.

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.29 Chapter 6: Data dictionary Classify Handbook Dependencies

6.6.3.1. Add Number Add the value of the relating field to the value of related-to field, using number-arithmetic.

6.6.3.2. Subtract Number Subtract the value of the relating field of the value of related-to field, using number-arithmetic.

6.6.3.3. Add Integer Add the value of the relating field to the value of related-to field, using integer-arithmetic.

6.6.3.4. Subtract Integer Subtract the value of the relating field of the value of related-to field, using integer-arithmetic.

6.6.3.5. SpecSerNr This procedure can be used to issue serial-numbers for child-re- cords (e.g. an invoice-line number). It increments the value of the related-to field and stores the new value in relating field.

6.6.3.6. SerNr This procedure can be used to issue unique serial numbers to new records. It increments the value of the related-to field and stores the new value in the relating field. This function should be used when relating to a system file (one record). There should be no DF-File relationship between the main file and the related-to file.

6.6.3.7. SetHighVal This procedure will set the value of the related-to field to the highest value of the relating and the related-to field.

6.6.3.8. SetLowVal This procedure will set the value of the related-to field to the lowest value of the relating and the related-to field.

6.6.4. Creating dependency We expect that this list of predefined procedures will grow, but you procedures can also create your own dependency functions. Any dependency procedure should have the following arguments:

Syntax: Procedure Name Integer From_field String Field_value Integer To_file ; Integer To_field Integer Update_object Integer Parent_State

Where: » From_Field is the field that is specified as trigger field in the pCreate_Dependency. » Field_Value is the value of the From_Field. During backout and delete, this will be the ‘old’ value. In update and create, this will be the ‘new’ value. » To_File is the file specified in the pCreate_Dependency. » To_Field is the number of the field specified in pCreate_Depend- ency. » Update_object is the address of the DDO for the file to update. » Parent_State is TRUE if a parent record has been found. If no relationships exists or no parent record was found, it will be FALSE.

All these parameters are passed automatically.

If there is a relationship between the main file of the current data dictionary and the file the dependency is pointed to, Classify will perform a relate to position the correct record in the buffer. If there is no relationship, Classify will leave this up to you (unless it is an innerfile relation, in which case the source and destination will be the same). Please make sure to find the correct record using the messages defined the the file handler.

Warning: Doing direct file-buffer manipulations might cause data cor- ruption since Classify provides intelligent buffering of writes while the database is locked. The CLEAR command could easily wipe out data ready to be saved. Sending mClear_File would first save pending data and clear after that.

Page 6.30 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary Dependencies

Warning: Before the relational procedures are executed the database will be locked and the record-buffer will be filled with the current record. This means you can directly access the field in the record buffer, but only for this file. It also means that you should never implement any form of user interactions in these procedures, since this might suspend multi-user - tions.

6.6.4.1. Update Field Whenever you want to update the field a dependency is pointed “to”, you should use this message. Use of this message will make sure that any dependencies specified for this field are executed as well.

Example: If you specify a dependency between Line.Amount and Order.Total and between Order.Total and Cust.Order_Amount, a change in Line.Amount would trigger the first dependency. If this send mUpdate_Field to update Order.Total, this will in turn trigger the dependency to Cust.Order_Amount.

This message should be sent to the data dictionary of the file the dependency points to. The last argument passed is the ID of this object.

Warning: Only if a dependency points to itself, you should not use the mUpdate_Field but use pField_Buffer to update the buffer directly. Please note that any inner-file relation specified us- ing @_Any_Field points to itself.

Example: Procedure mAdd_number Integer From_field Number Field_value Integer To_file ; Integer To_field Integer Update_object

Local Number New_value //*** The new value to place in the field

//*** Add the Field_value to the record to update Get pField_Buffer To_File To_Field To New_Value Calc (New_value + Field_value) To New_value Send mUpdate_field To Update_object To_field New_value End_procedure // mAdd_number

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.31 Chapter 6: Data dictionary Classify Handbook Synchronisation

6.7. Synchronisation Sometimes the need exists to update a specific file with changes from the same file at another location. For example, when Calvin Consultancy updates Classify with a new version, some errors may have been added or changed in the error-file. In case one error has been added by Calvin, you wouldn’t mind adding this error manually to your own error-file. But when the number of errors added or changed would exceed, say 15 or 20, some typing-resistance could easily arise, especially when every update of Classify introduces more additions and/or changes to the error-file.

In this situation a synchronisation-tool would come in handy. This tool should be able to: » detect changes Calvin Consultancy has made to all the system- files (HDS*.*); » create some sort of export-file with these changes and at your place, add those changes to your system-files. » More general, this tool detects changes in files at one location and updates the same files in another location with these changes.

6.7.1. Requirements In order to make use of synchronisation features, you will need to make some changes to the data files you’ll want to synchronise. You might also want to take a look at some of the fields in the system file. And depending on the level of synchronisation, you will also need a number of ASCII files.

6.7.1.1. Data-files The file-definition of every data-file has to be expanded with 5 extra fields: » date of creation (D) » time of creation (N6) both are needed to register the time of creation of a specific record. » date of last change(D); » time of last change(N6); these are both needed to keep track of the exact time of the last change. » delete-flag (A1); whenever a record is deleted it should not physically be deleted until the synchronisation-files are created. So, this flag indicates whether the record has been deleted.

6.7.1.2. The system-file The system-file should keep track of the following: » The date and time when the last update was made. Keeping this date and time enables the program, which is respon- sible for logging the changes, to check if a record is changed in the period since the last update. In fact, this information is only needed by the system-file in the database being changed (that would be: at Calvin Consultancy). But, when changes are to be passed from your place to yet another place, you too would need this information. » The date and time of the last synchronisation. This information is kept to check if changes which are brought in via the synchronisation-files have taken place after the last synchronisation. In contrast with the update-date and time, this information is typically kept in your system-file. » The date and time the application was last activated; Of every change that is made to records of files which should be synchronised, the exact time is kept in the record changed. Therefore it is very important that an application cannot be fired at a time which lies before any change in one of the files. So, actually the time and date on which the application is shut down should be saved. Unfortunately, computers have the nasty be- haviour of locking up, so time and date would not be saved. » A name (path included) where to store or find update-files.

Page 6.32 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary Synchronisation

6.7.1.3. Data dictionaries In the data dictionary objects of the files you want to synchronise, you will have to set the following properties: » pDelete_flag The number of the field that holds this flag. » pCreate_date_field The number of the field that should hold the creation date. » pCreate_time_field The number of the field that should hold the creation time. » pUpdate_date_field The number of the field that should hold the update date. » pUpdate_time_field The number of the field that should hold the update time. » pSync_Level This should have one of the following values: ° @_None No synchronisation. ° @_Base_Level Keep track of changes per record and create mutation files peri- odically. ° @_Field_Level Keep track of changes on field level and output synchronisation file immediately. ° @_Audit_Trail Keep track of all changes writing both old and new values to the synchronisation file, including a User_Id (old values and User_Id are ignored during synchronisation).

Syntax: Set pDelete_Flag To [Field_Number] Set pCreate_Date_field To [Field_Number] Set pCreate_Time_field To [Field_Number] Set pUpdate_Date_field To [Field_Number] Set pUpdate_Time_field To [Field_Number] Set pSync_Level To @_None|@_Base_Level|@_Field_Level|@_Audit_Trail

Alternate: Set pDelete_Flag To Field [Field_Name.Field_Name] Set pCreate_Date_field To Field [Field_Name.Field_Name] Set pCreate_Time_field To Field [Field_Name.Field_Name] Set pUpdate_Date_field To Field [Field_Name.Field_Name] Set pUpdate_Time_field To Field [Field_Name.Field_Name]

Example: Object oCustomer_DDO is a cData_Dictionary Set pMain_File To Cust.File_Number Set pMain_Index To Index.1

Set pDelete_Flag To Field Cust.Delete_Flag Set pCreate_Date_Field To Field Cust.Create_Date_Field Set pCreate_Time_Field To Field Cust.Create_Time_Field Set pUpdate_Date_Field To Field Cust.Update_Date_Field Set pUpdate_Time_Field To Field Cust.Update_Time_Field

Set pSync_Level to @_Base End_Object

If you set the pSync_Level property, Classify will check whether all other properties are set as well. If not, an error will be generated and the pSync_Level will be rest to @_None.

6.7.2. Effects The synchronisation features will have an effect on all file opera- tions. The exact effects are specified in the upcoming sub-para- graphs.

6.7.2.1. Adding records If a record is added, the fields which hold the date and time of creation are to be filled. At the same time, the fields which keep trackofdateandtimeofupdatehavetobefilledtoo.

6.7.2.2. Changing records In case a record is changed, both the update date and the time-field are filled with the current date and time. If you want to change the key, this is only allowed if the creation date/time is after the date/time of the last synchronisation file created. This also means that key- changes are prohibited for levels @_Field_Level and @_Audit_Trail.

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.33 Chapter 6: Data dictionary Classify Handbook Synchronisation

6.7.2.3. Deleting records Whenever a record is deleted, it should not automatically be physi- cally deleted. First the creation-date and time of the record have to be compared to the date and time of the last update. When the record has been created after the last update was made, the record may be physically deleted, otherwise the delete-flag has to be set to true.

This means that all Classify programs should recognise a delete-flag and know how to react to it. In all pre-defined packages, the con- strain procedure will automatically detect the fact that a file is synchronise and skip deleted records. If you process files manually, you should keep track of this yourself.

Another side effect of turning on synchronisation is that if records are not physically deleted, the key-value still exists in the system even if the record has been deleted. This means that it will be impossible to re-create a record until the purge process has been executed.

6.7.3. Procedures In order to synchronise two databases, you will need to create a delta-file (= a file containing the differences) on one database and read this file in using the other database. Also, you will need a batch to physically delete flagged records. These three batches are lo- cated in the report pull-down of the System program.

6.7.3.1. Creating update-files The process of making update-files is very easy. From every file in the filelist, for which a data dictionary is specified, every record will be scanned. If the record was changed after the time the previous update was made, all fields of the record along with the date and time of change will be logged to an update-file.

After this process has finished, the system file will be updated with the date and time on which this update was made.

The update-file will be named exactly as the DataFlex-file, but with the extension .SYN. So changes to the Classify-error-file will be logged to the file HDSERR.SYN.

6.7.3.2. Processing update-files You will need to transfer the SYN files to the remote system in order to be able to update the files.

Again a batch will take every file in the filelist and check if a data dictionary is present. If so, the .SYN-file is opened and read. For every record found, the batch will try to find the record in the .DAT-file. Is the record found and if the update date/time in the synchronisation file is later than the date/time in the master file, it will be changed according to the update-file and saved. In case the record is not found, a new record will be created.

Whenever a .SYN-file has been processed completely, it will be deleted.

6.7.3.3. Purging records If the last two steps have been executed both databases might contain some files with records where the delete-flag is set to true. In order to physically remove these tagged records, a third batch should be run.

This batch will present you with a choice of files for which a data dictionary is present. Selecting one of the files will cause the batch to scan that file and it’s childfiles for delete-tags. If a record is found to have been tagged as deleted, it is now really being deleted with help of the data dictionary. Using the data dictionary ensures that Classify-dependencies are executed.

Page 6.34 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary Synchronisation

6.7.3.4. Writing the synchronisation Since the synchronisation batches need information from the data program dictionaries, you will need to “write” the synchronisation program yourself. This is far easier than it seems. You will have to create a standard Classify program with three batches and the data diction- aries for all synchronised files.

Example: Use Class_De Use BatchSub

Object oDesktop is a cDesktop No_Image

Use_Extend Cust.DDO Use_Extend Parts.DDO Use_Extend Deliver.DDO

Use_extend Syncmk.BTC

Object oMake_update_file Is A cMake_update_files No_image End_object

Use_extend Syncupd.BTC

Object oUpdate_synchronised Is A cUpdate_synchronised No_image End_object

Use_extend Synccln.BTC

Object oClean_synchronised Is A cClean_synchronised No_image End_object

End_Object

Start_Ui oDesktop Abort

6.7.4. Using synchronisation To use the synchronisation-facilities, you will have to do the follow- ing: » change the data-files which you want to be recognized by the synchronisation-tools; » change the DDO’s for these files (set the properties); » recompile the programs using the changed DDO’s.

Warning: If you want to synchronise files that have dependencies to other files, make sure you select these other files for synchro- nisation as well. If you should not do this, it will cause your database to become corrupt. The synchronisation levels should not necessarily be the same.

6.7.5. Advanced use The standard method as described above (level @_Base), works fine when you are only interested in copying changes from one database to another. However, if you would like to have some sort of audit-trail, this method does not work because even when only one field has changed, all other fields in a record are exported via the .SYN-files.

A better solution would be to export only the changed fields. This is done by setting the pSync_Level to @_Field_Level.

The second thing you would need to do is to skip the phase of writing the SYN file by using the batch. The file that is now constantly being updated should be distributed. The batches for reading the SYN files and for purging records can still be used.

If you want still more control, you could set the pSync_Level to @_Audit_Trail. This will also cause a log file to be created con- stantly, but now, this file will also contain the old field values and the user-id of the person making the change.

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.35 Chapter 6: Data dictionary Classify Handbook Linked lists

6.8. Linked lists The main mechanism in DataFlex for finding records is the use of indices. However, at times we are only interested in keeping entries (records) in a specific order, without having an explicit ordering. Introducing such a “line number” might even be unwanted because it makes insertion of data very hard.

In these cases, a “double linked list” is a very valid way of ordering the data. A double linked list is a mechanism where every record keeps a pointer to the previous record and the next record.

Classify can support double linked lists. To do this, you will need to add two fields to the file. The length of these fields should be able to (total_length_of_key + nr_of_segment + 1). Next, in the data dictionary, you must identify these fields using the properties pPre- vious_Key_Field and pNext_Key_Field.

These fields will be set to noenter automatically and no validations or dependencies are permitted in them. Neither can they be part of the key of the file.

Data entry for linked-list files is done through a subsystem with a multi-line entry object in it. You can do this on “top” level, or nested within another subsystem (say telephone calls within customer). However, you can not mix the usages. So youeitherneedtobuild the linked list in an “unrelated” environment, or as a child to a given parent (in which case there are actually a number of unrelated lists in the file; one per parent record).

To allow the data dictionary to check whether it can allow insertion of new records or not, you have to specify this “environment” by setting the pLink_Parent and pLink_Relation properties. If pLink_Parent is set to 0, a “top level” environment is assumed.

Inthesubsystem,youhavetosetthefindmodeto@_Link.

Syntax: Set pPrevious_Key_Field To [Fieldnr] Set pNext_Key_Field To [Fieldnr] Set pLink_Parent To [Parent_File|0] Set pLink_Relation To [relationNr]

You can totally disable the support for double linked lists using of the compiler options in Usage.Inc. However, if you have set the above properties and you have disabled the double linked list sup- port, it will be impossible to create records in the file.

Note: Access to these file through indices will still remain possible. The double linked list is just another way to access the data. However, the double linked list records can only be created in multi-line subsystems. Editing can be done in form oriented subsystems.

Important: It is impossible to perform key changes or tree copies on the linked list files.

Page 6.36 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary File modes

6.9. File modes The LOCK command in DataFlex will operate on all open files. While this is a very “safe” approach, it also means that at times, files will be unnecessary locked. In DataFlex 2.3 many developers therefor manually set the files that were not written to read only, thus preventing them from being locked.

In DataFlex 3.0, where programs tend to open many more files, a similar strategy would seem even more beneficial, but unfortunately also more complex to achieve.

However, the unique control Classify provides over file updates, has enabled us to implement this feature fully transparent. All the files opened through a DDO will be set to read only by the DDO. During the validate phase prior to a delete or save, Classify builds a list of files that will be affected. If the validation fails, the list is rest.

Once the intelliwrite session is started, Classify will toggle the file mode for all these files before issuing the lock. Once the operation is completed (stop intelliwrites), the database is unlocked and the files are set to read only again.

Testing has proven that the performance gain on multi-user plat- forms is dramatic. Also, the number of locks in use will be dramati- cally reduced.

This feature effectively inhibits all the write operations outside intel- liwrites. Please refer to the appendix about file handling for a more detailed discussion on Intelliwrites.

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.37 Chapter 6: Data dictionary Classify Handbook Retain templates

6.10. Retain templates It is possible to specify “retain templates” in the DDO. A retain template is basically a named set of fields that should be retained. The template is build using:

Syntax: Send mAdd_Retain_Field [Template_Name] [Fieldnr]

There can be as many fields added to a template as required, there can be as many templates as required. Per VIEW a template can be “set”. This is done by

Syntax: Set pRetain_Template To [Template_Name]

This will cause a message to be send to all subsystems in the view. These will all inquire at the DDO for the existence of a retain template with that name and if existing, apply it. This means that the issue of retain-temple names should be handled on a project wide basis and one template can spawn multiple files by being specified in multiple DDO’s by the same name.

Example DDO code: Send mAdd_Retain_Field “T1" Field HDSERR.Error_Tp Send mAdd_Retain_Field ”T1" Field HDSERR.Choices Send mAdd_Retain_Field “T2" Field HDSERR.BELL Send mAdd_Retain_Field ”T2" Field HDSERR.FATAL

Example view code: Class cHdserr_view Is A cView Procedure Construct_object Integer Image Forward Send Construct_object Image Set pId To “HDSERR” On_Key Key_Ctrl+Key_T Send mT1 On_Key Key_Ctrl+Key_Y Send mT2 End_procedure // Construct_object

Procedure Construct_children Forward Send Construct_children Object oHdserr_sbs Is An cHdserr_sbs No_image End_object // oHdserr_sbs End_procedure // Construct_children

Procedure mT1 Set pRetain_Template To “T1" End_Procedure

Procedure mT2 Set pRetain_Template To ”T2" End_Procedure

End_class // cHdserr_view

As can be seen from this example, setting templates is dynamic.

Page 6.38 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 6: Data dictionary Run time set-up

6.11. Run time set-up While most of the time, the DDO’s are coded, they are realy dynamic in nature. This means you can control the DDO settings during program load. We have implemented one setting as an example of how you can do this. Based on user feedback, future version might support more generic settings, but you can also use this example to implement your own runtime settings.

The basis for the runtime settings is a text field in the HDSRGT file. You can modify this field using the SYSTEM program. It can contain settings following the INI file conventions. Per field, a section is created and the setting for that field are set in this section.

Currently, only one keyword is supported: USAGE.

6.11.1. Usage This keyword is used to identify the usage of a field. The following settings are valid: » Not_Used This setting will eliminate all validations for the field (including relationships) and make the field no-enter. » Required This will make the field required. If there is already a validation on the field, nothing happens.

This setting is designed especially to allow you to configure fields in a “standard” database based on the end-user requirements without recompiling.

Syntax: [Fieldname] [Keyword] = [Value]

Example: [Name] Usage = required

[Discount_Group] Usage = Not_Used

This feature can be disabled using the compiler option USE$DDO$INI from the file USAGE.INC.

(c) '92 - '95 Calvin Consultancy May 1995 Page 6.39 Chapter 6: Data dictionary Classify Handbook Summary

6.12. Summary The data dictionary provides a set of business rules for your data- base. A number of special messages allows you to set up these rules. The data dictionary will enforce these rules automatically, acting like a sort of ‘quality control’ department.

Classname: cData_Dictionary

Base class: Message cFile_Handler cData_Dictionary_Procedures

Package file: DataDic.PKG

Filename suggestion: XXXXXXX.DDO

Where XXXXXXX is the filename of the datafile.

Include command: Use_Extend

Mandatory properties pMain_File pMain_Index

Special remarks: Data dictionary objects should be created inside the Classify desk- top object. Because, by design, there can only be one data dictionary object per file, this is the one place where we can actually place a lot of information in the object itself.

If there are validation or prompt messages you use multiple times, you can either create your own sub-class of the data dictionary, or you can multiple inherit them.

Page 6.40 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry

7. Data entry In Classify, data entry is handled by a variety of classes that can be divided into three groups: » views; » subsystems; » zooms.

The view is a container for (multi-file) data entry modules (equivalent to ‘old style’ programs who will be called from a menu). Views are usually listed as functions in the Function pulldown from Classify.

The view is made up of (multiple) subsystems. A subsystem is a container for zooms that allow data entry for a single file. A very important concept in Classify is that each subsystem contains only information about one single file. If information is needed from other (related) files, you’ll need to nest a subsystem per additional file.

The zooms are the data-entry modules. These will contain one or more of the fields from the main file for the subsystem they are in.

A typical data entry structure would look like this:

Object Customer_View is a cView Object Customer_Subsystem is a cSubsystem Object Customer_Find is a cEntry_Find Object Address_Zoom is a cEntry_Zoom Object Sales_Zoom is a cEntry_Zoom Object Invoice_Subsystem is a cSubsystem Object Invoice_Find is a cMulti_Line_Entry Object Invoice_Line_Subsystem is a cSubsystem Object Invoice_Line_Find is a cMulti_Line_Entry Object Invoice_Line_Detail_Zoom is a cEntry_Zoom

Please note this is not a code example but just reflects the structure of the program.

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.1 Chapter 7: Data entry Classify Handbook Zooms

7.1. Zooms A zoom is the smallest unit in a data entry module. A zoom will contain one or more fields from the main file of the subsystem the zoom is contained in. Zooms come in different ‘flavors’. We have supplied a number of zoom classes that will fit different situations and field-types.

7.1.1. Creating zooms Classify will use class-definitions where ever possible. This gives you the opportunity to easily re-use your code. This effectively means that we will create classes for almost anything and then just create an object specifying only object/end_object.

So, when we are talking about specifying zooms, we are actually talking about creating our own subclasses of the zoom class. These class definitions are then stored in seperate files for easy use over several programs. Although you can use any naming scheme you wish, we have included suggestioned naming conventions.

We will be discussing some examples of zoom-class definitions as we go along in this chapter.

7.1.2. General characteristics Before we go over the zoom classes and their specific charac- teristics, we will list a number of common methods and properties. Also, we will discuss the images attached to the zooms.

In Classify, we have implemened a method that allows you to specify images per zoom class and re-use that image multiple times. This means you only need to create an image once, even if you want to create two or more objects of the same zoom class.

The implementation of this technique relies on a combination of compiler and runtime procedures. The new DYNAMIC_IMAGE com- mand plays an important role in this. Another important requirement is the use of one file per image.

Windows: DYNPRESS Creating input forms using character mode DataFlex has always been very easy and straight forward. The complexity of Windows, with different fonts, different resolutions and different screen sizes seemed to put a final end to this.

Using visual design tools seems to be the industry standard re- sponse to this problem. However, this approach has one major drawback: it limits the end-user to the font, resolution and screen layout designed by the developer. In character mode applications, this was expected. The huge amount of user-configurability of Win- dows however seems to contradict this development.

Since Classify has always allowed for end-user configuration, we felt it was especially important to do this for Windows as well. To allow full flexability, we designed a form specification algoritm that pro- vides ease of design as well as end-user functionality.

We have called this system DYNamic PRESentation Specification and it is based on the conceptual design of images. Most images are designed using rows and columns. Some information might spawn multiple columns, and most columns will have different widths, depending on the data, but almost all forms will use “guide lines” to position the information.

DYNPRESS images are specified using row and column numbers only. The width, height and relative positioning of the entries (de- scription and entry) are calculated at runtime using the current configuration. This means that DYNPRESS will even adapt your screen design automatically not only when the user selects a differ- ent font but also when the length of the data field in the database or the length of the description is changed. Since DYNPRESS is aware

Page 7.2 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry Zooms

of proportional fonts, no clipping will occur in the descriptions, and excessive whitespace is suppressed.

The length of entry fields is calculated using a number of configur- able parameters, so that a good average width is presented, depend- ing on field length and attributes like capslocked or not.

In the appendices, there is an extensive discussion on DYNPRESS and how you can configure it, as well as additional messages you can use to configure your DYNPRESS zooms

7.1.2.1. ID This string property contains the unique identification for a zoom. It is used in the help- and authorisationsystems. It is also used to determine the text displayed in the options pull-down. To determine this text, the cSubsystem class first tries to find this ID in the help-descriptions file. If found, the short description given is used in the pull down. If no entry for this ID is found, the literal ID is displayed in the pull down.

A zoom ID can have any length, but only 8 characters are used by the file system and 15 are used in pull-downs.

Syntax: Set pID To [Val]

7.1.2.2. Auto Activate State If this property is set, the zoom will automatically be activated when the subsystem is first activated. From that point on, the user can toggle the active state at will. The property only sets the default to “activate” when the program is loaded.

Syntax: Set pAuto_Activate_State To_[True|False]

Default: True for find objects, false for all others.

Note: You can also set the ‘auto activate’ per zoom using the authorisation and configuration system. This will not require recompilation and will also allow you to set it depending on the user.

Windows: If you are using the View Panel class in the Windows environment, you will find that this property also effects the visual representation of the zoom. Please see the view panel class description for a more in depth discussion.

7.1.2.3. Button Bar You can set this property to identify the button bar you want to display when this field has the focus. The contents of the buttonbar should be specified in the buttonbar & menufile.

Syntax: Set pButton_Bar To [String]

7.1.2.4. Location The pLocation property is intended to provide a transparent move from Charactermode to GUI versions. In CM versions of Classify, the arguments are identical. In GUI versions, the arguments of pLocation are converted to the correct locations based on the active map mode and then set. We suggest you use the pLocation as much as possible.

Windows: Since it is very hard in Windows to convert character based locations to pixels, we suggest you use the drag & save feature as much as possible in Windows. Classify will allow you to store different loca- tions for charactermode and windows. However, GUI-locations are stored in pixels. So switching resolutions can provide some prob- lems in that situation.

Syntax: Set pLocation To [Row] [Column]

7.1.2.5. Version This is a general property that can be used for version control. It is available in every major class and can be retrieved by an end user using the Version Information function [Ctrl][F1].

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.3 Chapter 7: Data entry Classify Handbook Zooms

Syntax: Set pVersion To [Number]

Default: 0.0

7.1.2.6. Create Item This function is the Classify alternative for the ENTRY_ITEM command. It offers a number of advantages over the standard ENTRY_ITEM command: » Provide source code compatibility between CM and GUI-ver- sions » Reduced usage of message area » Returns the number of the created item and thus allows for generic programming.

This function will take the file and fieldnumber as arguments and create an item for that field. To set additional options or a zoom-spe- cific field message, you can use the standard properties.

Example: Class cZoom is a cAny_Zoom Procedure Construct_Object Integer Image Forward Send Construct_Object Image

Local Integer ItemNr Get pCreate_Item Account.File_Number Field Account.Credit To ItemNr Set Item_Entry_Msg Item ItemNr To Msg_Verify_User_Level Get pCreate_Item Account.File_Number Field Account.Last_Change To ; ItemNr Set Item_Options Item Item_Nr To ; (Items_Options(Current_Object,ItemNr) IOR @_NoEnter) End_procedure End_Class

If you don’t need the item number, you can direct the output to VOID.

Example: Get pCreate_Item Cust.File_Number Field Cust.Name To Void

The full syntax of this message is:

Syntax: Get pCreate_Item Filenumber Fieldnumber To Var

Alternate: Get pCreate_Item Filename.File_Number Field Filename.Fieldname To Var

Windows: In Windows, the items created using the create item syntax are automatically placed in consequetive rows, in column 0. The de- scription object will be displayed in style 0; the entry object in style 1. However, in tables the styles used are 2 and 3 respectively.

7.1.2.7. Create DYNPRESS Item This message is an extension over the standard Create Item mes- sage that allows you more control over the DYNPRESS algorithm. Apart form the definition of the file and field, you can now also specify the row and column for the description & entry field. Both row and column numbers start at zero.

Even if you are not yet using a GUI version of Classify, using this message provides you with the option to prepare your application for future conversion to the GUI version.

Syntax: Get pCreate_DYNPRESS_Item Filenumber Fieldnumber Row Column To Var

7.1.2.8. Create DYNPRESS Style Item This is the fullest version of the create item messages. It allows you full control over the DYNPRESS mechanism. You can supply the following arguments: » Filenumber As above » Fieldnumber As above » Row As above » Column As above » Display length The length of the actual entry field. This is especially important

Page 7.4 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry Zooms

if you display non-database information (see next paragraph). If this is left zero, the length of the data field is used (or 24 for non-database information). » Field style The presentation style for the entry field » Description the description to use. If you leave this field empty (“”), the field name as specified in the CFN file is used. If you want to suppress the description, you should specify an at-sign (“@”). » Description style The presentation style for the entry field

Syntax: Get pCreate_DYNPRESS_Style_Item Fieldnumber Filenumber ; Row Column Display_Length Entry_Style Description Des_Style To Var

7.1.2.9. Displaying other information If you want to display information that is not stored in fields of the main file, you can use DataFlex expressions to do this. You can specify any expression using the following syntax:

Syntax: Get pCreate_Item @_Expression [Expression]

You can also use pCreate_DYNPRESS_Item or pCreate_DYN- PRESS_Style_Item in a similar fashion. In all cases except the last we will use 24 as the display length.

Since DataFlex limits the use of the expression evaluator at runtime to standard DataFlex functions and custom functions without argu- ments, we suggest you create special functions in the DDO’s that can provide additional information.

The function would now execute whenever you find a record. If you also want to re-evaluate the function if some field changes (data entry, selection from prompt, program control, default value etc), you can specify “trigger fields” for the expression.

DDO example: Function pCountry_Name Returns String Local String Country_Name // Retrieve the name from the related file, normal table or otherwise Function_Return Country_Name End_Function

Zoom example: Get pCreate_Item FileField Customer.Country To Void Get pCreate_Item @_Expression ; EXP (pCountry_Name(pData_Dictionary(Current_Object))) To ItemNum Send mAdd_Item_Trigger ItemNum Field Customer.Country

Note the EXP keyword and the absence of quotes around the expression. Please refer to appendix D for more information about the EXP keyword.

Since you will often have the preceding field as trigger, we offer a shortcut as well, that will automatically setup the trigger based on the previous field.

Zoom example: Get pCreate_Item FileField Customer.Country To Void Get pCreate_Item @_Derived ; EXP (pCountry_Name(pData_Dictionary(Current_Object))) To ItemNum

This would also setup the trigger for Customer.Country.

Of course, you can have as many triggers per expression as you want. The only constrain is that the triggers should be fields within the same zoom as the expression.

The expression can be as extensive and complex as you want, and the same goes for the function in the DDO (or in the subsystem or zoom if that would be more appropiate). The following example is a bit more extensive.

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.5 Chapter 7: Data entry Classify Handbook Zooms

DDO example: Function pCredit_Check Returns String Local Number Order_Amount Local Integer Parent_Found Local String Result

Get pRelate Customer.File_Number 255 0 To Parent_Found If Parent_Found Begin Get pLocal_Field_Value Field Order.Amount To Order_Amount If (Customer.Credit_Limit - Customer.Outstanding) Gt Order_Amount ; Move “Order okay” To Result Else ; Move “** CREDIT LIMIT EXCEEDED **” To Result End Else ; Move “Customer not found” To Result Function_Return Result End_Function

7.1.2.10. Effect You can apply a three dimensional border to a zoom. However, in general, this will only be usefull if the zoom is contained inside a view panel and is auto-activated.

Please see the description of the view panel class for more details.

Syntax: Set pEffect To Style

7.1.2.11. Duplicate fields If you use the same field in multiple zooms (inside the same subsys- tem), Classify will detect this and automatically keep the two fields synchronised. So there is no need to specify “dependant items”.

7.1.2.12. Images Classify provides a scheme which will make image definitions reuseable, just like the class definitions. So for every data entry object class-definition, you also must specify an image definition. This image definition must be placed in a seperate file. We use a combination of compiler and runtime techniques to achieve reuseability of images and you need to stick to these guidelines to avoid problems. We suggest you use the same file name as for the class definition, but change the extension to IMG.

The Windows version will ignore the image files.

Page 7.6 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry Zooms

7.1.3. Entry find The entry find zoom is designed for record-oriented file mainte- nance. Its parent class is the DataFlex ENTRY class. This means that all entry-related syntax and properties apply. So properties like OPTIONS, ITEM_VALIDATE_MSG and PROMPT_OBJECT can be set. However, this class communicates with the data dictionary (through the subsystem) to set the options specified in the data dictionary and to perform validation and prompts defined in the data dictionary.

If you specify options in the zoom, it will always mean these options are added to the options already set in the data dictionary. The field-messages (validate, entering and exiting) are also ‘added’ to the ones in the data dictionary. That means that both the locally specified messages are excuted and the functions set up in the data dictionary are called.

Warning: The locally specified procedures are handled by the ENTRY class itself, so they act according to the DataFlex documenta- tion. This means they have to be specified as procedures and there are no arguments passed on the command line.

Note: If you want to, you can access the local file buffer from within locally specified field-procedures.

The entry find class is designed to hold all the fields the user would need to be able to find and identify a record. These will mostly be indexed fields, but might also contain some additional, non-index information to help the user identify the record.

The entry find class distinguishes itself from the entry zoom class (which will be discussed later) by allowing navigation from one item to another without validating. Only if data is entered in an item or the user tries to leave the object, the items are validated. This is done so the user can easily navigate to the correct field to start the find operation.

For every subsystem, there should only be one find-object. This is also the object that will always be activated whenever the user activates the subsystem (actually, to the end-user it might appear to be the subsystem). Deactivating the find-object will deactivate the entire subsystem (including all its children).

7.1.3.1. Image definition The image definition for the entry find is similar to a standard DataFlex image definition, except that it will have no image name. Instead of that, it should contain the DYNAMIC_IMAGE keyword.

Example: Dynamic_Image Code:_____ Name:______City:______/*

7.1.3.2. Summary The following details apply:

Classname: cEntry_Find

(Super)Parent class: EntryList

Package: EntFind.PKG

File name suggestion: XXXXXXY.FND Where XXXXXXX is the name of the data file and Y ranges from A to G.

Include command: Use_Extend

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.7 Chapter 7: Data entry Classify Handbook Zooms

Example: Class cCustomer_Find is a cEntry_Find

Procedure Construct_Object Integer Image Forward Send Construct_Object Image Set pID To “CUST_A”

Item_List Entry_Item Custom.Code Entry_Item Custom.Name Entry_Item Custom.City End_Item_List

End_Procedure

End_Class

Note: It is our opinion that to provide maximum flexibility to the end-user , we should create zooms as small as sensible and let the user ‘customize’ his own desktop. Although this opinion is reflected throughout our examples and system maintenance programs, you can create larger zooms on your own discretion (even full-page zooms are possible using Classify).

Page 7.8 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry Zooms

7.1.4. Multi-line find The multi-line find class is the ‘tabular’ counterpart of the entry_find. All of the specifics of the entry find class are available in the multi-line entry as well. The only difference is that the multi-line entry class supports ‘multi record’ displays.

In the definition, you must provide the ENTRY_ITEM command for all fields that should be displayed per record. The actual number of windows in the image will determine the number of records displayed at the same time. Classify will handle multiple-image-lines per re- cord. However, you might experience some problems with the auto- matic positioning of the scroll bar if you ‘split’ a record over multiple lines. In that case, you should manually set the ScrollBar_Offset (standard DAC).

Windows: In Windows, it is not possible to split the data per record over multiple lines.

If there are other zooms in the same subsystem, these zooms will always display information about the “current” record in the multi- line. The current record can easily be identified by its color, which will be updated even if the focus is not on the multi-line object.

7.1.4.1. Number Of Lines In character mode, the number of lines is determined from the image. In Windows, no image is used and the number of lines displayed is based on this property.

Syntax: Set pNumber_Of_Lines To [Val]

Default: 5

7.1.4.2. Image definition The image definition for the multi-line entry is similar to a standard DataFlex image definition, except that it will have no image name. Instead of that, it should contain the DYNAMIC_IMAGE keyword.

Example: Dynamic_Image Code Name City ______/*

7.1.4.3. Summary The following details apply:

Classname: cMulti_Line_Entry

(Super)Parent class: EntryList

Package: MLFind.PKG

File name suggestion: XXXXXXY.FND Where XXXXXXX is the name of the data file and Y ranges from A to G.

Include command: Use_Extend

Example: Class cCustomer_Find is a cMulti_Line_Entry

Procedure Construct_Object Integer Image Forward Send Construct_Object Image

Set pID To “CUST_A”

Item_List Entry_Item Custom.Code Entry_Item Custom.Name Entry_Item Custom.City End_Item_List

End_Procedure

End_Class

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.9 Chapter 7: Data entry Classify Handbook Zooms

DAC-Package Comparison: The multi-line entry class will not require the “BE- GIN_ROW/END_ROW” syntax (in fact, it will not work if you use it)

Warning: Multi-line finds can only work if the pFind_Mode of the sub- system is @_Relation or @_Index. If you set the find mode to @_Index, you should also set the pIndex property of the sub- system.

Hint: There is a special subclass of the multi-line entry called cSpecial_Multi_Line that has the ability to suppress duplicate information in consecutive lines.

Page 7.10 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry Zooms

7.1.5. cSpecial_Multi_Line This class was designed upon a special request by one of our customers and is included both for regular usage and as an example of how to subclass existing zooms to provide additional features.

The objective of this class is to allow suppression of duplicate data in multi line tables.So the following information:

Johnson Houston Drive Dallas USA Peterson Mountain View Road Dallas USA Smith Likeside view New York USA Gordon Country road Birmingham UK Smith Picadilly Circus London UK

Should display as:

Johnson Houston Drive Dallas USA Peterson Mountain View Road Smith Likeside view New York Gordon Country road Birmingham UK Smith Picadilly Circus London

The suppression can be turned on per column by setting the pSup- press_State specifying the column number (starting with 0). All other usage is identical to that of the standard multi line entry.

7.1.5.1. Image definition The image definition for the multi-line entry is similar to a standard DataFlex image definition, except that it will have no image name. Instead of that, it should contain the DYNAMIC_IMAGE keyword.

Example: Dynamic_Image Code Name City ______/*

7.1.5.2. Summary The following details apply:

Classname: cSpecial_Multi_Line

(Super)Parent class: cMulti_Line_Entry

Package: Spec_Ml.PKG

File name suggestion: XXXXXXY.FND Where XXXXXXX is the name of the data file and Y ranges from A to G.

Include command: Use_Extend

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.11 Chapter 7: Data entry Classify Handbook Zooms

Example: Use Spec_Ml

Class cCustomer_Find is a cSpecial_Multi_Line

Procedure Construct_Object Integer Image Forward Send Construct_Object Image

Set pID To “CUST_A”

Item_List Entry_Item Custom.Code Entry_Item Custom.Name Entry_Item Custom.City End_Item_List

Set pSuppress_State Item 2 To True

End_Procedure

End_Class

Special remarks: This class is not a part of the standard Classify and Class_DE packages, so if you want to use it, you must manually include the file SPEC_ML.

Page 7.12 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry Zooms

7.1.6. Entry Zoom This is the most commonly used zoom. It is almost identical to the entry find class (please check out the documentation on that class as well), except for the validation mechanism. In a zoom, every item will be validated, even if the value is a blank. Obviously, in a zoom there is no need to navigate to other fields without validation. Apart from the general properties for zooms, there are no properties or messages specified.

7.1.6.1. Image definition The image definition for the entry zoom is similar to a standard DataFlex image definition, except that it will have no image name. Instead it should contain the DYNAMIC_IMAGE keyword.

Example: Dynamic_Image Street :______City :______Zipcode:______State :__ /*

7.1.6.2. Summary The following details apply:

Classname: cEntry_Zoom

(Super)Parent class: EntryList

Package: EntZoom.PKG

File name suggestion: XXXXXXY.ZM Where XXXXXXX is the name of the data file and Y ranges from H to Z.

Include command: Use_Extend

Example: Class cCustomer_Address is a cEntry_Zoom

Procedure Construct_Object Integer Image Forward Send Construct_Object Image

Set pID To “CUST_H”

Item_List Entry_Item Custom.Street Entry_Item Custom.City Entry_Item Custom.Zipcode Entry_Item Custom.State End_Item_List

End_Procedure

End_Class

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.13 Chapter 7: Data entry Classify Handbook Zooms

7.1.7. Checkbox Zoom This class provides the facilities for data-entry of yes/no choice fields. The fields indicated in the item_list are displayed as check- boxes. The user can indicate which fields are True by ‘checking’ it by an “X”. Zero, one or more fields can be checked.

7.1.7.1. True ID This additional property holds the character that will represent a True value in the field.

Syntax: Set pTrue_ID [Fieldnumber] To [Val]

Default: ℵ

7.1.7.2. False ID This property holds the character that will represent a False value in the field.

Syntax: Set pTrue_ID [Fieldnumber] To [Val]

Default: Space

7.1.7.3. Image definition The image definition for the checkbox zoom should contain one window per field, each three characters wide.

Example: Dynamic_Image ___ Dealer discount ___ Prefered customer ___ Send orders C.O.D. ___ Send X-Mas gift /*

7.1.7.4. Summary The following details apply:

Classname: cCheckbox_Zoom

(Super)Parent class: EntryList

Package: ChkbZoom.PKG

File name suggestion: XXXXXXY.ZM Where XXXXXXX is the name of the data file and Y ranges from H to Z.

Include command: Use_Extend

Special remarks: This class is not included in the standard Class_DE and Classify pre-compiles, so you will need to put USE CHKBZOOM at the begin- ning of the zoom-definition.

Example: Class cCustomer_Shipping is a cCheckbox_Zoom

Procedure Construct_Object Integer Image Forward Send Construct_Object Image

Set pID To “CUST_I”

Item_List Entry_Item Custom.Dealer_Discount Entry_Item Custom.Prefered_Consitions Entry_Item Custom.Send_COD Entry_Item Custom.XMas_Gift End_Item_List

End_Procedure

End_Class

Page 7.14 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry Zooms

7.1.8. Radio Zoom This class is based on the cCheckbox_Zoom, but will allow only one (or none) item to be selected. Like the checkboxzoom class, the field-value is translated into a ‘check’ mark.

7.1.8.1. Image definition The image definition for the checkbox zoom should contain one window per field, each three characters wide.

Example: Dynamic_Image ___ Federal Express ___ United Parcel Service ___ Standard ground mail ___ Customer picks up parcels /*

7.1.8.2. Summary The following details apply:

Classname: cRadio_Zoom

Parent class: cCheckbox_Zoom

Package: RadiZoom.PKG

File name suggestion: XXXXXXY.ZM Where XXXXXXX is the name of the data file and Y ranges from H to Z.

Include command: Use_Extend

Special remarks: This class is not included in the standard Class_DE and Classify pre-compiles, so you will need to put USE RADIZOOM at the begin- ning of the zoom-definition.

Example: Class cCustomer_Shipping is a cRadio_Zoom

Procedure Construct_Object Integer Image Forward Send Construct_Object Image

Set pID To “CUST_J”

Item_List Entry_Item Custom.FedEx Entry_Item Custom.UPS Entry_Item Custom.Ground Entry_Item Custom.Pickup End_Item_List

End_Procedure

End_Class

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.15 Chapter 7: Data entry Classify Handbook Zooms

7.1.9. Entry Memo This class is designed to provide all edit functions for database fields of the Text type. Contrary to the Data Access Edit class, this class does require an image to be defined. This image (generally only the border lines) is used as background of the edit window. The actual editor is positioned inside this image, so there is no need to set the size of the edit object.

Important: This image should contain (at least) one underscore, or you will get a runtime error (beep)!

7.1.9.1. Main field To indicate the database field to be edited, the following syntax must be used:

Syntax: Send Read_DBMS (pEdit(Current_OBject)) [Filename.Fieldname] TRUE

As you can read from this syntax, the entry memo object creates a child object of the edit class, whose ID is stored in the pEdit property.

Warning: If you don’t set the TRUE keyword, the zoom will not function.

7.1.9.2. Begin Of Text If this property is set, the cursor will be positioned at the beginning of the text after every display (the first line of text will be the top line in the image). If it is set to False, the cursor will be at the end of the text and the display will show the last lines of text field.

Syntax: Set pBegin_Of_Text To True|False

Default: True

7.1.9.3. Image definition Usually, the image-definition for a memo object will be just a border and one underscore.

Example: Dynamic_Image

_

/*

7.1.9.4. Summary The following details apply:

Classname: cEntry_Memo

Parent class: Message

Package: EntMemo.PKG

File name suggestion: XXXXXXY.ZM Where XXXXXXX is the name of the data file and Y ranges from Z to H.

Mandatory message: Read_DBMS ...... True

Include command: Use_Extend

Example: Class cCustomer_Remarks is a cEntry_Memo

Procedure Construct_Object Integer Image Forward Send Construct_Object Image

Set pID To “CUST_Z”

Send Read_DBMS To (pEdit(Current_Object)) Custom.Remark True

End_Procedure

End_Class

Page 7.16 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry Zooms

7.1.10. Table Zoom An object of this class will build a list of choices (single- or multi-se- lect), based on the table ID of the main field (table id is obtained from the DDO). Both the checkboxes and the descriptions are stored in a list, thus enabling scrolling through the choices.

A zoom of this class will usually be used to display fields that are attached to a normal table in the data dictionary with its type set to multi-select. To the end-user it will appear as if a field is available for every choice in the normal table and he can select/deselect every option.

7.1.10.1. Main Field The field for which the table should be displayed.

Syntax: Set pMain_Field To [Fieldnumber]

Alternate: Set pMain_Field To Field [Filename.Fieldname]

7.1.10.2. Image definition An image definition for a table zoom should contain a number of lines to display the table-descriptions in. If you use the full length of the description, these lines should be 28 characters wide (3 for the checkbox, 1 for a space, 24 for the description). If you are absolute sure all descriptions are shorter, you could shorten the windows as required.

You can have as many lines as you want. If there are more choices in the normal table than will fit in the image, the table will scroll (including the checkbox).

Example: Dynamic_Image ______/*

7.1.10.3. Summary The following details apply:

Classname: cTable_Zoom

(Super)Parent class: List

Package: TabZoom.PKG

File name suggestion: XXXXXXY.ZM Where XXXXXXX is the name of the data file and Y ranges from H to Z.

Mandatory property: pMain_Field

Include command: Use_Extend

Special remarks: This class is not included in the standard Class_DE and Classify pre-compiles, so you will need to put USE TABZOOM at the beginning of the zoom-definition.

Example: Class cCustomer_Interests is a cTable_Zoom

Procedure Construct_Object Integer Image Forward Send Construct_Object Image

Set pID To “CUST_K”

Set pMain_Field To Field Custom.Interest

End_Procedure

End_Class

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.17 Chapter 7: Data entry Classify Handbook Zooms

7.1.11. Bitmap zoom This zooms is designed especially for Windows. In character mode applications, it is totally ignored. In Windows, it will display a bitmap. The name of the bitmap should be specified in the field designated by the pMain_Field property.

7.1.11.1. Main Field This property should hold the name of the field that contains the name of a bitmap file.

Syntax: Set pMain_Field To [FieldNumber]

Alternate: Set pMain_Field To Field [Filename.Fieldname]

Example: Set pMain_Field To Field Persons.Picture

7.1.11.2. Image definition There is no image definition required.

Summary

7.1.11.3. The following details apply:

Classname: cBitmap_Zoom

(Super)Parent class: cField_Base

Package: BitZoom.PKG

File name suggestion: XXXXXXY.ZM Where XXXXXXX is the name of the data file and Y ranges from H to Z.

Mandatory property: pMain_Field

Include command: Use_Extend

Special remarks: This class is not included in the standard Class_DE and Classify pre-compiles, so you will need to put USE BITZOOM at the beginning of the zoom-definition.

Example: Class cCustomer_Interests is a cBitmap_Zoom

Procedure Construct_Object Integer Image Forward Send Construct_Object Image

Set pID To “CUST_K”

Set pMain_Field To Field Custom.Picture

End_Procedure

End_Class

Page 7.18 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry Zooms

7.1.12. Special Zoom The special zoom class is provided to give the programmer the ability to define certain procedures, that can be executed by a choice from the options pull-down.

Objects of this class are listed in the options pull down just like any other zoom. If selected, the message stored in pSpecial_Proc is sent. This message must be defined by the programmer.

In general, this message can be stored either in the special zoom itself or in one of its parent objects (e.g. the subsystem). In the latter case, the message will automatically be delegated to the parent object. Whether the message is placed inside the special zoom or at a higher level will depend on a number of things. For instance, if you want to be able to send the same message by pressing an accelerator key, it is necessary to put the message in the subsystem.

Objects of this class are ignored when “selecting all zooms” by [Ctrl][A].

7.1.12.1. Special Proc This property must contain the message to be sent when this object is selected from the options pull down.

Syntax: Set pSpecial_Proc To [Procedure_ID]

7.1.12.2. Redirect Errors If you set this property to TRUE, all errors will be redirected to a temporary file and will be shown after completion of the message specified in pSpecial_Proc.

If set to False, errors will appear as usual.

Syntax: Set pRedirect_Errors To [True|False]

Default: False

7.1.12.3. Image definition There is no image for special zooms.

7.1.12.4. Summary: The following details apply:

Classname: cSpecial_Zoom

(Super)Parent class: Message

Package: EntSpec.PKG

File name suggestion: XXXXXXY.ZM Where XXXXXXX is the name of the data file and Y ranges from H to Z.

Mandatory property: pSpecial_Proc

Include command: Use_Extend

Special remarks: This class is not included in the standard Class_DE and Classify pre-compiles, so you will need to put USE SPECZOOM at the begin- ning of the zoom-definition.

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.19 Chapter 7: Data entry Classify Handbook Zooms

Example: Register_Procedure mPrint_Label

Class cCustomer_Label is a cSpecial_Zoom

Procedure Construct_Object Integer Image Forward Send Construct_Object Image

Set pID To “Cust_L” Set pSpecial_Proc To mPrint_Label

End_Procedure

/Customer_Label Customer: ______City : ______/*

Procedure mPrint_Label

Local Integer Channel_ID

Get pRequest_Channel To Channel_ID If Channel_Id Ge 0 Begin Get pLocal_Field_Value Field Custom.Name To Customer_Label.1 Get pLocal_Field_Value Field Custom.City To Customer_Label.2 Output Channel Channel_ID Customer_Label Send mRelease_Channel Channel_ID End End_Procedure End_Class

Warning: The procedures pRequest_Channel and mRelease_Channel are desktop procedures that keep track of I/O channels in use by other objects. If you do not use these, you could accidently use an I/O channel already in use by another object. Please refer to the chapter about support functions for more informa- tion.

Page 7.20 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry Zooms

7.1.13. General Text Memo This is a very special class that allows you to attach a memo-field to any (existing) database. This is done by storing the actual memo- information in a seperate file (HDSINF) containing only file-ID, re- cord-ID and the memo field.

The advantages of using this technique when compared to standard text field approach are: » you can use all other files without compression, which might optimize performance; » it reduces memory usage; » easy to add without the need to modify the data file definition.

At the same time, there are some disadvantages: » one extra record is created and must be found, so general performance might be a bit slower; » the text fields are stored in a seperate file, which increases the risk of problems during back up and restore procedures.

Since this class is 100% pre-defined, you can actually immediately create the object inside the subsystem-class definition. There is no real reason here to create a specific zoom class. However, remem- ber to put the appropiate Use_Extend_Img statement in the image definition for the subsystem.

7.1.13.1. Image definition You can use the standard image definition GEN_TXT.IMG or provide an image like you would for a standard memo zoom.

7.1.13.2. Summary: The following details apply:

Classname: cGeneral_Text_Memo

Parent class: cField_Base

Package: Gen_Txt.PKG

File name suggestion: Not applicable.

Include command: Not applicable.

Special remarks: This class is not included in the standard Class_DE and Classify pre-compiles, so you will need to put USE gen_txt at the beginning of the subsystem-definition.

Example: Use Gen_Txt

// The following code should be in the subsystem class definition, // along with the other zooms

Object oMemo is a cGeneral_Text_Memo Next_Image End_Object

// The rest of the subsystem goes here

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.21 Chapter 7: Data entry Classify Handbook Subsystems

7.2. Subsystems The subsystem is the main object in any data entry module. The zoom classes are just ‘display devices’ and the view is barely more than a container. But the subsystem is the nerve-center of all data entry procedures. » The subsystem will communicate with the data dictionary. » The subsystem will maintain the local file buffer. » The subsystem will perform and control all find operations. » The subsystem keeps track of changes and validations. » The subsystem will automatically ‘synchronize’ zooms if a field is displayed in multiple zooms.

The subsystem is the most complex and intelligent part of all data entry classes. Yet from a programmers point of view, the subsystem usually will be quite simple and easy to program.

An object of the cSubsystem class is mostly used as a parent object for one or more zooms. All zooms contained in a subsystem object should work on fields from the same file. This file should be indicated by the pMain_File property of the subsystem class. All entry_items referring to another file will be forced to “display only”.

Just like zoom definitions, class definitions will usually be put into a class definition. In order to create the zoom objects, you should include the neccessary zooms.

Example: Use_Extend Custom_A.Fnd Use_Extend Custom_H.Zm Use_Extend Custom_I.Zm Use_Extend Custom_J.Zm Use_Extend Custom_K.Zm Use_Extend Custom_L.Zm

Class cCustomer_Subsystem is a cSubsystem

Procedure Construct_Object Integer Image Forward Send Construct_Object Image

Set pID To “Custom_0"

Object oCustomer_Find is a cCustomer_Find Next_Image End_Object

Object oCustomer_Address is a cCustomer_Address Next_Image Set Location To 7 0 Set pAuto_Activate_State To True End_Object

Object oCustomer_Statistics is a cCustomer_Statistics Next_Image Set Location To 12 0 End_Object

Object oCustomer_Shipping is a cCustomer_Shipping Next_Image Set Location To 12 30 End_Object

Object oCustomer_Interest is a cCustomer_Interest Next_Image Set Location To 17 0 End_Object

Object oCustomer_Label is a cCustomer_Label No_Image End_Object

Object oCustomer_Remarks is a cCustomer_Remarks Next_Image Set Location To 17 35 End_Object

End_Procedure

End_Class

If you go over this example code, you might find some interesting points: » The locations for the zooms is set here rather than in the class definition of the zoom. This is done because you might want to use the same zooms in other subsystems and want to display them on different locations to provide optimal use of the screen (you could also ignore all locations and let the user-configuration handle it at runtime). » The same applies to the pAuto_Activate_State.

Page 7.22 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry Subsystems

» All zoom objects (except for the special zoom) have NEXT_IM- AGE as their image name. This is a special (Classify) keyword that is used for the re-use of the images. » The special zoom has NO_IMAGE and also no location is set, since this object has no image.

All objects, except for the find, will be automatically listed in the options pull-down. The options pull-down is dynamically linked to the subsystem. This means this pull-down will only be accessable while (one of the zooms in) this subsystem has the focus. As soon as another subsystem gets the focus, the option pull-down for that subsystem will become accessable.

The description in the option pulldown will, by default, be the pID of the object. However, if you have entered data in the helpsystem, Classify will try to find a record in the help-description file that matches the ID of the object. If that is found, the short description specified in there will be displayed.

When a subsystem is activated, it will automatically activate its find object (and any other object having the pAuto_Activate_State set to True).

When deactivating a subsystem, all children of this subsystem (including nested subsystems) will also be deactivated. This means it is not possible to have a parent and a grand-child active, without having the child active. Deactivation of a subsystem is triggered by deactivating the find object.

That is why every subsystem should contain precisely one find object. This object will be of either the cEntry_Find or the cMulti_Line_Entry class and is the “leading” object. It is used to determine the active record. All other zooms (if any) and all nested subsystems (if any) will display information related to or being part of this active record.

The subsystem provides a full local record-buffer for all fields except Text and Binary types (this is done because of memory considera- tions). This enables you to work with the contents of the fields without having to be concerned over the global use of the actual record buffer. These buffered values can be accessed by use of the pLocal_Field_Value property and are automatically matched with the displayed values. So, changing the value on the screen updates the pLocal_Field_Value and updating the pLocal_Field_Value will also update the displayed value.

7.2.1. Index selector SBS This is a special subclass of the subsystem that provides an index selector. This is especially handy in subsystem featuring multi-line find objects. The index selector can be activated by pressing Ctrl-O. No further programming action is necessary, just base the subsys- tem on cIndex_Selector_SBS instead of on cSubsystem.

Hint: This is also a nice example of a custom extension on Classify.

7.2.2. Option group Theoptionpull-downcantakeamaximumof15entries.Since “Zoom all” and “Zoom none” are included automatically, you can have a maximum of 13 zoom objects inside a subsystem. If you need more, you will need to create an “zoom group”. This is done by the creation of an object of the option group class. pID is the only property for this class.

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.23 Chapter 7: Data entry Classify Handbook Subsystems

Example: Use_Extend Custom_A.Fnd Use_Extend Custom_H.Zm Use_Extend Custom_I.Zm Use_Extend Custom_J.Zm Use_Extend Custom_K.Zm Use_Extend Custom_L.Zm

Use_Extend Cascade1.IMG

Use OptGroup

Class cCustomer_Subsystem is a cSubsystem

Procedure Construct_Object Integer Image Forward Send Construct_Object Image

Set pID To “Custom_0"

Object oCustomer_Find is a cCustomer_Find Next_Image End_Object

Object oExtra_Customer_Info is a cOption_Group Cascade_1

Set pID To ”Extra information"

Object oCustomer_Address is a cCustomer_Address Next_Image Set Location To 70 Set pAuto_Activate_State To True End_Object

Object oCustomer_Statistics is a cCustomer_Statistics Next_Image Set Location To 12 0 End_Object

End_Object

Object oCustomer_Shipping is a cCustomer_Shipping Next_Image Set Location To 12 30 End_Object

Object oCustomer_Interest is a cCustomer_Interest Next_Image Set Location To 17 0 End_Object

Object oCustomer_Label is a cCustomer_Label No_Image End_Object

Object oCustomer_Remarks is a cCustomer_Remarks Next_Image Set Location To 17 35 End_Object

End_Procedure

End_Class

This will cause a new entry in the option pull down for the new group, while all objects inside this group are moved from the main pull down to a cascade activated by a [RETURN] on the new item.

Just like with ordinary zooms, Classify will attempt to find a descrip- tion record in the helpsystem matching the pID of the group. If not available, it will use the literal pID. Since a group is hardly ever a true entity in a helpsystem, we tend to specify the literal text in the pID.

You are required to create (or include) an image for the cascade menu’s. Since it is possible to reuse the same image as long as two active objects are not using it at the same time, we suggest you use one image per level. We have included the files CASCADEx.IMG (where x ranges from 1 to 5) with the image names franging from CASCADE_1 to CASCADE_5. You can include these files using the USE_EXTEND command.

Warning: You should not include the cascade images using USE_EX- TEND_IMG since this command will perform multiple includes. USE_EXTEND will only include every image once.

The option group class is not included in the standard pre-compile. In order to be able to create objects of this class, you should specify USE OPTGROUP.

Page 7.24 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry Subsystems

7.2.3. Properties and There are a lot of messages and properties specified in the subsys- messages tems. The ones listed here are the properties and messages you are likely to need.

7.2.3.1. ID As with the zooms, the subsystem needs an ID as well. Again, this ID is the main link into the helpsystem. The helpsystem is able to identify between a pID for a zoom and a pID for a subsystem, so you could use the same ID for a zoom and a subsystem.

Any pID can have theoratically have any length, but only 8 charac- ters are used by the file system and 15 are used in pull-downs.

Syntax: Set pID To [Val]

7.2.3.2. Main File This property must be set and indicates the file for which this subsystem is meant to be used. The subsystem will perform all find operations on this file and will create a local file buffer. It will also request the address of the DDO for this file and re-route all delete and save requests through the DDO to ensure full validation and database integrity.

Also, during activation, the subsystem will request information about the field related properties (entry options, prompts etc) and pass these on to the zooms contained in the subsystem.

Syntax: Set pMain_File To [Filenumber] Get pMain_File To [Var]

7.2.3.3. Constraint Msg This property can contain the ID of a function that will be activated directly after every Find operation. The programmer can check in this function if a record is valid for the subsystem.

Example: If you only want to allow paid invoices in a certain subsystem, you can check in this message if the invoice is fully paid. If not, I can return a “not found” and the next record will be retrieved.

Register_Function pCheck_Paid Integer Find_Argument Integer IndexNr

Set pConstraint_Msg To Get_pCheck_Paid

Function pCheck_Paid Integer Find_Argument Integer IndexNr Local String Paid_Flag Get pField_Buffer Invoice.File_Number Field Invoice.Paid_Flag To Paid_Flag If Paid_Flag Eq “Y” ; Function_Return 0 Else ; Function_Return 1 End_Function

The message checking the constraint is passed two arguments: the find operator and the index. The following find operators are speci- fied by the system: » @_Next » @_Prev » @_Ge » @_First » @_Last » @_Eq

The return value of the function should be: » 0: record is accepted (found); » 1: record is rejected, try next one; » -1: record rejected, simulate end of file.

If a value of 1 is returned on a Find Equal, the error “Record not found” will be generated. If 1 is returned with find operator @_Ge, the find operator is automatically changed to @_Next.

Syntax: Set pConstraint_Msg To [Message_ID] Get pConstraint_Msg To [Var]

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.25 Chapter 7: Data entry Classify Handbook Subsystems

7.2.3.4. Find Mode This property indicates the way the find procedures should find a record. The following values are valid: » @_User When this mode is set, the user can determine which index is used by selecting a field to be used for the find operations. If this field is contained in an index, the subsystem will automatically set the pIndex property to the main index for this field. Selecting another indexed field will change the pIndex again. Selecting an index is done by placing the cursor on the item attached to this field and pressing one of the find keys. When using these keys on any other field will cause a find to be performed based on the stored index. Changing the index can only be done if the field is part of an cEntry_Find class object. This mode should not be selected when using a multi-line entry object as the find object. » @_Index In this mode, the programmer can set the pIndex in the program. Changing the index by the user through selection of an index field is suppressed. » @_Link Use this find mode if you want to display the data using linked list ordering rather than index ordering. » @_No_Find This find mode is automatically selected when a subsystem for a parent file is nested within a subsystem for the child file. The parent related to by the active child is automatically displayed and cannot be changed. Using a subsystem with a multi-line find object is both not allowed and not functional (only one parent record can exist).

Warning: This property should generally only be set in the “top” sub- system (if any) and in that case it should be set to @_Index. In all other cases it is either redundant or not allowed.

Syntax: Set pFind_Mode To @_Index|@_User|@_No_Find|@_Relation

Default: @_User for the top subsystem, @_Relation for nested subsystem with the main file set to a child file of the main file of the parent object, @_No_Find for all other nested subsystems.

7.2.3.5. Key_Nr This property specifies the relation number for a subsystem. This is only valid for nested subsystems. Please refer to the paragraph about complex views for an example.

Syntax: Set pKey_Nr To [Key_Nr] Get pKey_Nr To [Var]

Default: @_DF_Relation (255)

7.2.3.6. Index This property indicates which index should be used for finding. Should only be set when setting the pFind_Mode to @_Index.

Syntax: Set pIndex to [IndexNr] Get pIndex to [Var]

7.2.3.7. Auto Activate State If this property is set, the subsystem will be activated automatically whenever the parent subsystem is activated. This property is only relevant in nested subsystems. Please refer to the paragraph about complex views for an example.

Syntax: Set pAuto_Activate_State To True|False

7.2.3.8. Local_Field_Value This property allows you to extract or update the value of a specified field in the local buffer (automatically updating the display if neces- sary).

Page 7.26 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry Subsystems

Syntax: Set pLocal_Field_Value [FieldNumber] Get pLocal_Field_Value [FieldNumber]

7.2.3.9. Ok To Delete Check Func This property can hold the ID of any function that should be excuted whenever a request to delete a record is received. If this message returns a non-zero value, the deletion is aborted.

Warning: Do not generate an error message yourself since this will prompt user input while the database is locked. Classify will generate an error for you once the database is unlocked.

Warning: If you are creating your own subsystem class, you should not set this property but augment pOk_To_Delete_Check. Otherwise you run the risk that a programmer can set this property and thus overwrite your setting.

Syntax: Set pOk_To_Delete_Check_Func To [Message_ID] Get pOk_To_Delete_Check_Func To [Var]

Default: None

Note: This property is meant to set a validation that is specific to this data entry function. General rules should be specified in the data diction- ary.

7.2.3.10. Ok To Save Check Func This property can hold an ID of a function that should be executed whenever a request to save a record is received. Any non-zero value will result in an error and the save command will be aborted.

If you want, you can generate an additional error message to explain the exact nature of the error.

Syntax: Set pOk_To_Delete_Save_Func To [Message_Id] Get pOk_To_Delete_Save_Func To [Var]

Default: None

Warning: If you are creating your own subsystem class, you should not set this property but augment pOk_To_Save_Check1. Otherwise you run the risk that a programmer can set this property and thus overwrite your setting.

Note: This property is meant to set a validation that is specific to this data entry function. General rules should be specified in the data diction- ary.

7.2.3.11. User hooks To provide maximum flexibility, Classify offers a number of ‘hooks’ that allow you to perform specific actions during save and delete actions. These hooks are provided in the form of properties that can contain message id’s. The following properties are provided: » pBefore_Validate_Msg The message stored here is sent prior to the validation of all the fields. This message is only sent when a save is requested, not when the fields are validated during data entry. All field references should be to the local buffer2. » pAfter_Validate_Msg The message specified here is sent after the validations are finished. However, if an error has occured during validation, this message is never executed since the process aborts as soon as

1 See the on line techical reference guide.

2 The cSubsystem class maintains a local file buffer which can be accessed by the pLocal_Field_Value message. The global file buffer can be accessed using pField_Buffer. Please refer to the documentation on file-handling in Classify for more information.

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.27 Chapter 7: Data entry Classify Handbook Subsystems

an error occurs. All field references should be to the local buffer. » pBefore_Save_Msg This message is sent at the start of the save procedure even before the buffer gets updated or the backout dependencies get executed. However, the file buffer has been repositioned and the database is locked. This message is the best hook if you want to compare old and new values. You can retrieve the new information from the local buffer, while the old information can be retrieved from the file buffer. » pBefore_Update_Msg This message is sent after the backout procedures but before the information from the local buffer is transfered to the file buffer. » pAfter_Update_Msg This message is sent after the transfer from the local buffer to the file buffer. All field references should be to the global file buffer. » pAfter_Save_Msg This message is sent after all the saves are completed. If any errors occur during the saves, this message will never be sent. All references should be to the global file buffer. » pBefore_Delete_Msg This message is sent before a record is deleted. » pAfter_Delete_Msg This message is sent after the record is deleted.

Warning: If you are creating your own data dictionary class, you should not set these properties but augment the corresponding mes- sages. Otherwise you run the risk that a programmer can set this property and thus overwrite your setting.

Warning: You cannot abort a save or delete operation by returning non-zero values from these procedures.

Syntax: Set pBefore_Save_Msg To [Message_ID] Set pBefore_Validate_Msg To [Message_ID] Set pAfter_Validate_Msg To [Message_ID] Set pBefore_Update_Msg To [Message_ID] Set pAfter_Update_Msg To [Message_ID] Set pAfter_Save_Msg To [Message_ID] Set pBefore_Delete_Msg To [Message_ID] Set pAfter_Delete_Msg To [Message_ID] Get pBefore_Save_Msg To [Var] Get pBefore_Validate_Msg To [Var] Get pAfter_Validate_Msg To [Var] Get pBefore_Update_Msg To [Var] Get pAfter_Update_Msg To [Var] Get pAfter_Save_Msg To [Var] Get pBefore_Delete_Msg To [Var] Get pAfter_Delete_Msg To [Var]

Default: 0

Note: This property is meant to set a validation that is specific to this data entry function. General rules should be specified in the data diction- ary.

7.2.3.12. Version This is a general property that can be used for version control. It is available in every major class and can be retrieved by an end user using the Version Information function [Ctrl][F1].

Syntax: Set pVersion To [Number] Get pVersion To [Var]

Default: 0.0

7.2.3.13. Update State This property is maintained automatically by the subsystem. It sig- nals whether the current record is being edited (True) or is being created (False).

Page 7.28 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry Subsystems

Syntax: Get pUpdate_State To [Var]

Warning: You are not allowed to SET this property.

7.2.3.14. Data dictionary This property holds the ID of the data dictionary object for the main file. It can be used if you want to send messages to this object.

Syntax: Get pData_Dictionary To [Var]

Warning: You should not attempt to SET this property.

7.2.3.15. May Change Parent This property only has importance if the subsystem is used as a “No find” subsystem. This means the subsystem is displaying informa- tion about the parent file of the parent subsystem (if this sounds complex, read it again).

By default, Classify will not allow you to find other records in such a subsystem, because in that case you are effectively changing the information in the child file by “attaching” another parent record. If you set this property to TRUE, and the user tries to find another record, Classify will prompt the user first whether he realy wants to change the parent record. And if so, allow the user to browse through the records, thus effectively selecting a different parentrecord for the child.

Syntax: Set pMay_Change_Parent To [True|False]

Default: False

Hint: You might prefer to set this property while creating the views

7.2.3.16. Rights There are several properties controlling the rights in the subsystem. These properties are similar to the ones used in the data dictionary but now can be set per subsystem. However, you can only impose stronger rules than setup in the data dictionary, not weaken them.

For a full description of the properties, please refer to the appropriate chapters in the data dictionary chapter.

Syntax: Set pMay_Read To [True|False] Set pMay_Create To [True|False] Set pMay_Delete To [True|False] Set pMay_Modify To [True|False] Set pMay_Copy To [True|False] Set pMay_Change_Key To [True|False]

All these properties default to TRUE

7.2.4. Image definition As with zooms, you should specify image files per subsystem. Again, these will usually be stored in seperate files with the same name, but with extension IMG.

In this file, you should list all the zooms needed in the subsystem using the USE_EXTEND_IMG command.

Example: Use_Extend_Img Custom_A.Img Use_Extend_Img Custom_H.Img Use_Extend_Img Custom_I.Img Use_Extend_Img Custom_J.Img Use_Extend_Img Custom_K.Img Use_Extend_Img Custom_L.Img

7.2.5. Summary The subsystem is both a grouping mechanism for zooms and the file manager for data entry processes. It is the back-bone of all data entry modules.

Classname: cSubsystem

Base class: Message cFile_Handler

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.29 Chapter 7: Data entry Classify Handbook Subsystems

Package file: Subsys.PKG

Filename suggestion: XXXXXXXY.SBS Where XXXXXXX is the name of the main file and Y ranges from 0 to 9.

Include command: Use_Extend

Mandatory properties: pMain_File

Page 7.30 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry Views

7.3. Views Views are the final ‘layer’ in our data entry structure. The view is a grouping mechanism for subsystems and communicates with the desktop to obtain its place in the function pull-down.

Every view should contain at least one subsystem. This subsystem should be specified in the procedure Construct_Children.

Example: Use_Extend Cust.DDO Use_Extend Cust_0.SBS

Class cCustomer_View is a cView

Procedure Construct_Object Integer Image Forward Send Construct_Object Image Set pID To “CUST” End_Procedure

Procedure Construct_Children Forward Send Construct_Children Object oCustomer_Subsystem is a cCustomer_Subsystem No_Image End_Object End_Procedure End_Class

Please note that the subsystem requires a NO_IMAGE argument because it does not have any image attached to it.

The object of the procedure Construct_Children is to allow easy creation and destruction of views. Apart from the need for this procedure, this is totally transparant to you.

Whenever a view is specified, it will acknowledge its presence to the desktop and this will result in an entry in the function pull down of the main action bar. The description in this pull down is either the literal pID or (if an appropriate help record is found) the short description of the help system.

Whenever the user selects an entry from the function pull down, this will activate the view, which will in turn activate the subsystem and that will in turn activate the find object of the subsystem. The view itself is virtually ‘invisable’ to the end-user.

7.3.1. Properties and The following properties and messages can be set in the view messages objects.

7.3.1.1. pID The pID identifies the view for the help-system. It is also used to look up the description to be used in the Functions pull-down. If no description is found in the Help system, the literal pID will be displayed in the pull-down.

Syntax: Set pID To [Val]

7.3.1.2. pMay_Destroy_Function This property can contain a function id. If this property is set, the function will be executed whenever the data in this view is about to be forcefully destroyed. This can be triggered by either [aF4] or [cF4]. A non-zero return value for this function will cause the infor- mation to be kept and will return the user to the active zoom within the view.

This function is meant to be used for overall-validations, like com- paring the total stock-modification with a pre-entered count of the new stock. If these two don’t align, the user cannot exit the program or remove the view with [cF4]. He can however use other views and even remove this view from the screen using [Esc].

Syntax: Set pMay_Destroy_Function To [Message_ID]

7.3.2. Complex views It is possible to create complex views that will show information about multiple (related) files. This is done by nesting subsystems. At the ‘top level’ should be only one subsystem. In this object, you

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.31 Chapter 7: Data entry Classify Handbook Views

can nest subsystems. The only condition for this is that the main file for the parent object is either parent- or childfile to the main file of the nested subsystem.

Example: You can nest a subsystem for invoices-lines inside a subsystem for invoice- headers, but you could include a subsystem for customers as well.

When nesting subsystem, Classify will automatically detect the re- lationship and set the pFind_Mode property of the nested subsystem accordingly. This means that either no finds are allowed (the nested subsystems main file is a parent to the main file of the parent subsystem) or finds are constrained (the main file for the child subsystem is a child to the main file of the parent subsystem).

Example: Use_Extend Cust.DDO Use_Extend InvH.DDO Use_Extend InvL.DDO Use_Extend Order.DDO

Use_Extend Cust_0.SBS Use_Extend InvH_1.SBS Use_Extend InvL_1.SBS Use_Extend Order_1.SBS

Class cCustomer_View is a cView

Procedure Construct_Object Integer Image Forward Send Construct_Object Image Set pID To “CUST” End_Procedure

Procedure Construct_Children Forward Send Construct_Children Object oCustomer_Subsystem is a cCustomer_Subsystem No_Image Object oInvoice_Subsystem is a cInvoice_Subsystem No_Image Object oInvoice_Line_SBS is a cInvoice_Line_SBS No_Image End_Object End_Object Object oOrder_Subsystem is a cOrder_Subsystem No_Image End_Object End_Object End_Procedure End_Class

In this sample, you will be able to view all customers. Per customer, you can retrieve the invoices and orders (or enter new ones) and per invoices, you can access the invoice-lines.

There is no real limit to the complexity of views. The only restrictions are memory limitations, overall program size and the comprehension of the end-user.

7.3.3. Data dictionaries In order to be able to work with any file, the data dictionary for that file needs to be present. In order to make it easy to incorporate a view in a program, we will usually place the Use_Extend commands for the data dictionary in the file for the view class. Be sure to include the data dictionaries for all files needed to update the mainfile, otherwise CLassify will generate an ‘related file not open’ error. This will generally mean the data dictionary is not included.

7.3.4. Images Like with the subsystem, you need to have an image file for every view. In this file, you should list all the subsystems needed in the view using the USE_EXTEND_IMG command. The order should match the order of the subsystems in the view (as read in the source from the top down). If you have multiple objects of the same subsys- tem class, you will need to specify the image for this subsystem twice (or rather: as many times as you have objects and you also need to specify it at the right location).

Example: Use_Extend_Img Custom_A.Img Use_Extend_Img Custom_H.Img Use_Extend_Img Custom_I.Img Use_Extend_Img Custom_J.Img Use_Extend_Img Custom_K.Img Use_Extend_Img Custom_L.Img

Page 7.32 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 7: Data entry Views

7.3.5. View classes Classify offers two distinct classes for views. In character mode environments, the two classes work exactly the same. However, in Windows the visual presentation is different.

7.3.5.1. View If you base your views and the cView class, the presentation in Windows and character mode is similar. All zooms are presented as independent panels and can be moved over the complete Classify desktop.

7.3.5.2. View Panel This class will provide the user with a visible panel representing the whole view when in Windows. All zooms that are auto-activated will appear in the panel without their own borders. The zooms that are activated manually will appear with their own border and are draga- ble within the constraints of the view panel.

If you select “save windows”, the size and location of the view is saved as well. All the locations of the zooms in the view are saved relative to the view itself.

The auto-activated zooms can be dragged by using the rubberband. To activate the rubber band, right click the mouse and select “Rub- berband”. You can now drag and resize the zooms. Deactivate the rubberband by pressing the right mouse button again and make sure to save the windows locations.

In character mode, the view panel will work exactly like the view.

7.3.6. Summary The view is the main grouping mechanism for data entry objects in Classify. A view is activated through the function pull down and probably closest to a ‘procedural style program’ as far as function- ality is concerned.

Classname: cView; cView_Panel

Base class: Message

Package file: View.PKG; ViewPan.PKG

Special remarks: The view panel class is not automatically included in the CLASS_DE and CLASSIFY pre-compiles. So you will have to add USE VIEW- PAN manually.

Filename suggestion: None

Include command: Use_Extend

(c) '92 - '95 Calvin Consultancy May 1995 Page 7.33 Classify Handbook Chapter 8: Batches

8. Batches In Classify, we make no distinction between batches and reports. Very often, you will need to update a particular field while printing a report, or you need to print a log during a batch process.

Also, you will find that batches will require more (procedural) pro- gramming than do the data entry systems. This is because it is much harder to find a common delimiter in batches than it is to find one in data entry.

On the other hand, you will probably find some features in the batches both similar to the data entry structure and very handy at that.

(c) '92 - '95 Calvin Consultancy May 1995 Page 8.1 Chapter 8: Batches Classify Handbook The Batch report

8.1. The Batch report This class is the kernel for all the batches and handles the file inter-action, much like the subsystem in the data entry modules. It also has a lot of similar properties.

The main difference is that the batch report lacks the equivalent of zooms. In a batch report this is handled by custom build procedures (similar to the sections in the old report macro).

Another difference is the way images are handled. In the zooms, we needed to recreate the images for every object (after all, multiple objects of the same zoom class could be active at the same time). By definition, any batch is a gigantic ‘pop up’. This means that during a batch operation, no other objects can take control. And thus we need only one image. This image is included in the class definition.

8.1.1. Properties and As we go over the properties and messages for the batch report messages class, you will see a lot of similarity with the subsystem class.

8.1.1.1. ID As with all other major objects, the batch report needs an ID as well. Again, this ID is the main link into the helpsystem. But this time, the pID is not used to retrieve descriptions in pull downs (for the simple reason that batch reports do not show up in pull downs.

A zoom ID can have any length, but only 8 characters are used by thehelpsystem.

Syntax: Set pID To [Val]

8.1.1.2. Main File This property must be set and indicates the file for which this class needs to do a report. The batch report class will scan all records in this file and for every valid record, it will send the message specified in pDetail_Message.

Syntax: Set pMain_File To [Filenumber] Get pMain_File To [Var]

8.1.1.3. Constraint Msg This property can contain the ID of a function that will be activated directly after every Find operation. The programmer can check in this function if a record is valid for the subsystem.

Example: If you only want to allow paid invoices in a report, you can check in this message if the invoice is fully paid. If not, I can return a “not found” and the next record will be retrieved.

Register_Function pCheck_Paid Integer Find_Argument Integer IndexNr

Set pConstraint_Msg To Get_pCheck_Paid

Function pCheck_Paid Integer Find_Argument Integer IndexNr Local String Paid_Flag Get pField_Buffer Invoice.File_Number Field Invoice.Paid_Flag To Paid_Flag If Paid_Flag Eq “Y” ; Function_Return 0 Else ; Function_Return 1 End_Function

The message checking the constraint is passed two arguments: the find operator and the index. The following find operators are speci- fied by the system: » @_Next » @_Prev » @_Ge » @_First » @_Last » @_Eq

The return value of the function should be: » 0: record is accepted (found);

Page 8.2 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 8: Batches The Batch report

» 1: record is rejected, try next one; » -1: record rejected, simulate end of file.

If a value of 1 is returned on a Find Equal, the error “Record not found” will be generated. If 1 is returned with find operator @_Ge, the find operator is automatically changed to @_Next.

Syntax: Set pConstraint_Msg To [Message_ID] Get pConstraint_Msg To [Var]

8.1.1.4. Detail Message This property can hold the ID for a message that should be sent for every valid record found. Since Classify will not only send the detail message for every valid record, but also executes the nested batches. This is why we have provided two detail messages: one that is executed prior to the child batches and one to be executed after the child batches have been executed.

Syntax: Set pPre_Child_Detail_Message To [Message_ID] Set pPost_Child_Detail_Message To [Message_Id]

Note: The old pDetail_Message is still supported for compatibility reasons and will set the pPre_Child_Detail_Message

8.1.1.5. Minimum Detail Lines In this property you should specify the minimum number of lines a detail message will have. This is used for “orphan protection”. If a field break occurs, Classify will check whether all headers and at least one detail (occording to this setting) will fit on the page. If not, it will print the appropiate footers and start the break headers on a new page.

If you would want to keep at least two detail lines on one page, you would set this property to twice the number of lines in a detail.

Syntax: Set pMinimum_Detail_Lines To [Val]

Default: 1

8.1.1.6. Error handler Classify allows you to set up your own procedure for error handling. You can create your own procedure and set this property to contain the message id. This message will then be sent for every record where an error occurs during a save operation with the record still in the record buffer.

Syntax: Set pError_Handler To [Message_Id]

8.1.1.7. Key_Nr This porperty specifies the relation number for a batch. This is only valid for nested batches. Please refer to the paragraph about com- plex batches for an example.

Syntax: Set pKey_Nr To [Key_Nr] Get pKey_Nr To [Var]

Default: @_DF_Relation (255)

8.1.1.8. Index This property indicates which index should be used for finding. Should only be set in the ‘top’ batch report..

Syntax: Set pIndex to [IndexNr] Get pIndex to [Var]

8.1.1.9. Local Field Value This property allows you to extract or update the value of a specified field in the local buffer (automatically updating the display if neces- sary).

Syntax: Set pLocal_Field_Value [FieldNumber] Get pLocal_Field_Value [FieldNumber]

(c) '92 - '95 Calvin Consultancy May 1995 Page 8.3 Chapter 8: Batches Classify Handbook The Batch report

8.1.1.10. Ok To Delete Check Func This property can hold the ID of any function that should be excuted whenever a request to delete a record is received. If this message returns a non-zero value, the deletion is aborted.

Warning: Do not generate an error message yourself since this will prompt user input while the database is locked. Classify will generate an error for you once the database is unlocked.

Warning: If you are creating your own batch report class, you should not set this property but augment pOk_To_Delete_Check. Otherwise you have the risk that a programmer can set this property and thus overwrite your setting.

Syntax: Set pOk_To_Delete_Check_Func To GET_[Function_Name]

Default: None

8.1.1.11. Ok To Save Check Func This property can hold an ID of a function that should be executed whenever a request to save a record is received. Any non-zero value will result in an error and the save command will be aborted.

If you want, you can generate an additional error message to explain the exact nature of the error.

Syntax: Set pOk_To_Delete_Save_Func To GET_[Function_Name]

Default: None

Warning: If you are creating your own batch report class, you should not set this property but augment pOk_To_Save_Check. Otherwise you run the risk that a programmer can set this property and thus overwrite your setting.

8.1.1.12. User hooks To provide maximum flexibility, Classify offers a number of ‘hooks’ that allow you to perform specific actions during save and delete actions. These hooks are provided in the form of properties that can contain message id’s. The following properties are provided: » pBefore_Validate_Msg The message stored here is sent prior to the validation of all the fields. This message is only sent when a save is requested, not when the fields are validated during data entry. All field references should be to the local buffer. » pAfter_Validate_Msg The message specified here is sent after the validations are finished. However, if an error has occured during validation, this message is never executed since the process aborts as soon as an error occurs. All field references should be to the local buffer. » pBefore_Save_Msg This message is sent at the start of the save procedure even before the buffer gets updated or the backout dependencies get executed. However, the file buffer has been repositioned and the database is locked. This message is the best hook if you want to compare old and new values. You can retrieve the new information from the local buffer, while the old information can be retrieved from the file buffer. » pBefore_Update_Msg This message is sent after the backout procedures but before the information from the local buffer is transfered to the file buffer. » pAfter_Update_Msg This message is sent after the transfer from the local buffer to the file buffer. All field references should be to the global file buffer.

Page 8.4 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 8: Batches The Batch report

» pAfter_Save_Msg This message is sent after all the saves are completed. If any errors occur during the saves, this message will never be sent. All references should be to the global file buffer. » pBefore_Delete_Msg This message is sent before a record is deleted. » pAfter_Delete_Msg This message is sent after the record is deleted.

Warning: If you are creating your own batch report class, you should not set these properties but augment the corresponding mes- sages. Otherwise you run the risk that a programmer can set this property and thus overwrite your setting.

Warning: You cannot abort a save or delete operation by returning non-zero values from these procedures.

Syntax: Set pBefore_Save_Msg To [Message_ID] Set pBefore_Validate_Msg To [Message_ID] Set pAfter_Validate_Msg To [Message_ID] Set pBefore_Update_Msg To [Message_ID] Set pAfter_Update_Msg To [Message_ID] Set pAfter_Save_Msg To [Message_ID] Set pBefore_Delete_Msg To [Message_ID] Set pAfter_Delete_Msg To [Message_ID]

Default: 0

8.1.1.13. Version This is a general property that can be used for version control. It is available in every major class and can be retrieved by an end user using the Version Information function [Ctrl][F1].

Syntax: Set pVersion To [Number]

Default: 0.0

8.1.2. Breakpoints The report class allows you to set up an unlimited number of breakpoints. Breaks are always triggered by a change in a particular field or in the result of the expression specified. When the break occurs, Classify will execute the specified header and/or footer message.

You specify breakpoints using the mSet_Breakpoint_Message. This message takes as arguments the IDs for a header and footer mes- sage and the number of lines for the images outputted by these messages.

Syntax: Send mSet_Breakpoint [Fieldnumber|Expression]; [Header_Message_ID] [Header_Lines] ; [Footer_Message_ID] [Footer_Lines] ; [At_PageBreak] [Footer_At_Page_End_Lines]

The header and footer messages will be send whenever a break occurs. If you specify At_PageBreak as TRUE, the specified mes- sage will also be sent when a pagebreak occurs. If you specify FALSE, the message is only sent when the value in the breakfield occurs.

Hint: If you use the expression, you must put it in quotes or precede it by the EXP keyword. In the latter case, the compiler will do some pre-processing on the expression. If you omit the EXP keyword, the expression is fully evaluated at runtime an will probably require the symbol table.

The “Footer At Page End Lines” specifies the number of lines used by the sub-footer if it is printed at the bottom of the page rather than at a field break. If the two are the same, you still should specify this. If you will never print at the pagebreak, you can specify 0.

(c) '92 - '95 Calvin Consultancy May 1995 Page 8.5 Chapter 8: Batches Classify Handbook The Batch report

Important: You can still use the SUBTOTAL command as we would do in the ordinary report macro.

Note: The old mAdd_breakpoint syntax is also supported for com- patibility, but does not support the “at page break” and “footer at page end lines” options.

8.1.3. Writing a detail message The report class will automatically send the message specified in pDetail_Message for every valid record found.What you do in this message is entirely up to you.

You can use this message to print the ‘body’ of a report (we will get to breaks, headers and subheaders later). But you could also do some processing here.

It is very important you understand that batches are not nearly as much ‘automated’ as are the data entry functions. This is because there is such a wide variety in needs for batches.

8.1.3.1. Printing information If you want to print information, you will have to create an image and issue a number of PRINT commands, just like you would do in the standard report macro. You can also use the print wrap command to output text-fields.

8.1.3.2. Report Write Image Classify keeps track of line-count per report. But in order to allow Classify to update and check this line count, and to allow headers and subheaders to be printed, you should use this message instead of doing the OUTPUT command. This message will output the image to the default output channel for this report (assigned by the batch server).

Syntax: Send mReport_Write_Image [Image_Nr] [Nr_Of_Lines]

Alternate: Send mReport_Write_Image [Image_Name].N [Image_Name].Lines

8.1.3.3. Report Write Image Wrap If you need to output a wrapped image, you should use this mes- sage. It will output the image specified to the default output channel for this report. If you want to keep the entire memo on one page at all times, you can specify a higher number of lines than are actually in the image. You could even set this depending of the size of the text field.

Syntax: Send mReport_Write_Image_Wrap [Image_Nr] [Nr_Of_Lines]

Alternate: Send mReport_Write_Image_Wrap [Image_Name].N [Image_Name].Lines

8.1.3.4. Raw output If you want to send ‘raw’ data to the output channel, you can use mReport_Write and mReport_WriteLn. Again, this will output the string to the default channel.

Syntax: Send mReport_Write [String] Send mReport_WriteLn [String]

8.1.3.5. Check Page This message can be used to check if the specified number of lines is still available. If not, Classify will perform a page break (including the print of footers and headers).

Syntax: Send mCheck_Page Nr_of_Lines

8.1.3.6. Buffer access The entire batch is treated as a popup object. This means that it is started in a seperate ‘mode’ and no other object can gain control while the batch is running. This also means there is no real need for local buffering of information.

So, wile you are in a batch, you can access the file buffer through direct references (e.g. CUSTOMER.NAME) or through pLo- cal_Field_Value. However, if you change information, you must

Page 8.6 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 8: Batches The Batch report

update the buffer through the pLocal_Field_Value message, or you will bypass the data dictionary validations.

Syntax: Set pLocal_Field_Value [Field_Number] To [Val]

Alternate: Set pLocal_Field_Value Field [Filename.Fieldname] To [Val]

8.1.3.7. Save If you have made modifications to the file buffer, you can issue a save command by sending the message. This will force the valida- tion by the data dictionary, and only if all fields validate, the record will be saved (and any dependencies will be updated.

Syntax: Send mSave

Warning: If you do not change the fields through the pLo- cal_Field_Value message, the data dictionary is not aware of the changes and will not validate, nor perform any depend- encies.

8.1.3.8. Save all This message saves all the updated batch reports inside a batch server. It does this by sending mSave to all child objects of the server.

Syntax: Send mSave_All

8.1.3.9. Request delete If you want to delete a record in the batch, you can send this message. It will perform all data dictionary validations specified for deletion of a record and delete the record only if no check fails.

Syntax: Send mRequest_Delete

Example: Suppose you would setup validations in the data dictionary that a customer could only be deleted if all invoices could be deleted as well, and in the data dictionary for the invoices is specified that only paid invoices can be deleted.

If you would now write a batch to delete all customers (and you had included the data dictionary for invoices as well), Classify would check for every customer whether he could be deleted or not by checking whether all invoices were paid. If so, Classify would first delete all the invoices for this customer and then delete the actual customer.

8.1.3.10. Request purge This message is similar to mRequest_Delete, except that it will perform the “purge” dependencies rather than the standard backout and delete dependencies.

Syntax: Send mRequest_Purge

8.1.4. Writing subheaders and The tecniques involved in writing subheaders and subtotals are subtotals similar to those used for the detail message. The only difference is the definition of the procedure. This should contain two additional parameters:

Procedure mSub_Header String Break_Value Integer Reason

Classify will automatically pass the reason for the execution of this message to the procedure. The reason can be: » @_No_Break Initial call for headers or last call for totals » @_Field_Break A change in the corresponding field was detected. » @_Page_Break The message is sent because of a pagebreak that occured.

By checking on this value, you can print the appropriate information.

Important: If you want to print file-information in the subheader, you should always do this on the first occurance. It is possible that

(c) '92 - '95 Calvin Consultancy May 1995 Page 8.7 Chapter 8: Batches Classify Handbook The Batch report

a “page break” header is generated while the next record is in the buffer. So always use the following structure:

Procedure mCustomer_Sub_Header String Break_Value Integer Call_Reason If Call_Reason @_Eq @_Field_Break Begin Print Customer.Name To Break_Footer.1 Print Customer.City To Break_Footer.2 Print Customer.Name To Page_Footer.1 Send mReport_Write_Image Break_Footer.N Break_Footer.Lines End Else ; Send mReport_Write_Image Page_Footer.N Page_Footer.Lines End_Procedure

8.1.4.1. Display_Subtotal This is a new command we added which displays a subtotal, like the standard SUBTOTAL command of DataFlex, but which will not reset the count to zero. Thus it is ideal for displaying running subtotals.

8.1.4.2. At Top Of Page This property allows you to check whether you are still at the top of the page or not. It is maintained by Classify and should only be retrieved.

Syntax: Get pAt_Top_Of_Page To [Var]

8.1.5. New Page You can send this message to force a pagebreak, including all the necessary headers and footers.

Syntax: Send mNew_Page

8.1.6. Headers and Footers True page headers and footers should be specified in the batch server class. However, headers and footers specific to the report, such as column titles and counters, can be specified in the report itself.

You can specify the messages for the headers and footers by using the following syntax:

Syntax:: Set pReport_Header_Message [Header_Message_ID] [Header_Lines] ; [At_PageBreak] Set pReport_Footer_Message [Footer_Message_ID] [Footer_Lines] ; [At_PageBreak]

If you specify At_Pagebreak TRUE, the header will be printed at the top of every page as well, when set to FALSE, it is only printed at the start/end of the report.

8.1.7. Summary The batch report is the main class for batches and reports. It will scan the specified file and send the message specified in pDe- tail_Message for every valid record.

Classname: cBatch_Report

Base class: Message

Package file: BatRep.PKG

Filename suggestion: XXXXX.BTR

Include command: Use_Extend

Page 8.8 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 8: Batches The Batch report

Example: Register_Procedure mPrint_Phone Register_Procedure mPrint_Area_Code

/Area_Header Areacode: ______

/Phone_List ______/*

/Cust_Memo ______/*

Class cPhone_Report Is a cBatch_Report

Procedure Construct_Object Integer Image Forward Send Construct_Object Image Set pID To “PHONES” Set pMain_File To Cust.File_Number Set pIndex To Index.3 Set pDetail_Message To mPrint_Phone Send mAdd_Breakpoint Field Cust.Area_Code Msg_mPrint_Area_Code ; Area_Header.Lines 0 0 False End Procedure

Procedure mPrint_Phone Print Cust.Name To Phone_List.1 Print Cust.Phone To Phone_list.2 Send mReport_Write_Image Phone_List.N Phone_List.Lines Print_Wrap Cust.Memo To Cust_Memo.1 Send mReport_Write_Image_Wrap Cust_Memo.N 10 End_Procedure

Procedure mPrint_Area_Code Integer Reason Print Cust.Area_Code To Area_Header.1 Send mWrite_Report_Image Area_Header.N Area.Lines End_Procedure

End_Class

(c) '92 - '95 Calvin Consultancy May 1995 Page 8.9 Chapter 8: Batches Classify Handbook The Batch_Server

8.2. The Batch_Server The batch server is pretty much a container for the batch-report(s), just like the view is a container for the subsystems. However, the batch-server allows some extra options for you which we will go over later.

The batch server will request an I/O channel from the desktop and will channel all I/O through that channel automatically. It will also inform the desktop that a batch is running, which will automatically disable all error popups. Only fatal errors will appear.

At the end of the batch, an errorlog is displayed using the standard editor. The errors are stored in a temporary file. This file is created in the directory specified by the TMP environment variable. The files are not automatically deleted to allow a supervisor to monitor the batch logs and to retreive them when necessary.

8.2.1. Properties and mes- The following properties and messages are specified for the batch sages server.

8.2.1.1. Report State Before the actual report starts, the batch server will also display a selection screen where the user can specify the destination for the report (file, printer, screen) if the report state is set to true. The selected output channel will be the default output channel for all output generating messages.

If the report state is false, Classify assumes that you are either running a pure batch (no output) or are handling all I/O related issues yourself.

Syntax: Set pReport_State To [True|False]

Default: False

8.2.1.2. Selection Message If you want to give the user the possibility to make some sort of selection, you can do this using a special function, and setting the pSelection_Message to this function. If this function returns a nega- tive value, the print job will be aborted.

What you do in this function is totally up to you. Usually, it will involve some sort of base-class objects pops up and lets the user make some selections. But it might as well do a verification for some system variables to determine whether the report can be run or not (you might have a flag siugnalling that only one workstation at the time can print invoices).

Syntax: Set pSelection_Message To [Message_ID]

8.2.1.3. Output file The batch server will automatically present a destination selector. You can set the default file name to appear there by setting this property.

Syntax: Set pOutput_File To [Val]

8.2.1.4. Headers and footers Headers and footers are handled by the batch server. Again, they are similar to the detail messages in that you will specify a message ID and this message is sent for every page break.

Classify distinguishes between page headers and footers and report headers and footers: » Report header Will be sent only for the first page. » Page header Will be sent for all pages except the first. » Report footer Will be sent only for the last page.

Page 8.10 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 8: Batches The Batch_Server

» Page footer Will be sent for all pages except the last.

Furthermore, Classify provides a page top message (sent prior to the header) and page title (sent after the header message), as well as a page total message (prior to the footer) and a page bottom (after the footer).

Syntax: Set pPage_Top_message To [Message_ID] Set pPage_header_message To [Message_ID] Set pReport_header_message To [Message_ID] Set pPage_Title_message To [Message_ID] Set pPage_Total_message To [Message_ID] [Lines] Set pReport_footer_message To [Message_ID] [Lines] Set pPage_footer_message To [Message_ID] [Lines] Set pPage_Bottom_message To [Message_ID] [Lines]

There is a standard header available. If you want this printed on every page, you should specify:

Syntax: Set pReport_Header To mStandard_Header Rpt_Standard_Header.Lines Set pPage_Header To mStandard_Header Rpt_Standard_Header.Lines

8.2.1.5. Filler Image In this property you can store the ID of an image that should be used to “fill” the page before the footers are printed. By default, it is an empty line.

This image should always be one line. You can disable the “page fill” feature by setting this property to 0.

Syntax: Set pFiller_Image To [Image_Id]

8.2.1.6. Page number You can retrieve the current page number at any time. The page number is automatically updated by Classify and should not be set.

Syntax: Get pPage_Number To [Var]

8.2.1.7. ID As with any other main class, you can set the pID, which will also be used to determine the pull-down description for this report.

Syntax: Set pID To [Val]

8.2.2. Complex batches Like with the views and subsystems, it is possible to create complex reports by nesting reports inside eachother. The same rules apply as when nesting subsystems. So nesting a batch report for invoices inside a batch report for customers will print a list of customers, and per customer all its invoices. If you nest the customer report inside the invoice-report, it will print customer information per invoice.

The batch server will first send the detail message to the parent report and after that it will activate the child reports.

(c) '92 - '95 Calvin Consultancy May 1995 Page 8.11 Chapter 8: Batches Classify Handbook The Batch_Server

Example: Use_Extend Cust.Btc Use_Extend Invoice.Btc

Use_Extend Cust.DDO Use_Extend Invoice.DDO

Register_Function pCheck_Paid Integer Find_Argument Integer IndexNr

Class cOutstanding is a cBatch_Server

Procedure Construct_Object Integer Image Forward Send Construct_Object Image

Set pID To “OUTST” Set pOutput_File To “OUTST.TXT” Set pReport_State To True End_Procedure

Procedure Construct_Children Forward Send Construct_Children

Object oCustomer_Report is a cCustomer_Report No_Image Object oInvoice_Report is a cInvoice_Report No_Image Set pConstraint_Msg To Get_pCheck_Paid End_Object End_Object End_Procedure

Function pCheck_Paid Integer Find_Argument Integer IndexNr Local String Paid_Flag Get pField_Buffer Invoice.File_Number Field Invoice.Paid_Flag To ; Paid_Flag If Paid_Flag Eq “Y” ; Function_Return 0 Else ; Function_Return 1 End_Function

End_Class

Note that instead of building a special class to just print outstanding invoices, we used the standard invoice class and just added a constrain procedure. The fact that we can specify the actual con- strain function is due to the automatic delegation of messages in DataFlex.

8.2.3. Summary The batch server is the grouping object for batch reports and takes care of line count, headers, footers and I/O selection.

Classname: cBatch_Server

Base class: Message

Package file: BatServ

Filename suggestion: XXXXXXXX.BTS

Include command: Use_Extend

Page 8.12 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 8: Batches Batch subsystem

8.3. Batch subsystem This is the ‘free form’ batch class. Its only action is that it will appear in the reports pull-down. If you select this option, the message stored in the pBatch_Procedure property is sent.

This makes this class very similar to the cSpecial_Zoom class discussed in the data entry section.

8.3.1. pID Again, this property identifies the class and provides a hook into the help and menu system.

Syntax: Set pID To [Val]

8.3.2. Redirect Errors If you set this property to TRUE, Classify will redirect all erros, just like in the batch server, and display them at the end of the batch. If you set it to FALSE (default), errors will popup.

Syntax: Set pRedirect_Errors To [True|False]

8.3.3. pBatch_Procedure The message stored in the property will be sent whenever the user selects this option from the report pull-down.

Syntax: Set pBatch_Procedure To [Message_ID]

8.3.4. Summary This class does (close to) nothing and is meant to hook a piece of procedural code into the report pull-down.

Classname: cBatch_Subsystem

Base class: Client

Package file: BatchSub.PKG

Filename suggestion: XXXXXXXX.BTC

Include command: Use_Extend

Mandatory property: pBatch_Procedure

Special remarks: cBatch_Subsystem is not a part of the pre-compiled Classify classes. You should specify USE BATCHSUB if you want to use this class.

(c) '92 - '95 Calvin Consultancy May 1995 Page 8.13 Classify Handbook Chapter 9: Programs

9. Programs We now have studied the main building blocks for programs. So we come to the actual building of the program.

This is easier than you might think, since we already pre-fabricated all the components by creating classes for them. The actual program is almost nothing more than creation of pre-defined objects. This is what a typical program could look like:

Example: Use Classify

Object oDesktop is a cDesktop No_Image

Set pID To “PROGID”

Use_Extend Cust.Vw Use_Extend_Img Cust.Img For oCustomer_Maintenance

Object oCustomer_Maintenance is a cCustomer_View End_Object

Use_Extend Parts.Vw Use_Extend_Img Parts.Img For oParts_Maintenance

Object oParts_Maintenance is a cParts_View End_Object

Use_Extend Outst.Btc

Object oOutstanding_Invoices_List is a cOutstanding_Invoices_List No_Image End_Object

End_Object

Start_Ui oDesktop Abort

This actually represents the full code for a program with two data entry modules (customers and parts) and a report (outstanding invoices). We will go over the seperate parts of this program and we will also introduce a couple of additional tools.

The first line, Use CLASSIFY, includes the most commonly used Class- ify classes for both data entry and batches. If you are just using data entry modules in a specific program, you can also use Use CLASS_DE. This will only include classes for data entry and save you some memory. For programs containing only batches, CLASS_BT is avail- able.

(c) '92 - '95 Calvin Consultancy May 1995 Page 9.1 Chapter 9: Programs Classify Handbook The desktop

9.1. The desktop Every Classify program needs one object of the cDesktop or cMini- mal_Desktop class class. This object is vital to all Classify opera- tions and should also be the object that is first activated by the Start_Ui command.

Starting this object will cause all initialisation to take place and it will show the standard action bar (cDesktop only; cMinimal_Desktop will start the contained modules automatically), after which the user is prompted for his user ID and password. As soon as the user has been identified, colors will be set to his preferences and if selected, a button bar and helpline will display.

Hint: You can supply username and password directly form the commandline if you want. This is required for programs using cMinimal_Desktop as the base class.

The desktop will automatically scan the available views and batches and create a Function pull down listing all the views and a Report pull down listing all the batches.

You can now activate the views and batches selecting them from the specific pull-downs. If you select ‘exit’ from the function pull down, that will terminate the execution of the UI and return to the command immediately following START_UI.

If you try to exit the action bar, it will send a message to all active views to check whether they can be aborted. This will involve sending the message stored in pMay_Destroy_Function and check- ing for possible data loss. If any view cannot be closed, termination of the desktop will abort and the view will gain the focus.

Page 9.2 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 9: Programs Groups

9.2. Groups Since any pull down will take only 15 entries, you might need to create cascade-pull downs. This is done in a fashion similar to the option groups. There are two classes available to do this: » cView_Group » cBatch_Group

The view group class should be used to group views, the batch group for grouping batches. Again, as with the option group class, you can create multiple levels of cascade menu’s. Per level, you must include an image file called CASCADE#.IMG where # stands for the level. You can then specify the image name CASCADE_# on the object definition line.

The CASCDE#.IMG files are located in the PKG directory so then can always be used, even from other projects.

Example: Use Class_DE Use Viewgrp

Object oDesktop Is A cDesktop No_image

Set pID To “HDSSYS”

Use_view Hdssysvw Use_image Hdssysvw For oHdssys_vw

Object oHdssys_vw Is A cHdssys_vw End_object // oHdssys_vw

Use_Extend Cascade1.Img

Object oTable_Group is a cView_group Cascade_1 Set pID To “Tables”

Use_view Hdslmt Use_image Hdslmt For oHdslmt_view

Object oHdslmt_view Is A cHdslmt_view End_object // oHdslmt_view

Use_view Hdstc Use_image Hdstc For oHdstbl_hdstbc_view

Object oHdstbl_Hdstbc_view Is A cHdstbl_Hdstbc_view End_object // oHdstbl_Hdstbc_view

End_Object

End_object // oDesktop

Clearscreen Start_ui oDesktop Abort

(c) '92 - '95 Calvin Consultancy May 1995 Page 9.3 Chapter 9: Programs Classify Handbook Other programs

9.3. Other programs Although it might be theoretically possible to build all functionality into one program, OS and DataFlex limitations will prohibit this. Classify offers a standard ‘gateway’ to other programs by the ‘Exter- nals’ options from the Desktop pulldown. However, this option is meant for general services, not to build a full menu system.

For that, you should use the pull down menus. These can be controlled both by programming and by source code.

9.3.1. The menu file If you want to display menus specified in the menu file, you only need to create an object for the (cascade) pull down. As soon as the menu gets activated, it will “read” the menu-definitions from the file and display the appropriate options.

Every cascade object must be specified and the property pID must be set. You must also specify an image for the pull down. We provided 5 standard images (CASCADE_1 through CASCADE_5 in the files CASCADE0.IMG through CASCADE5.IMG). While you can use the same image for multiple pull downs, you should use different images for different levels.

Example: Use_Extend Cascade1.IMG

Object oDesktop Is A cDesktop No_image

Set pID To “HDSSYS”

Object oView_Group is a cView_Group Cascade_1 Set pID To “OPT_CAS” End_Object

End_object // oDesktop

This will force Classify to look up the definition for the menu “OPT_CAS” and display its contents. You can now set up any menu in the menu file (which could even be user-specific).

9.3.2. Coding menu options The alternative is to code the menu options into the program. This can be done by creating a view-group object and place a number of Set pMenu_Item messages in the object.

This message will not just allow you to specify external programs, but also all the other options you can specify in the menu file. You can even specify a message here, which is impossible in the menu file. In the following chapter, you will find a full discussion of the message.

Example: Use_Extend Cascade1.IMG

Object oDesktop Is A cDesktop No_image

Set pID To “HDSSYS”

Object oView_Group is a cView_Group Cascade_1 Set pID To “OPT_CAS”

Set pMenu_Item End_Object

End_object // oDesktop

Page 9.4 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 9: Programs cView_Group

9.4. cView_Group We already illustrated three uses of this class. You can actually mix all these uses (create both views and coded menu options in one group and add some extra choices from the menu file).

In this paragraph, we discuss the full functionality of this class.

9.4.1. ID This is the main property in this class. It should contain a description matching an entry in the menu file if you want to be able to add options through the menu file (8 characters). The contents of this property will also be used to determine the menu-description in the help file.

Syntax: Set pId To [Val]

9.4.2. Pull down number By default, a cascade pull down will appear in the first pull down of the action bar (Functions). But by changing this property, you can select another item from the action bar (1 = Reports). The only difference between cBatch_Group and cView_Group is the default value for this property.

Of course will this property only work if the cascade is not nested within other pull downs. Once you start nesting menu’s, the cascade will always follow the object structure.

Syntax: Set pPull_Down_Number To [Number]

Default: 0

Example: Set pPull_Down_Number To 1

9.4.3. Menu item This is a very powerfull message that allows you to create several types of menu entries. It can set up the menu for external functions, other pull downs, key-strokes and more. Since the logic for this message strongly resembles the logic of the menu file, you can also use this paragraph as guidance for creating your own menu file.

Syntax: Set pMenu_Item [LineNr] [Description] [Type] [Subtype] [Command] [Object] [Shadow_Mask]

This message will create or update a menu item in the pull down. The following arguments always have the same effect: » LineNr The line number in the menu file where you want this option to appear. If you specify a line number already containing informa- tion, this information will be overwritten. If you specify a line number from 91 up to (and including) 99, the menu item will be appended to the currently existing menu. » Description This is the description as it will be displayed in the pull down (except for type “L”). » Shadow_Mask This indicates when the menu option should be shadowed. This is indicated by a reference to the type of navigation. If the current activation does not match the specified navigation type, the item will be shadowed. If you specify an empty navigation mask, the option will never be shadowed. The following navigation types are pre-defined: ° @_Dekstop ° @_Form ° @_Multi_Line ° @_Edit

All of the other arguments can contain values depending on the type of the menu item.

Type L:

(c) '92 - '95 Calvin Consultancy May 1995 Page 9.5 Chapter 9: Programs Classify Handbook cView_Group

If you specify this type, Classify will display a line in the menu and assign a “dummy” message to the menu choice. » Subtype Indicates the type of line: ° S: Single line ° D: Double line » Command Not used » Object Not used

Type N: Assign a “dummy” message to the menu choice (but display the supplied description) » Subtype Not used » Command Not used » Object Not used

Type M: Set up the menu item to sent the specified message to the specified object when the user selects the item. » Subtype Not used » Command Message IS » Object Object to which the message should be sent

Type K: This option is typically used if you want to display a menu option that is also available as a hot key. In that case, you can just specify the key and Classify will sent “Process key” to the specified object. This allows you to be independent of the actual message. » Subtype The state of the key: ° S: Shift key pressed ° C: Control key pressed ° A: Alt key pressed ° Space: No extra keys pressed » Command The scancode for the key » Object Not used

Type C: This type can be used to activate a cascade pull down. Usually, this will not be necessary since the cView_Group automatically deter- mines all the “nested” cascades. » Subtype Specifies how to identify the cascade: ° O: Object ID ° N: Name » Command Should contain the name of the pull down if subtype is “N”. For activation by object id, this argument is not used. » Object This argument is only used if you specify the pull down by object name and in that case it should contain the object ID.

Type A: This type allows you to activate external programs from the pull downs. The logic resembles that of the “externals” functions. » Subtype This specifies the type of application: ° 1: CHAIN ° 2: CHAIN WAIT

Page 9.6 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 9: Programs cView_Group

° 3: RUNPROGRAM ° 4: RUNPROGRAM WAIT ° 5: CHAIN, passing user id to another Classify program ° 6: CHAIN WAIT, passing user id to another Classify program » Command The name of the program (can contain extra arguments) » Object Not used

Type S: This type will file a service request with the desktop. These services could be extended by the programmer. » Subtype The type of service that is requested. The following service requests are pre-defined: ° L: Login ° E: Editor ° C: Calendar ° A: cAlculator ° X: eXternals ° W: save Windows ° P: change Password ° D: Display logfile ° I: pIcklist ° B: aBout ° F: Field help ° Z: Zoom help ° H: file Help ° Y: subsYstem help ° U: UI-help » Command Not used » Object Not used

Example: Set pMenu_Item 99 “Dos shell” “A” 2 “Command.com” 0 “” // Start command.com Set pMenu_Item 99 “Close view cF4" ”K" “C” Key_F4 0 “” // Specify cF4 Set pMenu_Item 4 “” “L” “S” 0 “” // Draw a line

9.4.4. Summary Classname: cBatch_Group cView_Group

Package file: BatchGrp.Pkg ViewGrp.Pkg

Special remarks: These files are not part of the standard Classify pre-compile.

(c) '92 - '95 Calvin Consultancy May 1995 Page 9.7 Chapter 9: Programs Classify Handbook Demo versions

9.5. Demo versions Classify provides automatic support for demo versions of software. The demo limitation supported by Classify is based on the maximum number of records in a file.

In the desktop, you can specify a maximum number of records for every file. This is done in the desktop rather than in the DDO because it is possible to open and use files without including the DDO (for instance in batches).

Classify will test the number of records in the file upon activation and during create actions. If the demo limit is exceeded, Classify will issue a fatal error.

9.5.1. Demo limit This is the file-specific property that stores the maximum records for a file. If not set, it will ignore the file size.

Syntax: Set pDemo_Limit [Filenumber] To [Val]

Alternate: Set pDemo_Limit [Filename].File_Number To [Val]

Default: 0 (checking disabled)

9.5.2. Demo version This property enables or disables the demo-version limitation check- ing. If set to true, Classify will perform all the checkings. If set to False, no checking will take place.

Syntax: Set pDemo_Version To [True|False]

Default: False

Page 9.8 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 10: Classify relationships

10. Classify Classify will handle relationships far more powerful than the DataFlex base products, but it also is more formal about relation- relationships ships than the original kernel.

This part of the manual is designed to give you a better insight in the way Classify handles relationships and how you can use the en- hanced capabilities of Classify to create more powerful relation- ships. It explicitly does not discuss the setup of these relationships. This is done in the chapters “Data Dictionary; relationships” and “Data Dictionary; dependencies”.

Designing a correct datamodel will help you to build stable applica- tions more easily. Many problems in existing software can be traced back to errors in the underlying data model. We have put a lot of effort into the support of more powerful relationship structures. This means that in general, you will be able to implement the relationships as they appear in your analysis document. It will usually not be necessary to create special structures such as alias files, artificial bridge files or manually coded relationships, to work around techni- cal limitations.

Keeping the datamodel as pure as possible will help you in the design and programming phases of the development as well as during maintenance.

For those who want to know more about relational database design, we can suggest reading the “Introdcution to database design” by Chris Date.

(c) '92 - '95 Calvin Consultancy May 1995 Page 10.1 Chapter 10: Classify relationships Classify Handbook

10.1. The key of a file Every file consists of a number of records. Each record can be uniquely identified by the value of a specific field or group of fields. This field, or group of fields, is called the key of the file. The contents of the key is the key value of this record. The key value should uniquely identify the record within the file.

Classify will require you to set up an index containing only the field(s) making up the key. This is not really an additional requirement since you will usually do this any way.

You should identify the key by setting the pMain_Index property in the DDO. The data dictionary will read the index specification and setupthekeyfieldsaccordingtothisinformation.

Syntax: Set pMain_Index To [indexNr]

The ability to use multiple fields as the key makes the use of overlap fields for relationships unnecesary. Therefore, the use of overlap fields in relationships is not supported in Classify.

If you want to keep the overlap relationships in the data file definition for compatibility reasons, you can specify the multi-field relationship as a Classify relationship (relation number <> 255), specify the overlap relation in DF-File and set the pUse_DF_File_Relations property in the DDO to false. This will cause Classify to ignore the relationships setup in DF-File and only to use relations setup in the DDO.

Syntax: Set pUse_DF_File_Relations To [True|False]

Default: True

The above technique (ignore DF-File relations) can also be used if you want to specify relationships conditionally (e.g. based on a certain module being purchased) or when you are using different FD filestoworkaroundthenumberoffilesinfilelist.

Page 10.2 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 10: Classify relationships

10.2. Foreign keys The theory of database design requires us to go through a process called normalization. This will give us a data model that has no redundant information in it. Instead, it will consist of several files that are linked to each other by the use of the key-values. An example of such a relationship is the order-header / order-line construction, as shown in the figure below. Example:

Order header CustNr OrderNr Date Orderlines Amount OrderNr LineNr Item Price Nr_Of_Items

The order number is the key for the order-header file. By repeating this key in the order-line file, we know which order lines belong to a specific order header. The order-number links these two files to- gether. The order number in the order-line file is called a foreign key for the order header file.

Even though a file can have only one key (for orderline, that would be order number + line number), it can have multiple foreign keys. In fact it can have foreign keys pointing to different files, but it might also have multiple foreign keys pointing to the same file, or maybe even to itself.

A foreign key is identified by the fields it is made off (these should match the order, number, type, length and order of the fields in the key it is pointing to), the file it points to and an arbitrary sequence number to distinguish between several foreign keys pointing to the same parent file.

In the example above, there is only one foreign key in the order-line file. If we would add an article file and include the article number in the order-line file, this would represent a second foreign key. The following figure shows this in the diagram.

Example:

Orderheader Items CustNr ItemNr OrderNr Description Date Orderlines Color Amount OrderNr Stock LineNr Item Price Nr_Of_Items

If we take another example using two files representing a simple message-tracking system, we will see that there are two foreign keys pointing to the same parent file. Both the fields ‘message from’ and ‘message to’ are pointing to the persons file.

We now not only have a relationship, but we also need to identify the relation. This could be done by an abstract name (e.g. “TO” and “FROM”, but because of speed considerations, we have imple- mented it using numbers (1 .. 250, 255 for DF-Relations).

(c) '92 - '95 Calvin Consultancy May 1995 Page 10.3 Chapter 10: Classify relationships Classify Handbook

The following diagram shows the mail system database: Example:

Persons Messages Person_ID From_ID Name To_ID Address Message City Date Phone

You could apply names to the relationships using the DataFlex rename command:

Syntax: #REPLACE @_MAIL_FROM 1 #REPLACE @_MAIL_TO 2

Page 10.4 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 10: Classify relationships

10.3. The DataFlex Classify will handle relationships more powerful than the DataFlex kernel. Still, it is important to know the way DataFlex handles approach relationships, since for example DFQuery is limited to this implemen- tation. FlexQL on the other hand will allow you to setup relationships more flexible.

DataFlex will allow you to set up relationships on a field-to-field basis. You could even use different ‘keys’ in the same file. On the other hand, relationships can only be based on single fields. A key based on multiple fields can only be defined using a ‘overlap field’, combining the multiple fields into one.

If multiple relationships must point to the same file, this can only be achieved by using ‘alias’ files.

(c) '92 - '95 Calvin Consultancy May 1995 Page 10.5 Chapter 10: Classify relationships Classify Handbook

10.4. The Classify solution Classify requires a key to be defined, and all relationships should point to this key. But remember that in Classify, this key may consist of multiple fields. As in DataFlex, we require that an index is defined consisting of the fields in the key and these fields only. This way, we can retrieve the parent record based on the foreign key specified in the child file.

Next, you need to define the foreign keys in the child files. As we said earlier, these are defined by the fields, the file they point to and a sequence number. To support as much of the original DataFlex implementation, we will let you set up one foreign key per parent file in DFFile. This foreign key may consist of multiple fields. Just remember that the order of the fields must match the order of ‘related to’ fields in the key in the parent file (which is the order they appear in the index).

Classify will automatically scan the file definition and set up the foreign keys (this can be disabled by setting pUse_DF_File_Rela- tions to False). The foreign keys will be assigned sequence number @_DF_Relation (255). Since the rest of Classify is set up to act on this foreign key by default, their might be numerous occasions where this way of working is sufficient for your needs. But if you need to set up additional relationships, you can do so by using the mAdd_Foreign_Key_Field message to set these up. You will have to send this message for every field in the foreign key.

Finally, one important remark. In standard DataFlex it is quite com- mon to specify relationships between fields, not because these fields link the records together, but because the progammer wants the contents of the field in the parent to be copied to the field in the child. This practice should be abandoned when using Classify. Classify will offer you other ways to achieve this and it will confuse the automatic detection of the foreign keys. You should use the depend- ency functions in Classify to achieve this.

10.4.1. How Classify reacts In the following paragraphs, we try to outline which elements of Classify react to the relationship specifications and how you can set them up to act the way you want them to.

10.4.1.1. The Data Dictionary The data dictionary is, of course, the central knowledge base for relationships and acts as a service center for all other objects working with relationships. But it also uses this information to deter- mine the child-records whenever a record is deleted.

If the data dictionary finds that deletion of a parent record is permit- ted, it will find all the child-records. This is done by finding a matching foreign key in the child file. If multiple foreign keys point to the parent, Classify will first find all children based on the first foreign key, then on the second and so on.

Classify will first check all child-records to determine if deletion is permitted. Only if all records are ‘deleteable’, Classify will refind them all and delete them.

This process is also controlled by the settings of the pOk_To_De- lete_Range and the pDelete_Range properties.

10.4.1.2. The subsystem If a subsystem is nested within another subsystem, it will display related information (either the parent record or the child records). By setting the pKey_Nr property you can setup a subsystem to act on a specific foreign key.

Since this property is set to 255 by default, Classify will act on the relationships setup in DF-file by default. If you want a subsystem to

Page 10.6 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 10: Classify relationships

act on an auxiliary foreign key, you should set this property manu- ally.

10.4.1.3. The report The report-nesting works a lot like the subsystem nesting. And likewise, it is set up by default to act on the ‘dffile relationship’, but it can be set to act on other foreign keys by setting the pKey_Nr property.

10.4.2. Relation-commands In the following paragraph we discuss the commands that are used to maintain relationships.

10.4.2.1. Attach The attach command is replaced in Classify by the mAttach mes- sage.

Syntax: Send mAttach [Parent_File] [Relation_Number] [Subsystem Parent] [Subsystem]

This message should always be sent to the data dictionary object for the child file. » Parent file is the number of the parent file » Relation_Number is the identifier for the relation (use @_DF_Re- lation for relations specified in DF-File). » Subsystem should hold the ID for the subsystem holding the information for the child file. All attached information will be stored in this subsystem. If you specify zero (0), attached infor- mation is placed directly into the global file-buffer. » Parent Subsystem is the ID for the ID of the subsystem contain- ing the information for the parent file. Usually, this will be the parent object for the subsystem of the child file. If you specify zero (0), information is taken directly from the global file-buffer.

Special care should be taken if you address the global buffers. Please refer to the appendix on file management for more informa- tion.

10.4.2.2. Relate Like the attach, relate is replaced by a message, or more accurately, a set of messages. All these messages should be sent to the data dictionary object of the child file.

mRelate The first is mRelate, which works much like the relate command, finding all parent files recursively. This messages does not support the complex relationships Classify offers. It operates on the global file buffer only.

Syntax: Send mRelate

Warning: This message is supplied for compatibility. However, we strongly suggest you use the more specific relation mes- sages.

pRelate Key The pRelate_Key message is usually the best to use. It will take the parent file and the relation number to this file as arguments.

Syntax: Get pRelate_Key [Subsystem] [File_Number] [Relation_Number] [Recurse_State]; To [Var] » Subsystem should hold the ID of the system containing the information for the child file. If you specify zero (0), the relate will be performed based on the contents global file-buffer. » File number is the number of the parent file to relate (= find based on the information in the child). » The relation number should identify the relation. Use @_DF_Re- lation for relationships specified in DF-File. » If Recurse_State is True, Classify will send a pRelate_Field for the first field in the key of the parent file if the relate is success- ful. This will cause the grand-parent to be found automatically.

(c) '92 - '95 Calvin Consultancy May 1995 Page 10.7 Chapter 10: Classify relationships Classify Handbook

The pRelate_Field will also get recursive_state True, so the entire parentage will be parsed.

If the relate is successful, this message will return 99. If the relate fails, a -1 value is returned. If only a partial match is found, the return value indicates the number of matching fields. If the message re- turns zero (0), the specified relation does not exist.

Example: Suppose a relationship is specified based on the fields Main_Group, Sub_Group, Part_Code. If you try to perform a relate and Classify would not be able to find a parent matching the child information, but this parent record would hold the same Main_Group, the return value would be 1.

This is especially very useful if you are validating newly entered data. If the user enters the Main_Group, you could do a relate. A return value of -1 would indicate there is no record with the main_group specified. An error could be generated. If 1 is returned, the user has a chance of completing a valid foreign key.

pRelate_Field The pRelate_Field message is supplied to make usage of relation- ships a bit easier. This message will automatically determine if the field specified is part of a foreign key. If so, it will issue the pRel- ate_Key message based on the information stored in this foreign key.

Syntax: Get pRelate_Field [Subsystem_ID] [Field number] [Recurse_State] To [Var]

Alternate: Get pRelate_Field [Subsystem_ID] Field [Filename.Fieldname] [Recurse_State]; To [Var] » Subsystem should hold the ID of the system containing the information for the child file. If you specify zero (0), the relate will be performed based on the contents global file-buffer. » Field number is the number of the field that should be part of the relation. » If Recurse_State is True, Classify will send a pRelate_Field for the first field in the key of the parent file if the relate is success- ful. This will cause the grand-parent to be found automatically. The pRelate_Field will also get recursive_state True, so the entire parentage will be parsed.

If the relate is successful, this message will return 99. If the relate fails, a -1 volume is returned. If only a partial match is found, the return value indicates the number of matching fields. In this mes- sage, the relate is considered fail if the specified field is not part of the matching fields. So based on the above example, a pRel- ate_Field passing Sub_Group and finding only a matching Main_Group will return -1. If both Main_Group and Sub_Group are found, 2 is returned. If the Part_Code matches as well, 99 is re- turned. If the message returns zero (0), the specified relation does not exist or the field is no part of a foreign key.

If the field is part of multiple relationships, Classify will attempt to find al the parent fields. If all parents are found, a value greater than 0 is returned (the number of matching field in the last relate). If any of the relates fails, -1 one is returned.

Warning: We suggest that if you know parent file and relation number, you use the pRelate_Key.

The pRelate finally is a ‘shortcut’ for using pRelate_Field. It is designed for use in formulas to perform multiple relates and it is available in zoom classes as well (in which case, it is just re-directed to the data dictionary).

Syntax: Get pRelate [Parent_File] [Relation_Number] [Special_Code] To [Var] » The Parent_File indicates the parent file the message should relate.

Page 10.8 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 10: Classify relationships

» Relation number specifies which relation to use (@_DF_Relation for relationships specified in DF-File). » The special code should have one of the following values: ° 0: Get the values for the child file from the current subsystem. ° -1: Do not perform the pRelate and return -1. ° >0: Get the information for the child file from the global buffer. The special code should contain the file number for the child.

The valid return values for this message are: » -1: related failed » >0: The number of the parent file.

Example: As stated, this message is especially useful in formulas. The following formula will try to find the grand-parent for a record in the current subsystem:

(pRelate(Current_Object,GrandPa.File_Number,@_DF_Relation, ; (Parent_File(Current_Object(Parent.File_Number,@_Df_Relation,0)))))

Because of the brackets, the pRelate for Parent will be performed first. The result of this will be -1 (failed), which is the special_code for the second pRelate, indicating that no further action is required and the overall return value will be -1. If the first pRelate finds a valid parent, it will return the file number for the parent, which is the child for the next pRelate.

These formulas can also be used with pDisplay. This is a small procedure taking two arguments:

Syntax: Get pDisplay [Condition] [Value]

This message will return blanks if Condition equals -1 or Value if Condition has a value greater than 0.

If you would use the formula from the previous example as the condition and a field from GrandPa as value, this message would display either blanks if no grandparent is found or the correct field (the condition is evaluated first).

(c) '92 - '95 Calvin Consultancy May 1995 Page 10.9 Chapter 10: Classify relationships Classify Handbook

10.5. Advanced usage We have already discussed the capability to have multiple relation- ships to the same parent file. But Classify offers two more intriguing capabilities: » Recursive relationships » Multiple relationships from one field

The following diagram shows a datamodel that can be implemented without problems using Classify:

2 3 4 5 6 Discount Discount Product Sales person Customer schemes details group

er to ce

7 8 9 10 Orderheader Orderline Product Inventory

nents

11 12 Deliveries Warehouse

10.5.1. Recursive relationships In many data models, recursive relationships could simplify the structure quite dramatically. Bill of materials is only one example of many. A standard contact database using recursing to allow for companies, persons and departments to be tracked in one common file (one access path, unlimited number of levels) is another.

While Classify does support this type of relationship, there are some considerations. » Classify will not handle recursive deletion of child records yet. You should set pOk_To_Delete_Range false for the file if you want to use a recursive relationship » You cannot have recursive dependencies

Apart from the above limitations, recursive relationships work just like all other relationships. You can nest multiple subsystems to show company and employee or part and components. The DDO will automatically check for the existence of child records before deleting a parent record and so on.

10.5.2. Multiple relationship Sometimes, one field should relate to multiple parents. The deliver- from one field ies file in the above diagram is an example of this situation. The key for a delivery consists of at least the product and warehouse plus some discriminating field (e.g. date). The combination warehouse + product relates to the inventory file. But the warehouse ID should also relate to the warehouse file (this allows us to build a view with a delivery view nested inside the warehouse view, showing all the deliveries to that warehouse regardless of product). The same applies to the relationship from deliveries to product.

Page 10.10 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 10: Classify relationships

10.6. Dependencies No matter what relation database theory teaches us, we will always find it useful to include redundant information in our databases. It might be subtotals, or just an additional field to make reporting more powerful.

This usually shows during the transition from the conceptual model to the technical database layout. The motivation might be speed or the ability to index on a particular field.

Example: Usually, you might have the need for an invoice-total, based on the sum of all the invoice-line amounts. The relational design would dictate that we find all invoice lines and calculate the sum whenever you need it. Performance issues dictates us to keep the total in the header and update it constantly. Another situation might occur if we need to print an invoice in zip-code order. Now the only information about the customer needed in the invoice-header would be the key (customer number). This would cause us to go through all clients by zip-code and check if they have an invoice that needs printing. Doing a report in this fashion will take a considerable amount of overhead. In order to optimize this report, we might want to copy the contents of the zip-code field from the parent to every child.

Classify will allow you to setup up these dependencies in a very easy and comprehensive way. The pCreate_Dependency message al- lows you to specify dependencies between fields, not between keys.

The dependencies are specified by: » The field triggering the dependency (meaning any change in this fieldwillresultinanactiontobetaken). » The file and field to be effected by the dependency (the field that should be changed whenever the triggering field is changed). » The relation number for the foreign key to be used when relating to this parent (zero if the parent should be found based on the relation set up in dffile). » The actions to be taken whenever a change in the triggering field is detected. These actions are specified by single procedures that will be executed depending on the type of change that is taking place. Supported functions are: ° Purge This procedure is executed whenever you purge a record (a batch function). The purge function is supplied to allow you to remove for instance inventory-mutations without changing the inventory totals (which would happen with a standard delete). This proce- dure will usually be used when deleting historical information. ° Create Executed whenever a record is created. ° Delete Executed whenever you delete a record, except when you do it using the purge function in a batch. ° Backout This function is executed if you delete a record or if you change it. When changing the record, the record buffer will still be filled with the ‘old’ information, and the ‘old’ parent records will be in the buffer. ° Update This procedure is executed whenever the record is created or changed. The new values are moved into the record buffer and the new parents are found prior to the initiation of this message.

Please refer to the chapter on the Data Dictionary for more informa- tion and examples on dependencies.

(c) '92 - '95 Calvin Consultancy May 1995 Page 10.11 Classify Handbook Chapter 11: File handling

11. File handling Classify handles files in quite a different manner than DataFlex does. In this part of the manual we will try to explain just how Classify handles files and how you should access them.

DataFlex has one file-buffer per file. If you need more, the only possibility is to create an alias file. While this might work under 2.3 to support some non-hierarchical relationships, it will not work in a non-modal 3.0 environment. In the non-modal environment, multiple instances of the same file will need to be active in the same program.

Example: Suppose you have two main views in a program: customer maintenance and order-entry. During order-entry you will be using the customer file and prob- ably only a part of the information needed for the order-processing (like payment conditions) will be visible in items. So, after finding the correct customer in the order-entry-view, you might still need other information from the buffer. But during the order-entry process the user might decide to go to the customer maintenance view first and change information there. This would definitely change the active record in the file-buffer.

Another example is a system where a customer would request the ability to work on two customers at the same time (quite handy actually, since you will only need to create the second object [3 lines of code] and could charge for a ‘doubled functionality’).

To avoid these problems we gave the subsystem class and the report class the ability to have its own private (local) buffer. This buffer is fully encapsulated and can not be effected by file-opera- tions in any other object.

(c) '92 - '95 Calvin Consultancy May 1995 Page 11.2 Chapter 11: File handling Classify Handbook The local file buffer

11.1. The local file buffer Every single subsystem is used for maintenance of a specific file, specified by the pMain_File property. The subsystem will take care of buffering in the following way: » During initialization of the subsystem, it will take an inventory of its zooms, registering all fields used in one or more zooms. There is no need for the subsystem to buffer these fields, since they are kept in the items. Once the inventory is taken, the subsystem will create an array where it will keep the values of all the fields not contained in the zooms. We usually refer to this array as the ‘dummy zoom’, because it acts like an invisible zoom. » Binary and text fields are not buffered if they are not in any of the zooms. This is done mainly because of memory conservation reasons.

While you are in the subsystem or a report, you can access the local buffer using the pLocal_Field_Value message. This message will retrieve/set the field value inside the subsystem only. If a specific field is used in multiple zooms, the set pLocal_Field_Value will show the new value in all the zooms automatically.

Syntax: Set pLocal_Field_Value [Field_Number] To [Val] Get pLocal_Field_Value [Field_Number] To [Var]

Alternate: Set pLocal_Field_Value Field [File_Name.Field_Name] To [Val] Set pLocal_Field_Value Field [File_Name.Field_Name] To [Var]

The local file buffer is filled whenever a new valid record is found by the user through the use of the find-keys or buttons. If you want to fill the buffer ‘by hand’ after you have found a record, you can use the message mRecord_Found1.

In the DDO, you can access the file buffer of the subsystem or report requesting the service from the DDO by using the same messages. These are redirected by Classify to the subsystem. This redirection is done if a subsystem requests specific services from the DDO, like validation or saves. In these cases, the invoking message will pass the subsystem address which is stored temporarily in the Subsystem property in the DDO. If you send messages to the DDO yourself, the subsystem address might not be set.

11.1.1. When to use the local » in all field messages (entering, exiting, validation, prompt and buffer zoom); » in ’ok to save’ and ’ok to delete’ check procedures; » in the ’before save’, ’before validation’, ’after validation mes- sages’; » in the ’before update message’ to retrieve the new values; » in ’after save messages’.

11.1.2. Local buffers outside When you select a subsystem, Classify will automatically create a the subsystem virtual buffer for every subsystem. when you need to use a local buffer outside of the subsystem, you can create an object based on the cFilebuffer class. The filebuffer class provides you with the same functionality that the subsystem is providing with the exception of the user interface aspects. So apart from having zooms, the filebuf- fer acts just like a subsystem. you can nest the buffers just like you would nest subsystems. All the same commands like save and find will operate on the filebuffer class as they would on the subsystem.

1 Please refer to the reference guide for more information about this message.

Page 11.3 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 11: File handling The local file buffer

When you start using the filebuffer, you don’t need a view as you would when you would use a subsystem. The top filebuffer will act as the coordinator between all nested filebuffers. When you want to nest filebuffers but you don’t want to link them together for save and find operations, you can control this by setting the slave state of the top filebuffer to @_is_main_file.

Syntax: Set pSlave_State To @_Is_Main_File|@_Is_Child_File|@_Is_Parent_File

Classify will atomatically set the value of this property based on the nesting of the buffer (or subsystem) unless you provide a value under program control.

This also means that you could nest a filebuffer in a subsystem and by setting its slave state still keep it isolated, or alternately, by not setting the slave state allow it to latch on to the subsystem structure.

The following messages are supported by the file buffer (and thus subsystem) class:

11.1.2.1. Request save The message will save a set of records in the current filebuffer structure. It will delegate up to the “top” buffer in the structure (slave state = “is main file”) and from there perform a save on that object and all children (except if they have set the slave state to is main file).

Syntax: Send mRequest_Save

This message will automatically take care of validation, intelliwrites, locking etc.

11.1.2.2. Request clear This message will clear the current buffer and all of its children.

Syntax: Send mRequest_Clear

11.1.2.3. Request clear all This message clears the whole structure be sending the message to the top buffer and than clearing all the subsystems.

Syntax: Send mRequest_Clear_All

Request delete

This message deletes the currently active record from the current filebuffer. The data dictionary will handle the deleetion of all children (independent of any nested filebuffers) and after the record is suc- cesfully deleted, the buffer is cleared.

Syntax: Send mRequest_Delete

11.1.2.4. Find This message can be used to find a record based on the current contents of the buffer and using the constrain applied to the buffer.

Syntax: Send mFind @_First|@_Prev|@_Le|@_Eq|@_Next|@_Last

If a record is found, the information about that record is moved from the global buffer into the local buffer.

11.1.2.5. Init object This message is used to initialize the buffer. Since a buffer can only be initialized after it has been fully created, it is mandatory that you manually send this message to a buffer object before using it.Thisisnot required for a subsystem.

The buffer will automatically send this messages to all other buffers in the same structure. If you nest a buffer inside a subsystem, the

(c) '92 - '95 Calvin Consultancy May 1995 Page 11.4 Chapter 11: File handling Classify Handbook The local file buffer

buffer is not automatically initialized. You can augment the message mDetermine_Contents of the subsystem to do so.

Syntax: Send mInit_Object

Warning: You must send this message prior to using the filebuffer object. Failing to do so will cause all sorts of errors!!!!!

Page 11.5 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 11: File handling The DataFlex file buffer

11.2. The DataFlex file Of course, the DataFlex file buffer is still available. Although you can still access it using the ‘old’ procedural commands, we recommend buffer that you use a number of messages we specified in the file handler class. These messages will automatically respect the ‘intelliwrites’ that has been implemented in Classify. The intelliwrites will log all save-requests during a lock, but it will not do the actual saves. Only when an unlock is requested, the save-requests are honored.

During these saves, all related commands are first compared with the current file buffer. If it turns out the keys match, no find is done. This will speed up performance dramatically if you have multiple relations to the same file.

Example: If intelliwrites are active and an object sends a pSave_File message, Classify will ‘remember’ this, but will not immediately write the file. If you would now issue a CLEAR command, this would clear the buffer with the ‘information to be saved’ in it. If you would sent pClear_File, Classify would detect the information in the buffer and first save the record and clear the file after that.

Another advantage of using the messages is that they are more powerful and will return error codes instead of relying on a global indicator.

11.2.1. Clear File This message will clear the buffer for the specified file. If a save was pending for this file, it will be performed first.

Syntax: Send mClear_File [File_number]

11.2.2. Special Clear This message will perform a clear, but after the initial clear, it will initialize the buffer with ‘min’ or ‘max’ values. This is imperative if you are using indices with descending fields. As a direct result of this dependency on the index, this message will need both the index and a direction.

Syntax: Send mSpecial_Clear [File_Number] [Index_Number] @_First|@_Last

@_First will signal to initialize with the values to find the first record, @_Last will set the buffer for a find of the last record.

11.2.3. Save File This message will save the indicated file buffer. However if intelli- writes are active, it will just signal the buffer as changed and pending for a save. If you need ‘write through the buffer’ (= save regardless of intelliwrites), you can pass TRUE as the second argument, in all other cases pass FALSE.

Any non-zero return value indicates an error during the save. This will always be a hardware or OS related error. All validations should be done prior to this message.

Syntax: Get pSave_File [File_Number] [True|False] To [Var]

11.2.4. Delete File This message will delete the record in the indicated file buffer. If the record was waiting to be saved during an intelliwrites operation, the file is also removed from the ‘pending’ list.

Syntax: Get pDelete_File [File_Number] To [Var]

11.2.5. Field Buffer This message can be used to access fields in the global buffers. This is done by specifying both file number and field number.

Syntax: Set pField_Buffer [File number] [Field number] To [Val] Get pField_Buffer [File number] [Field number] To [Var]

Alternate: Set pField_Buffer [File number] Field [File_Name.Field_Name] To [Val] Get pField_Buffer [File number] Field [File_Name.Field_Name] To [Var]

(c) '92 - '95 Calvin Consultancy May 1995 Page 11.6 Chapter 11: File handling Classify Handbook The DataFlex file buffer

11.2.6. Find File This function replaces the traditional FIND command. However, it will take some additional parameters as compared to the find com- mand. » File number Thisisthenumberofthefiletoperformthefindon. » Find type What is used to determine the index: index number or field number? You have two options here: ° @_By_Index ° @_By_Field » Operand If you choose @_By_Index, you will need to supply the index number here, otherwise you will need to specify the field number. » Operator The find mode. This must be one of the following: ° @_Next find the next record ° @_Prev find the previous record ° @_Ge find the next record (greater or equal) ° @_First clear the file (using mSpecial_Clear) and then perform a find. ° @_Last clear the file (using mSpecial_Clear) and then perform a find. ° @_Eq find an exact match ° @_Le find the previous record (less or equal). » Constrain function You can specify a constrain function for the find. The find will handle this internally and notify the user to ‘wait’ if records fail in the constrain. The message will be removed as soon as a valid record is found. If you specify zero (0), no constrain is performed.1 » Constrain object This is the id of the object where the constrain procedure is located. You should always specify this value, even if it is CUR- RENT_OBJECT.

If you issue a find command during the time intelliwrites are active, Classify will check if the file needs to be saved and if so, save the buffer prior to performing the find.

The function will return a non-zero value if the find failed.

Syntax: Get pFind_File [File_Number] @_By_Index [Index_Number] ; @_Next|@_Prev|@_Ge|@_First|@_Last|@_Eq|@_Le ; [Constrain_Function] [Constrain_Object] To [Var] Get pFind_File [File_Number] @_By_Field [Field_Number] ; @_Next|@_Prev|@_Ge|@_First|@_Last|@_Eq|@_Le ; [Constrain_Function] [Constrain_Object] To [Var]

Alternate: Get pFind_File [File_Number] @_By_Field [File_Name.Field_Number] ; @_Next|@_Prev|@_Ge|@_First|@_Last|@_Eq|@_Le ; [Constrain_Function] [Constrain_Object] To [Var]

Example: Get pFind_File Cust.File_Number @_By_Field Field Cust.Name @_Next 0 0 ; To Error_Code Get pFind_File Orders.File_Number @_By_Index Index.2 @_First 0 0 ; To Error_Code

1 Please refer to the chapter on subsystems for a more detailed description on constraints.

Page 11.7 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 11: File handling The DataFlex file buffer

11.2.7. File Scan This is a highly powerful message that lets you manipulate groups of records. It will go through a file using the specified index. For every valid record found, it will send a specified message.

If we compare it with the pFind_File message, we have only a couple of additional parameters: » Start_Point This indicates how you want the list to initialize: ° @_Begin_Of_File Start with a (special) clear and scan from the beginning/end of the file. Whether we use the beginning or the end depends on the find direction. ° @_Current_Record Start with a find @_Ge|@_Le and use that as the first record in the list. ° @_Continue Start with a find @_Next|@_Prev. This option is added to support browsing through a file without overlap. » Direction Do you want the scan to use @_Next or @_Prev as the main find mode. Valid choices are: ° @_Forward ° @_Backward » Max_Count The maximum number of records to scan. If you specify @_Scan_All it will go through the entire file. » Detail_Function The message to be send for every valid record. If it returns a non-zero value, it will abort the scan.

Note: This function will ‘remember’ its position in the index even if you would update fields used in the index while in the detail function.

Syntax: Get pFile_Scan [File_Number] @_By_Index [Index_Number] ; @_Begin_Of_File|@_Current_Record|@_Continue @_First|@_Last ; [Max_Count]|@_Scan_All [Constrain_Function] ; [Detail_Function] [Constrain_Object] To [Var] Get pFile_Scan [File_Number] @_By_Field [Field_Number] ; @_Begin_Of_File|@_Current_Record|@_Continue @_First|@_Last ; [Max_Count]|@_Scan_All [Constrain_Function] ; [Detail_Function] [Constrain_Object] To [Var]

Alternate: Get pFile_Scan [File_Number] @_By_Field Field [File_Name.Field_Name] ; @_Begin_Of_File|@_Current_Record|@_Continue @_First|@_Last ; [Max_Count]|@_Scan_All [Constrain_Function] ; [Detail_Function] [Constrain_Object] To [Var]

Example: Get pFile_Scan Cust.File_Number @_By_Field Field Cust.Name ; @_Begin_Of_File @_First @_Scan_All 0 ; Get_pPrint_Name 0 To How_Many

The return value always contains the number of valid records found.

11.2.8. When to use the » In constrain procedures, since while you are putting a constrain DataFlex buffer on a record you should access the DataFlex buffer. During the find, the local buffer will still contain the values of the last valid record. » In ‘before update’ procedures to access the ‘old’ values as they are reread from disk. » In ’after update’ since any updates to the local buffer at this point will become obsolete. » Dependency procedures.

11.2.9. Other use of the file The above subparagraph lists the required use of the global buffer. buffer However, since Classify will maintain a local buffer in all other situations, you can pretty much use the global file buffer in almost all other cases. Some explicit examples of this are:

(c) '92 - '95 Calvin Consultancy May 1995 Page 11.8 Chapter 11: File handling Classify Handbook The DataFlex file buffer

» the use of the global file buffer in a validation message to check what is the highest customer number used, or check whether a similar name is already entered in the file; » in dependency procedures to retrieve information from a system file; » in an entering procedure to find default information based on another record/file.

In all these cases, you will usually access both the local and the global file buffers. You should take care to not confuse them!

Page 11.9 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 11: File handling Classify Intelliwrites

11.3. Classify Intelliwrites Classify allows you to set up dependencies between files. This means that an update in one file can result in updates in other files. Very often this will be parent files of the file being updated. If no foreign-key change is involved, there is no need to save the parent record both during backout and save procedures. However, if a foreign key is changed, the parent record should be saved both during backout and update.

But in coding generic dependency procedures, we cannot take this in account. That is why we incorporated a system of “lazy writes” in Classify. This system is for the largest part fully transparent to you as a programmer. We have called this system “intelliwrites”.

Once you have activated intelliwrites, all save request for a file will be qeued. So, if you request a pSave_File this will not immediately result in a flush of the buffer to disk. Instead, Classify will add the file to a list of “pending” files. As soon as you cancel the intelliwrites, Classify will go through the list of pending files and save each one of them.

This means that if you first update the parent record using the backout procedure, issue a pSave_Record, update it again in the update procedure and than save it again, this will result in only one actual save to disk.

Now, if the foreign key changed, wouldn’t this fail because finding of the new parent record would “cancel” the data from the backout? No! Classify will automatically check whether intelliwrites are active prior to doing any buffer operations (find or clear), provided you use the file-handler messages (pFind_File, mClear_File) rather than the DataFlex commands, which will bypass any protection we provide.

Since all relate commands are also “intelliwrites aware”, Classify will not issue a second find command if the foreign key field has not changed.

11.3.1. Enabling and disabling The intelliwrites (and TTS-control) are turned on by the following Intelliwrites message:

Syntax: Send mStart_Intelliwrites {To Program_Desktop}

this will automatically do a lock (no reread) and start a new transac- tion. Once you have processed all records, you can turn off the intelliwrites using

Syntax: Get pStop_Intelliwrites {Of Program_Desktop} To ErrorCode

If any error occurs during the save of the pending files, this will be indicated in the errorcode (non zero value). The pStop_Intelliwrites will also perform an unlock and end the transaction.

If an error was detected during the flush of the buffers, a Transaction Skip is issued as well to signal the TTS system the transaction has been corrupted.

11.3.2. Handling errors during Since Classify will perform all validations prior to the actual saves, intelliwrites there should be no errors during a locked save operation. If an error does occur, this will usually be the result of an operating-system problem or a result of internal DataFlex filemanagement.

If such an error occurs, you can issue the transaction skip command to signal the TTS that the transaction has failed.

(c) '92 - '95 Calvin Consultancy May 1995 Page 11.10 Chapter 11: File handling Classify Handbook Classify Intelliwrites

11.3.3. Saving in dependency If a dependency procedure updates another file, this is done through procedures the mUpdate_Field which will take care of the save of that record. However, if a dependency procedure also updates the originating file, you will have to issue a pSave_File message yourself. The intelliwrite system might help you out in case you forget to do this (if the file buffer doesn’t change) so errors might not be immediately visable. But a change in another dependency procedure, or the addition of another dependency to the file might corrupt that.

Also please keep in mind that dependency procedures rely on the global buffers. If you need to change the record in the global buffer, make sure you always reposition it afterwards.

11.3.4. Bypassing Intelliwrites If you want to force a record to save to disk immediately, bypassing the intelliwrite feature, you can send pSave_File Filenum True (standard would be to specify pSave_File Filenum 0). This will tell the pSave_File message to immediately flush the buffer and write therecordtodisk.

11.3.5. Summary Intelliwrites (or lazy writes) can greatly optimize your performance, especially on heavily used networks. Intelliwrites are enabled auto- matically during saves in both batches and views. You can also use intelliwrites in other situations.

The following rules apply when using intelliwrites: » Send mStart_Intelliwrites enables intelliwrites » Get pStop_Intelliwrites To Errorcode disables intelliwrites and returns an errorcode if any of the saves generated an error » Always use file-handler messages (pFind_File, pSave_File, mClear_File, pDelete_File) instead of the DataFlex commands. » Use pSave_File Filenumber 0 to make use of the intelliwrites (if enabled), use pSave_File Filenumber 1 to write through the buffer and bypass the intelliwrites. » Enabling intelliwrites will automatically lock your database and create a new transaction. Disabling them will unlock the data- base and end the transaction. » To flag a transaction as failed while intelliwrites are active, issue the Transaction Skip command.

Page 11.11 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 11: File handling The Classify Save

11.4. The Classify Save Pressing the [Save] key in a view or sending mSave in a batch-report triggers a complex series of events. This appendix goes into the logic of the save operation and tries to give you an overview of the events, the messages involved and the user-hooks provided.

All actual message names are printed in bold. You will also find the pseudo code for several modules attached to this appendix, and again these will have actual message names printed in bold. All other code is pseudo-code and resemblance to existing messages would be purely coincidential.

The actual messages listed in the pseudo code will not necessarily have a full set of arguments. For that, you should check on the appropiate parts of the documentation.

The keyword Perform is used in the pseudo code to indicate the execution of a function or procedure whoms ID is stored in the specified property. If there is a message-augmentation available, it will also perform that message. This can even include performing a message in both subsystem and data dictionary if it is specified in both. So:

Perform pBefore_Save_Msg

Would translate to the actual code:

Local Integer Before_Save_Msg Get pBefore_Save_Msg To Before_Save_Msg Send Before_Save_Msg Send mBefore_Save Get pBefore_Save_Msg Of SBS To Before_Save_Msg Send Before_Save_Msg To SBS Send mBefore_Save To SBS

Unless explicitely specified otherwise, the view and batch-server are assumed to have equivalent functionality, as do subsystem and batch-report. So while all procesess are listed for the data entry modules, they apply as well for the batches.

As soon as the save is initiated, this is first delegated up to view (mSave_All). The view will then prompt the user if he realy wants to save after which the actual save process is initiated (note: the save verification depends on user-settings and is not performed in batches).

First, the message pValidate is sent to the subsystem. Upon receipt, the subsystem will check the user-rights. If these are okay, the subsystem will perform an attach (mAttach) from the parent subsys- tem if it is a nested subsystem and the main file for the subsystem is a child to the main file of the container subsystem.

Next, the subsystem will send pValidate_It to the data dictionary handling the main file for the subsystem. This function will first check the rights of the user and the demo limitations. Next it will perform the ok-to-save checks for both the subsystem and the data dictionary (pOk_To_Save_Check and pOk_To_Save_Check_Func).

If these functions do not produce any errors, the before validation hooks are performed, followed by the actual field validations. If this also produces no errors, Classify will first perform the after validation hooks and than it will check whether the key has changed, which will only produce an error if there are existing child-records.

Finally, it will check whether all files needed for the save (depend- encies) are open. This could be the last cause for errors in the validation.

(c) '92 - '95 Calvin Consultancy May 1995 Page 11.12 Chapter 11: File handling Classify Handbook The Classify Save

If no errors are encountered, the subsystem will broadcast the pValidate to all nested subsystems, which will finally cause a cas- cade of validations to go through all subsystems.

If all validations return a “no error” status, the view will enable intelliwrites (this locks the database) and broadcast the pSave message. Again, this message will perform an attach form the parent subsystem if necessary because the save in the parent subsystem might have changed the key (e.g. during the creation of an invoice, the invoice number will be assigned).

Next it will instruct the data dictionary to perform the actual save.

The data dictionary will check whether it is a new record or an existing record being updates (pUpdate_State). In the case of an update, it will perform a refind of the record.

Warning: from this point on, the use of the global buffer is restricted and you should not attempt any operations without the use of the file-handler functions and you should always correctly reposition the buffer if you do.

After this, the data dictionary will perform the before-save (pBe- fore_Save_Msg and mBefore_Save) user hooks, and again depend- ing on the update state the backout procedures.

Next, it will perform the before update user hooks (pBefore_Up- date_Msg and mBefore_Update) and move all the data from the local buffer to the global buffer.

Important: Up till this point, all changes should be made in the local buffer. From now on, changes in the local buffer will be lost.

After the data is moved, the data dictionary will perform the after update hooks (pAfter_Update_Msg and mAfter_Update) and the update dependencies. If it is a new record, it will also execute the create-dependencies.

After these are performed, the record will be saved. For new records, a save is forced, by-passing the intelliwrites so that the recordnum- ber will be available.

If the save in the data dictionary did not produce any errors, the subsystem will reset the changed-flags to reflect the succesfull save and broadcast the pSave to all other subsystems.

If any subsystem has detected a problem during the save, it will flag the entire transaction as failed. In any case, it will issue a pStop_In- telliwrites, which will cause a flush of all buffers and an unlock of the database (from this point on, the database is no longer locked).

Warning: The following only applies to views, the save process of the batches is finished at this point.

If no errors occur, the view will broadcast a re-display. This will cause the subsystem to perform the after save procedures (pAf- ter_Save_Msg and mAfter_Save; both in SBS and in DDO) and to either clear or re-display the data.

11.4.1. Pseudo code The following pseudo code outlines the save process in the specified parts of the system.

Page 11.13 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 11: File handling The Classify Save

11.4.1.1. View Procedure mSave_All Check_if_user_wants_to_save To Ok If Ok Broadcast Get pValidate To Error If Not Error Send mStart_Intelliwrites // The database is now LOCKed Broadcast Get pSave To Error Get pStop_Intelliwrites // The database is now UNLOCKed If Not Error // This does not apply to the batch server Broadcast Send mRedisplay End End End End_Procedure

11.4.1.2. Subsystem Function pValidate // All data is in the local buffer If Not pChanged_State Broadcast Get pValidate Else Check_User_Rights To Ok If Ok If Subsystem_Is_Nested_And_Displays_Child_File_Info Do_In_Memory_Attach_From_Parent End Get pValidate_It Of DDO_Object To Error If Not Error Broadcast Get pValidate End End End End_Function

Function pSave // All data is in the local buffer If Not pChanged_State Broadcast Get pSave Else If Subsystem_is_Nested_And_Displays_Child_File_Info Do_In_Memory_Attach_From_Parent End Get pSave_It Of DDO_Object To Error // Now the data is in the Global buffer and in the local // Changes in the local buffer made after this point will be lost If Not Error Reset_Changed_Flags Broadcast Get pSave End End End

Procedure mRedisplay Perform pAfter_Save_Msg Clear_Or_Redisplay_Based_On_User_Settings End_Procedure

(c) '92 - '95 Calvin Consultancy May 1995 Page 11.14 Chapter 11: File handling Classify Handbook The Classify Save

11.4.1.3. Data_Dictionary Function pValidate_It Check_User_Rights_And_Demo_Limitations To Ok If Ok Perform pOk_To_Save_Check_Func To Error If Not Error Perform pBefore_Validate_Msg Check_All_Field_Validations To Error If Not Error Perform pAfter_Validate_Msg Check_Key_Change To Error If Not Error Check_For_Open_Files To Error End End End End End_Function

Function pSave_It If pUpdate_State Begin Refind_Record // Now the global buffer contains the “old” values End

Perform pBefore_Save_Msg

If pUpdate_State Begin Do_Backout_Dependencies End

Perform pBefore_Update_Msg Move_Data_From_Local_Buffer_To_Global_Buffer // After this point, all updates to the local buffer will // be lost; it can be used for reference though. Perform pAfter_Update_Msg Do_Update_Dependencies

If Not pUpdate_State Do_Create_Dependencies End

If pUpdate_State Save_Record_Using_Intelliwrites Else Force_Save End

End_Fucntion

Page 11.15 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Chapter 11: File handling The Classify delete

11.5. The Classify delete When pressing the delete key in a subsystem, you start a sequence of events that will result in the deletion of the record currently in the subsystem and possibly of a set of related records. In this paragraph we will outline the events as they take place. The same conventions areusedasinthedescriptionofthesave.

When you hit the delete button, this is handled inside the subsystem. It will check whether it is okay to delete the record by checking the user rights and by prompting the user. After that it will issue the pDelete_It message to the data dictionary.

This message will first check the user rights. Next it will perform the Ok_To_Delete checks. If all this goes well, it will check if all files are open. If that is okay as well, the database is locked (intelliwrites enabled), the before delete (pBefore_Delete_Msg and mBefore_De- lete) and the datadictionary starts to check whether all child records can be deleted as well.

This is done by interrogating the DDO’s for the child files, who might interrogate DDO’s for their child files and so on. If every DDO for a child file has signalled that the delete can take place, Classify will start the actual delete by telling the DDO’s for all child files to delete the child records. Only when all child records are deleted, Classify will delete the main record as well. All DDO’s will follow this pattern, so all deletes take place form the bottom of the tree moving to the top. On every level, the dependency procedures for both backout and delete are executed.

After the delete, the after delete hooks are performed (pAfter_De- lete_Msg and mAfter_Delete).

The delete in the batch report is processed in exactly the same way. A purge in a batch also works the same, except that it will execute the purge-dependencies rather than the backout and delete depend- encies.

11.5.1. Pseudo code The following section lists the pseudo code for a delete operation in Classify.

11.5.2. Subsystem Procedure mRequest_Delete Check_User_Rights If Ok Get pDelete_It Of Data_Dictionary To Error If Not Error Redisplay_all_"older"_subsystems Clear_Subsystem_And_(Grand)_Children End End End_Procedure

11.5.3. Data_Dictionary Function pDelete_It Check_User_Rights If Ok Perform pOk_To_Delete_Check_Func To Ok If Ok Check_Open_Files To Error If Not Error Send mStart_Intelliwrites Reposition record Perform mBefore_Delete Check_If_All_Child_Files_Can_Be_Deleted To Error If Not Error Delete_All_Children Do_Backout_Dependencies Do_Delete_Dependencies Delete_Record Perform mAfter_Delete End Get pStop_Intelliwrites End End End End_Function

(c) '92 - '95 Calvin Consultancy May 1995 Page 11.16 Chapter 11: File handling Classify Handbook File modes

11.6. File modes DataFlex uses a very robust but simple locking mechanism. It basi- cally performs a file lock on all the files open in a program whenever the LOCK command is issued. With the growing size of programs in DataFlex 3.x the chance that files are locked in this process that will never be accessed during that locked is close to 100%.

In DataFlex 2.3 many developers already found that setting the file mode of a file to READ_ONLY would optimize performance. But again, in the complex 3.x programs it is close to impossible for any pro- grammer to do this manually.

However, the Classify data dictionary provides an excellent platform to automate this process. This means that Classify will automatically set all files attached to a data dictionary to read only. Prior to a save or a delete operation, Classify will analyze which files will be effected by this operation and set the file mode for these files to default. Once the operation is completed, the files are set to read only again.

Normally, this process will be totally transparent to the programmer. But if you are doing some special coding (not supported nor encour- aged) you can manually “add” files to the list of files that should be set to default:

Syntax: Send mRequest_Filemode_Dflt {FileNumber}

This message should be send before the intelliwrites are activated. It will include the file specified in the list of files that will be written to. This list is purged at the end of the write operation, so the addition is only temporary.

Page 11.17 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix A: Classify user manual

A. Classify user All Classify programs have a common user interface. This means that you, as an end-user, only have to learn the mechanics of using manual an application once. After that, all other modules and applications developed using Classify will immediately feel familiar to you.

In this chapter, we will try to familiarize you with the general user- interface of Classify programs. We will explain the different elements we have and we will also point out what you can do to customize the program.

(c) '92 - '95 Calvin Consultancy May 1995 Page A.1 Appendix A: Classify user manual Classify Handbook Program activation

A.1. Program activation Once a Classify program gets activated, it will always display a message to signal that the program is being loaded. Once the program is loaded, it will display the main Classify screen (explained in detail later) with a pop-up window asking for your username and password.

Figure 1: The Classify login screen

You may type the username and after you hit , it will display your full name and ask you for your password. As you type in the password, the system will show an “*” rather than the character you typed for enhanced security.

If you want, you can supply the username and password on the command line. Usually, this feature will be set up by a system administrator.

Warning: If you specify a wrong usercode/password combinationthe program will terminate immediately.

A.1.1. The main Classify Classify offers you a CUA-compliant environment. This means that screen you can control the program flow and to a certain extent can work with different tasks at the same time.

If you are used to computer programs that “lead you by the hand”, this will represent a big change and it might take some time for you to get used to it. But on the other hand, it allows you to use your computer much more efficiently and to set it up the way that you work best.

Other programs that provide similar functionality are Windows and Windows based products.

We will discuss the main elements on the Classify screen, along with a set of common user-interface elements such as errors. On the next page you will see a picture of the initial Classify screen as it appears immediately after you have provided your user id and password.

A.1.1.1. Title bar The title bar is the top line of your screen. It displays the full name for the program (middle), date and time (left) and finally the name of the view that is currently active.

Page A.2 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix A: Classify user manual Program activation

A.1.1.2. Action bar This is the main menu for your program. There are three “service” items: » Navigate » Desktop » Help

Title bar Date & time Program title Memory indicator Action bar Main data entry screen Button bar Status line Field description User name Chain depth

Figure 3: The Classify workspace

These options are not only available in every program, but will have exactly the same layout and contents.

The Options pull down is also available in every program, but its contents will differ, not just per program, but even depending on the part of the program you are working with. We will discuss this feature in more detail later.

The other items in this action bar (usually “Functions” and “Reports”) will contain different information per program. Even the total number and names of these application specific choices might differ.

Figure 2: The activated desktop pull down

(c) '92 - '95 Calvin Consultancy May 1995 Page A.3 Appendix A: Classify user manual Classify Handbook Program activation

You can select an item in the action bar by any of the following methods: » Navigate to it using the cursor control keys and press » Press the capitalized letter in the item description and the system will automatically highlight that item, after which you can press » Place the mouse cursor on top of it and press the left mouse button.

You have now activated a pull-down menu. When selected, any item in the action bar will present a pull-down. A choice from a pull-down menu can provoke a certain action, or it can display another menu (a so called “cascading” pull-down). You can distinguish between these two situations because any choice activating a cascade will have a series of dots (...) after it. If only a description is supplied, immediate action will be generated upon selection of the item.

The type of action depends on the pull-down and its contents. For instance the choice “Next record” will cause the system to find the next record in the data entry module you were working with and display that. A choice “Customer info” will probably display a screen with customer information.

Menu items in a pull-down menu can be selected in the same way as menu items in the action bar itself.

If a description in a pull-down list is both a description and a key, this means that you can use that particular key to activate the same function directly, without going through the action bar and pull-down first. However, this key will only work while you are in a general data entry function. Once you are in the action bar or in a pull down, these keys no longer work. If you find you use a particular function very often and there is a key-definition (often referred to as hot-key), it might pay to remember the key-stroke.

Once you are in a data-entry function, you can always switch back to the action bar by pressing [F10], by placing the mouse on the action bar and pressing the left mouse button or by using the [Alt] key together with the key representing the capital letter in the item you want to select (this will select the pull-down as well).

A.1.1.3. Button bar At the bottom of the screen you will see the so called “button bar”. This is a screen area, 3 lines high that lists up to 15 functions. Initially, it is almost empty, but once you start a data entry function, you will see that a number of additional functions appear.

This button bar is “context sensitive”, which means it will display functions that are relevant to the part of the program you are working in. The button bar displays functions and their key-strokes. So it works partly as a “reminder” of the most important key-strokes. But you can also activate any listed function by placing the mouse on the description and pressing the left mouse button.

Depending on the function, it might be “repeatable”, which means that it will repeat the command as long as you keep the mouse button pressed down. An example of this is the “Find next” function.

A.1.1.4. Help Line The last line of the screen is the “help line”. This line displays three items of information: » A context sensitive description of the item the cursor is posi- tioned on » The username of the current user » The chain-depth This figure (located at the right hand corner) indicates the depth of chained programs if the menu structure of your application

Page A.4 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix A: Classify user manual Program activation

requires switching of programs. The chain-depth in Dataflex cannot exceed 16, so this figure will indicate whether you can chain any deeper or not.

(c) '92 - '95 Calvin Consultancy May 1995 Page A.5 Appendix A: Classify user manual Classify Handbook Data entry

A.2. Data entry In Classify most data entry functions will offer the same functionality. Even though special modules might use different techniques or offer special features, the main part of your data entry will have the same interface.

Data entry functions are generally listed in the “Function” pull down. If you select one of the choices listed here, this will cause one or more data entry images to appear. If any other data entry images were active (visible), these will change in color to indicate that they are temporarily unavailable.

Every data entry image is called a “zoom” because it focuses on a part of the data available to you. The combination of all the zooms available through one selection from the function pull down is called a“view”.

If a view offers zooms that display information about multiple files, the zooms will be grouped into subsystems, each subsystem con- taining zooms for one file.

Example: The view “customer information” might contain subsystems for customer, invoices headers, invoice lines and payments. The subsystem for customers could contain zooms for naming information, address, telecommunication details and contact information. The invoice header subsystem might contain only one zoom displaying all the information about the order, while the invoice line subsystem again uses one zoom to display invoice line information. The payments view could contain a zoom containing the most essential information and an additional zoom for information about payment method, booking details etc.

Every subsystem has one zoom that will contain all the information necessary to identify records from the file. For customers, this could be a search code, debtor number, name and city. For invoice headers it would contain the invoice number and date.

This zoom will always be displayed if you select the subsystem it is contained in and is called the “find object” because it allows you to navigate through the file. When you select a view from the function pull down, the find object for the mainfile will be activated.

Figure 4: The option pull down

Page A.6 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix A: Classify user manual Data entry

Along with the find object, other objects might be activated as well. The default list of objects to be activated is automatically set up by the programmer, but you can overrule this list using the user-con- figuration features in the system file maintenance program.

A.2.1. Activation You can activate data entry modules through the “function” pull- down. Once you are in a view, you can activate additional zooms and/or subsystems with related information using the options pull- down. This pull-down will display a list of all available zooms and subsystems. Subsystems are marked by a little square attached to the description.

If you select an already active zoom or subsystem from the option pull-down, the cursor will be moved to the selected zoom (or the find object for the selected subsystem). If the zoom or subsystem is not yet active, it will appear on the screen but the cursor will return to its original location.

You can activate all zooms within a subsystem at once by pressing [Ctrl[A], by using “Activate all” from the options pull down, or, by using “Activate all” from “Window navigation” in the “Navigate” pull down.

A.2.2. Deactivation You can deactivate (remove from the screen) any zoom by pressing the [Esc] (escape) key while in the zoom. If you press the escape key in a find object, this will not only activate that object, but all the objects within that subsystem (and within related subsystems on a lower level). If it is the find object for the main file, it will deactivate all zooms within the view.

An alternative way to deactivate a zoom is by using the zoom-menu. The zoom-menu is a pull-down specific to the zoom. You can activate this by either placing the mouse on the upper-left-hand corner of the zoom and press the left-hand button or by pressing [Alt][F10] while in the object. You will now see an option “Deacti- vate”.

Figure 5: The zoom meu

If you want to deactivate all zooms within a view, you can also press [F3] or choose “Deactivate all” from the zoom-menu.

(c) '92 - '95 Calvin Consultancy May 1995 Page A.7 Appendix A: Classify user manual Classify Handbook Data entry

If you want to deactivate all the zooms within a subsystem that did not activate automatically, you can do that using [Ctrl][N], using the “Deactivate all” from the options pull down, or, by using “Deactivate all” from “Windows navigation” in the “Navigate” pull down.

By using the above methods of deactivation, all non-saved informa- tion in the view (both data entry information and screen-locations) are saved and the view will also stay in the picklist (this will be discussed later). This also means that the view still uses internal memory. If your memory is limited (see the memory status in the title bar), you can reclaim the memory used by the view by deactivating it using [Ctrl][F4] or selecting “Destroy all” from the zoom-menu.

This option will erase all information from the view. If there is data-entry information in the view that has not been saved yet, the program will issue a warning and you can still abort the process.

Warning: Due to the internal workings of Dataflex, you might find that sometimes not all the memory is reclaimed.

A.2.3. Finding records There are five basic operations to navigate through files: » Find next record » Find previous record » Find first record » Find last record » Find first match

The order in which the file is traversed is either set by the program- mer or can be selected by the user. In general, “list” oriented find objects will have a fixed order, as will all nested subsystems. If the find object for the main file in a view is a “form” oriented object (displaying one record at a time), this usually means that you can select the ordering. This is done by moving towards the field within this object that you want to be the sorting field. Now while the cursor is in this field, perform any of the find operations. This will automat- ically select the correct order. As long as you do not perform another find operation while the cursor is on another field in the find object, the order will remain the same.

Figure 6: The main navigation pull down

Page A.8 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix A: Classify user manual Data entry

Figure 7: File manipulation cascade

If you want to “seed” the search for a record, you should enter the available information about the index-fields in that record and then perform a “Find first match”. After that, you can navigate forward and backward using find next and previous.

The file navigation functions can be activated in three ways: » Using function keys ° [F8] Find next record ° [F7] Find previous record ° [Ctrl][Home] Find first record ° [Ctrl][End] Find last record ° [F9] Find first match » Using the appropriate choices in the “File manipulation” cascade of the “Navigate” pull-down » Using the buttons in the button bar

If you have entered information without saving, a warning might be displayed to inform you that this data will be lost and you can abort the find. Whether this happens or not depends on your user configu- ration.

If a view contains multiple subsystems, a find operation on the main file will always result in a find operation in all the subsystems for related files as well (so finding a customer will also result in invoice and payment data being retrieved). If you perform find-operations on related information, only the subsystems containing data related to the subsystem you are finding in will perform find actions (so navigating through invoices will also result in find operations in invoice lines and payment, while navigation through invoice lines will not result in any other finds).

All find operations in related subsystems are constrained so that only information belonging to the already displayed record can be found.

To restart a find, you should clear the subsystem and repeat the above steps. You can clear a subsystem (and all related subsys- tems) by pressing [F5]. After clearing, the cursor will be positioned in the first field of the find object of the cleared subsystem. If you want to clear an entire view, you can do so by pressing [Ctrl][F5].

(c) '92 - '95 Calvin Consultancy May 1995 Page A.9 Appendix A: Classify user manual Classify Handbook Data entry

The cursor will be placed in the first field of the find object of the view.

The functions “Clear” and “Clear all” are also available from the “File manipulation” cascade in the “Navigate” pull down and from the button bar.

Important: You can perform the find operations from any field within a subsystem, even if it is not in the find-object.

A.2.4. Advanced find functions Classify allows you to navigate through complex views displaying many files. Of course, this can be done by placing the cursor in a zoom displaying information from the file you want to navigate in.

However, if you want to perform find operations in other files, Classify also allows two sets of function keys to do so. Using [Shift][F7] and [Shift][F8] will navigate through the main file of the view, [Ctrl][F7] and [Ctrl][F8] will navigate through the parent file.

Example: Suppose you have a view with customer information, orders for the current customer and orderlines for the current order. If you place the cursor in a zoom displaying order line information, [F8] will find the next orderline, [Ctrl][F8] will find the next order and [Shift][F8] will find the next customer.

A.2.5. Editing records If you want to change information, you should first find the appropri- ate record using the method listed in the previous paragraph. Now you can enter the new information by typing it over the existing data. Once you are finished, save the information by: » pressing [F2] or » selecting “Save record” from the “File manipulation” cascade of the “Navigate” pull down or » selecting the “Save” button in the button bar

Once you have indicated that you want to save the record, the system might ask you for a confirmation. Again, this is controlled by your user setup.

It might not be possible to change the “key” value of records. The “key” is the field or combination of fields that uniquely identifies the record to the system (e.g. customer number). This is also the information that is used to link other information to this record (e.g. invoices). As soon as such related information exists, the system will not permit you to change this identifier because this would destroy the link to all additional information. If you try to change this infor- mation while related information exists, the system will issue an error.

If you have selected “Auto clear on modify” in the user configuration, the subsystem will be cleared automatically after the save. If not, the newly saved data will remain on the screen and you can continue to navigate through the file.

A.2.6. Deleting records To delete a record, you have to find the record first. Once the correct record is displayed, you can delete the record by pressing [shift[F2] or by selecting the appropriate action from the “Navigate” pull down or button bar.

Again, a warning might appear, depending on your user-configura- tion.

Warning: The deletion of a record can be a time-consuming task. If you would for instance issue a delete for a customer, this might mean that the system first has to check whether there are any outstanding invoices or orders in process (any of these would

Page A.10 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix A: Classify user manual Data entry

mean it is impossible to delete the customer right now). If all these validations pass, the customer will be deleted together with all invoices, invoice-lines, payments, orders, order-lines and delivery records.

If any of the files related to the record you are trying to delete can not be accessed, permission to delete will be denied. If the cause for a failure to delete is not clear, please contact your system supervisor.

A.2.7. Creating records To create new records, you should first perform an “insert” using the “navigate” pull down, button bar or [Shift][F10]. This will generate a blank subsystem (and also clear all related information). Now you can just enter the new information. If the information is fully entered, save this information as you would do while editing a record.

The save might be automatic after leaving the last field of the last zoom, but this will depend on the setting of the “Auto save” option in your user configuration.

If you have selected “Auto clear on create” in the user configuration, the system will automatically issue a new “Insert” command after the save.

If you are entering information in record-oriented subsystems, you can also start this process by just “clearing” the subsystem. This is done by pressing [F5].

If you have created a “blank” line in a multi-line subsystem and want to undo this (that is: remove the blank line, lose all entered data, and continue editing), you can do this by pressing [Shift][F2].

A.2.8. Changing key values Many times, records are “related” to eachother. Examples of related records are customers and orders, orders and orderlines, invoices and payment. These records are linked by the use of a unique identification in one of the files (the parent). For the relationship between customer and order this could be the Customer-Nr. This field is called the “key” of the customer file. All other informationm is attached to this key and the value of the key is stored not only in the main record (customer), but also in all the related records (orders, invoices).

If you would just change the customer nr for any customer, this would immediately “break” the link between this customer and all his related information. This is why Classify will check whether there are related records whenever you try to change a record. If related information exists, Classify will generate an error.

If you nevertheless want to change this value, Classify will let you do this by finding the original record (just like changing), entering the new value and than pressing [Ctrl][F2].

This will instruct Classify to change the key value not only in the main record but also in all the related records. Because this is potentially a very time-consuming process, Classify will ask you for an extra confirmation before starting this process.

Warning: During this process all other save operations on the database will be postponed. This can result in a temporary hold at other workstations.

A.2.9. Copying ranges of If you want to copy a record, you can make use of the retain-func- information tions. However, you can also use the copy-function built into Class- ify. The copy function requires you to find the record you want to

(c) '92 - '95 Calvin Consultancy May 1995 Page A.11 Appendix A: Classify user manual Classify Handbook Data entry

copy. Next, you must specify the new key value (and only the key value) and press [Alt][F2]. This will generate a prompt that asks you whether you want to proceed with this operation.

If you answer “Yes”, Classify will copy the main record plus all related information.

Warning: Druing this process all other save operations on the database will be postponed. This can result in a temporary hold at other workstations.

A.2.10. Support functions There are several functions to assist you during data entry, which will be discussed in the upcoming paragraphs.

A.2.10.1. Prompt A prompt is a list that can be activated by pressing the [F4] key, by selecting “Prompt” from the button bar or by selecting “Prompt” in the “Navigate” pull down.

Prompts can be divided into two groups: » Selection of a record » Selection of a valid value

The first group is a list of records in the file and you can make a selection from this list. This is an alternate way of finding a record.

Figure 8: The popup to select a record

These prompt lists can be seeded by entering some data before activating the prompt. For instance, if you want the record for “Smith”, you might start off by typing “SM”. This will start the list with “Small”.

Every field that is part of an index will have a prompt list attached to it.

The second group is used if the value that can be entered in a field is validated based on a limited set of choices. Some examples of this might be customer status (E=end user, D=dealer, W=Whole sale), state, or, customer-id in an invoice header.

Page A.12 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix A: Classify user manual Data entry

Every field that is validated based on a list will also have a prompt list attached that displays the valid choices. This can either be a (relatively) short list retrieved from the system information (customer status and state) or it might be a list displaying related information (customer). In the latter case, the list used is identical to the list used to select a customer record. This also means that you can seed this list. So to attach an invoice to “Smith”, I can type “SM”, activate the prompt and select “Smith”.

Figure 9: The popup to select a valid choice

If a field has both a validation and an index, the prompt function will activate the list with valid values. To activate the list to select a record, you can press [Shift][F4].

The contents of the lists displaying (related) records is set by the programmer. However, you can make modifications to this at run- time. Suppose the list for Customer in the above example displays name and city. But to find the correct Smith in New York, you also need the address.

You can now go to the address field for customer (in any zoom in any view) and press [Ctrl][L]. This will add the address to the prompt list. To remove city, you could move to city and press [Ctrl][L] there.

So [Ctrl][L] will toggle the presence of a field in the prompt-list.

The addition of a field will affect all the prompt lists for that file. So in the above example, address will also be displayed for the list with valid customer in the invoice-header.

You can navigate through a prompt list using the arrow keys (the file-lists will also scroll horizontally if the information displayed will not fit on the screen.

Once you have highlighted the item of your choice, press [Enter], [F2], or, choose “Select” from the button bar. If you decide you don’t want to make a selection after all, press [Esc] or choose “Cancel” from the button bar.

(c) '92 - '95 Calvin Consultancy May 1995 Page A.13 Appendix A: Classify user manual Classify Handbook Data entry

If you have selected the “Auto prompt” feature in your user configu- ration, a popup list will display automatically on every blank field that has a prompt attached to it.

A.2.10.2. Zoom Another standard feature of CUA programs is zooming. This means that with a single key-stroke, you can request more information about the current field.

This information can be requested using the [Alt][F9] key. However, the availability of this functionality depends largely on your specific application. Classify provides only one standard zoom function: explode a text-window to full screen.

Whenever you are in a text field, you can press [Alt][F9] to increase the size of the editor to almost full screen. You can collapse the editor by pressing [Alt][F9] or by navigating out of the field. You can still navigate through the records even if the text field is displayed “full screen”.

A.2.10.3. Toggle retain Classify allows the programmer to set up certain fields in a data entry screen so that their value will be retained after a clear command. This can dramatically reduce the amount of typing if a lot of similar information is entered.

Example: If you have many customers in the same city, the retain option on the city would mean that as long as the next customer you need to enter lives in the same city, you don’t need to re-type the city name.

While the programmer can set the initial retain state of a field, Classify allows you to change the retain state of any field at runtime by going to that field and pressing [Ctrl][].

Example: Suppose you now need to enter ten different branches of the same company in different cities. You go to the “name” field and press [Ctrl][R], go to city and also press [Ctrl][R]. This means that after a clear, the name will be retained while the city will be cleared.

Hint: The retain feature not only works on newly created records, but on any clear command. So suppose you need to enter yet another branch of an already existing company, you can find the information about the existing branches, select retain for the fields that are the same and then press clear.

Figure 10: The miscellaneous funtions cascade

Page A.14 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix A: Classify user manual Data entry

This way of working allows you to use existing information as a template for a new record, thus reducing the amount of work and the chance of errors.

Toggle retain is also available from the “Misc. functions” cascade of the navigation pull-down.

A.2.10.4. Retain all Retain all is a fast way to retain all fields in a subsystem. This includes even the fields that are not visible. You can activate retain all by [Ctrl][C] (for Copy), or through the navigation pull down.

Warning: If you select retain all, we strongly suggest that you turn off retain for one field using [Ctrl][R] afterwards, since it will otherwise be impossible to (visually) tell whether you have cleared the screen or not.

A.2.10.5. Retain none This function will deselect all retain options, except those set as a default by the programmer. It can be activated through the navigate pull down or by pressing [Ctrl][X].

A.2.10.6. Picklist (Viewlist) We already discussed several ways to activate and deactivate views. The main distinction between the ways to deactivate a view lies in the handling of non-saved information. We saw that [Esc] and [F3] would keep this information, while [Ctrl][F4] totally destroys this data.

Figure 11: The picklist

The picklist (available from the navigation pull down or by pressing [Ctrl][V]) will present you a list with all views still containing informa- tion. This includes both the “visible views” and the views that have been deactivated, but are still present in internal memory. By select- ing one of the views listed here, that view will be activated and placed “on top”. The cursor will be positioned on the first item of the first zoom within this view.

A.2.10.7. Version information If you ever need to call customer support with a specific problem, you can activate a special screen displaying all the version informa- tion about the current module. The information displayed here is very important for the customer support staff.

(c) '92 - '95 Calvin Consultancy May 1995 Page A.15 Appendix A: Classify user manual Classify Handbook Data entry

To activate this window, you must press [Ctrl][F1].

Page A.16 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix A: Classify user manual Errors & Warnings

A.3. Errors & Warnings During program execution, Classify might display errors or warn- ings. Both look similar, but might differ in color, depending on your user setup. Another difference between errors and warning is that an error will give you only one option: , Warnings might offer you more alternatives.

The popup will remain on the screen until you select one of the available options. If you feel the information provided is too limited, you can access the help system through the button.

While an error is visible, no other part of the screen is accessible, and none of the function keys will work.

A.3.1. Errors There are two types of errors: fatal and non fatal errors. Again, these look different but will probably be displayed in different colors, but this depends on your user setup.

Figure 12: A non-fatal error

If a fatal error occurs, the program will abort immediately after the error is confirmed. In case of an ordinary error, program execution will continue.

Errors can be logged in a file (depending on the system settings). In general, only a small number of errors will be logged. You can view the log file using one of the functions in the desktop pull down.

A.3.2. Warnings A warning can offer you several choices. There are three possibili- ties: » Standard warning ° OK » Warning with backout ° OK ° Cancel » Question ° Yes ° No ° Cancel

(c) '92 - '95 Calvin Consultancy May 1995 Page A.17 Appendix A: Classify user manual Classify Handbook Errors & Warnings

The standard warning is used to provide you with information only. The warning with a backout option allows you to “step back” and abort whatever command/action that triggered the warning.

Figure 13: A popup displaying a warning

Hint: If you call for support, or need to memorize the error, note the code on the right (e.g. HDS1 5) rather than the text. The support representative can immediately find the corresponding text.

Page A.18 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix A: Classify user manual Help system

A.4. Help system Classify features an extensive help system. You can activate the help system by pressing [F1], selecting “Help” from the button bar or through the “Help” pull down.

The information in the help system is contained in several area’s. Help is available about » files & fields » zooms » subsystems » views » batches » programs » errors » user interface » key words

If you activate the help system, a new panel will appear. This disables all other screen areas. The help-screen features four major areas:

The most important area is the part where the actual help is dis- played. You can use the cursor keys to navigate through this area. If the information displayed is only a part of the full text, this will be indicated by the arrow on the scroll bar.

Figure 14: The Classify help system

The list on the left shows the help-topics. This list comes in several levels. The top level will display the main help topics. Once you select a topic, the subjects within these topics are listed. For some subjects, there will be sub-categories (like fields per file). The header will always display the topic or subject which has been selected.

Selection of topics is done by means of “pointing” at the topic you want information on. If you want to go down one level, press [Enter]. To move up again, use the [Esc] key.

If there are any cross-references available, they will be displayed in the “See also” list and you can select them by moving the cursor to the list and pressing [Enter] or by clicking the mouse pointer on them.

(c) '92 - '95 Calvin Consultancy May 1995 Page A.19 Appendix A: Classify user manual Classify Handbook Help system

Finally, you can retrieve information about the current item by selecting one of the topics in the right-most column.

If the help system is activated using the [F1] key, it will start by displaying information on the field the cursor was positioned on. If it is activated from the error popup, it will display additional information about the error (if available).

Page A.20 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix A: Classify user manual Desktop features

A.5. Desktop features Every Classify program has a pull down menu called “Desktop”. This pull-down features a number of general services that can be ac- cessed from any part of the program (except for the pop-ups). This section will discuss these features.

Figure 15: The Classify desktop pull down

A.5.1. Calculator The calculator allows you to perform simple arithmetic without exit- ing the program. It features all the basic calculations and can be operated using keyboard or mouse.

A.5.2. Calendar The calendar lists all days in a month, while allowing you to browse through the dates by month and/or year. It will also display the week numbers.

A.5.3. Logfile This feature allows you to browse through the errorlog. Only the errors that are marked by the system supervisor will appear in this log. You can navigate through the log using the error keys, but you cannot edit it.

A.5.4. Login The feature allows you to change your user-identification. This will update the user-configuration (e.g. button bar on/off) and access rights.

A.5.5. Password The option will allow you to change the password. It will first ask for the old password. If this is correct, it will ask for a new one, which needs to be entered twice for validation.

A.5.6. Save Windows This option will save the location of all the active zooms in a file and will restore the zooms to the same location whenever you activate the view again.

The location is dependent on the view the zoom is in and the user-name. So locations can be set based on personal preference, screen size, and your way of working.

(c) '92 - '95 Calvin Consultancy May 1995 Page A.21 Appendix A: Classify user manual Classify Handbook Desktop features

A.5.7. Editor Classify offers you a small editor for personal use. It can edit any ASCII type file. This function is merely provided to allow you to edit small files, keep notes or edit system files. It is not designed to be a full word processor.

A.5.8. Externals The last option in the desktop pull down offers you a list of other programs and modules that are accessible to you.

The contents of this list can be altered through the system configu- ration program and will depend on your own application. Typical entries in this list would be: » Other modules in the system » Word processor » Dos shell » Configuration program » Report Writer

Depending on the configuration as set up in the system file, an external can be started as a temporary job or as the next task. In the first case, leaving the program or application started through exter- nals, you will return to the “old” program, displaying the same (unsaved) information as when you left it. In the latter case, you will actually leave the current program and start another. This means that any non-saved data will be lost. Therefore, Classify will verify whether you really want to exit this program.

Page A.22 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix A: Classify user manual Batches

A.6. Batches Batches are usually listed in the “Report” pull down. These can be activated by selecting the appropriate choice in this pull-down. Whether a batch requires (initial) user input and if so, what type of input depends on the particular batch, so there is no general descrip- tion of batches.

(c) '92 - '95 Calvin Consultancy May 1995 Page A.23 Appendix A: Classify user manual Classify Handbook Exiting the program

A.7. Exiting the program Classify offers you multiple ways to exit a program: » by selecting another programs from one of the menu’s or from the externals list; » by pressing [Alt][F4]; » by pressing [Esc] while in the action bar; » by selecting “Exit” from the first pull down.

Whichever way you use, Classify will always verify whether you are sure you want to exit the program. Once you have confirmed this, Classify will start to verify whether the modules in use allow this. If Classify finds any unsaved information in a particular view, it will display that view and ask you whether it is okay to loose the data or changes you’ve made. At that point, you can abort the process and stay in the program (to perform a save), or, say ‘Yes’ and leave while loosing unsaved changes to that record.

Another reason could be that one of the views has a programmers validation that will not allow you to exit the program. In that case, a special warning or message will probably be displayed but this is dependant on the particular program.

Page A.24 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix B: Enhancing and modifying Classify

B. Enhancing and Classify is a set of classes. This does not mean that they should fit your specific needs for 100%. This also means that there will be modifying times where you either want to expand Classify or you might want to modify default Classify behavior. This is easier than most people think. Classify is written in DataFlex and is compatible with all the Classify available classes an messages. So to do something extra, you can pick your tools from the combined DataFlex base classes, Data Access packages and Classify.

In this appendix we have a couple of very common tips and tricks to enhance or modify Classify. We also publish several techniques in the Calvin Clues, a newsletter for our customers. You will find a seperate section with back-issues of the Calvin Clues in your man- ual. You can also store new issues there for easy reference.

Finally, there are a lot of technical discussions in the Classify section of the Data Access forum on CompuServe. You will also find some uploads there by both Calvin Consultancy and other users. We encourage users to share general solutions and some users have actually handed back enhancements for inclusion in the next re- lease.

The package SPEC_ML.PKG contains a very nice example of a Classify extension. This package contains a subclass of an “older” class for multi line entry, but adds the capability of suppressing duplicate lines. This class was created upon a request by one of our customers but was built without any changes in Classify.

(c) '92 - '95 Calvin Consultancy May 1995 Page B.1 Appendix B: Enhancing and modifying Classify Classify Handbook Picking the correct package

B.1. Picking the correct While using Classify, you can place USE CLASSIFY in the first line of your program and this will include most of the packages in your package program. This will support all the classes for both data entry and batches. However, this might mean that a lot of classes are included while they or not actually used.

Therefore we have created a set of class-collections that you can use:

MINDESK.PKG This file contains only the minimal desktop. It is idealy suited for use with custom-made classes or maybe with the batch-classes if you want to make a program containing only a batch that starts automat- ically. See also the paragraph “Using the minimal desktop” in this appendix.

CDESKTOP.PKG This file contains the necessary classes for the base desktop with action bar. It can be used with custom-build classes.

CLASS_DE.PKG This package contains the packages needed for data entry. It in- cludes the desktop, data dictionary and the main data entry classes. In the chapter about data entry, it will be mentioned in the summary if a class is not included in the standard package. This is the best package to use if your program only contains data entry views.

CLASS_BT.PKG This package contains the classes for the full desktop, the data dictionary and batches. It is the best package to use if your program only contains batches.

CLASSIFY.PKG This class contains both the classes from CLASS_DE and CLASS_BT.It is the best choice for mixed programs but uses the most resources.

Page B.2 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix B: Enhancing and modifying Classify Compiling a "limited" version

B.2. Compiling a Classify offers a “framework” for your application. This means it not just offers a set of classes, but it also offers a large number of "limited" version “integrated” services. Naturally, these services require both runtime and compilation resources.

To allow you to exclude services you don’t want, we have created a set of compiler directives. With these directives you can specify which services you want and which service you want to eliminate.

We have decided to do this using compiler directives rather than by creating new (subclasses) because of the number of variations. If we offer say 5 services in the desktop, we would need to supply 32 classes to offer all combinations. This would be enhanced by the fact that the classes requesting these services should be modified as well, which would result in even more classes.

All compiler directives are placed in the file USAGE.INC and have the following format:

Syntax: #REPLACE USE$SERVICENAME YES|NO

By setting them to YES, the option will be included. By setting the option to NO, the option will be removed. Currently, we support the following compiler directives: » USE$CALENDAR Classify will also automatically ignore the service request for a calendar from the desktop menu, but we suggest you change the menu file to omit this choice. » USE$CALCULATOR Classify will also automatically ignore the service request for a calculator from the desktop menu, but we suggest you change the menu file to omit this choice. » USE$EDITOR This only applies to the file editor as available form the desktop pulldown. Classify will also automatically ignore the service re- quest for an editor from the desktop menu, but we suggest you changethemenufiletoomitthischoice. » USE$EXTERNALS Classify will also automatically ignore the service request for externals from the desktop menu, but we suggest you change the menu file to omit this choice. » USE$ABOUT Classify will also automatically ignore the service request for the about image from the help menu, but we suggest you change the menu file to omit this choice. » USE$VERSIONINFO This will exclude the Ctrl-F1 activated version popup from the desktop. The function key will also be disabled. » USE$DRAGGER$SYSBUTTON If you exclude this service, dragging of objects will be impossible. It will also become impossible to activate the object pull down by either Alt-F10 or by clicking the mouse in the top of an object. » USE$NAVIGATE$PULLDOWN If you exclude this service, no navigation pull down will be created. To reflect the change in the image, you should also update the MIDACT.PKG file to have one set of underscores less. » USE$DESKTOP$PULLDOWN If you exclude this service, no desktop pull down will be created. To reflect the change in the image, you should also update the MIDACT.PKG file to have one set of underscores less. » USE$LOG If you enable this option, Classify will look at the INI file to determine whether logging should be enabled. If disabled, log- ging will not be used.

(c) '92 - '95 Calvin Consultancy May 1995 Page B.3 Appendix B: Enhancing and modifying Classify Classify Handbook Compiling a "limited" version

» USE$SCRIPT If this option is enabled, Classify provides functionality to record and playback keystrokes. See the appropiate appendix for more information. » USE$PICKLIST You can disable the Classify picklist using this compiler switch. » USE$VIEW$NAVIGATOR Classify offers a view-navigator that allows the user to navigate quickly to any zoom inside a view. You can disable this function using this switch. » USE$LINKED$LIST If you set this switch to “OFF”, you will disable the Classify linked list support. » USE$ENHANCED$CHECKING Classify will at certain places in the code check for runtime errors where these usually can not occur in a tested program. Examples of this are checking for array dimensions and the presence of data dictionaries for subsystems. Once you have confirmed the proper working of your program, you can disable the enhanced checking for improved runtime performance. » USE$USER$RIGHTS This option can disable the user right verification used in Class- ify. » USE$USER$ZOOM You can disable user-specific zoom configuration (location, auto- activate) using this switch. » USE$USER$CONFIGURATION This switch disables the user configuration (colors. buttonbar and such). » USE$RECORD$INFORMATION If you are not using the general text zoom to specify text com- ments, you can disable the support for that using this switch. Please note that this should be a system wide setting, not a program by program setting. » USE$DDO$INI This switch can be used to disable the interpretation of the runtime DDO configuration. » USE$DEMO$LIMIT This option disables the demolimitation checking » USE$EXPRESSION$HANDLER Classify has an extended expressionhanler that allows you to write custom functions and use these in expressions. These custom functions should be named “p#?????????”. The use of this extended expression handler does require addi- tional code and processing time which can be avoided using this switch

In the usage include file, you also find the ID‘s for the menu’s. By changing these, you can store different desktop pull down descrip- tions in your HDSMEN file to reflect in- or exclusion of certain services.

Page B.4 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix B: Enhancing and modifying Classify Adding your own services

B.3. Adding your own In the menu file (HDSMEN) you can specify the contents of your own menu’s. One of the types of actions you can specify in the menufile services is “service request”. Classify provides a number of standard service requests. However, it is quite easy to add your own services to this list.

All you have to do is to follow the following steps: » Create a subclass of the cDesktop class » Augment the procedure mRequest_Service to trap the service request and check for your specific service. » Add your service request to the normal table using SystemA (Table ID: HDS20004). » Put the service request in the menu file. » Base the desktop object in your programs on your own desktop class.

Example: Class c My_Desktop is a cDesktop

Procedure Construct_Object Integer Object Forward_Send Construct_Object Image End_Procedure

Procedure mRequest_Service String Service_Type If_Service_Type Eq “0" ; Send mMy_Message Else ; Forward Send mRequest_Service Service_Type End_Procedure End_Class

(c) '92 - '95 Calvin Consultancy May 1995 Page B.5 Appendix B: Enhancing and modifying Classify Classify Handbook Using the minimal desktop

B.4. Using the minimal All Classify programs are encapsulated in a desktop object. The standard class for this desktop is cDesktop and contains (among desktop others) an actionbar. This means that when you activate the pro- gram, it will display an action bar and require the user to start the modules present in the program.

However, sometimes you might want to automatically start one (or more) modules automatically and terminate the program as soon as they are done.

The cMinimal_Desktop class provides just this functionality. It allows you to build programs just like you would using the standard desktop. But unlike the cDesktop class, it will not display an action bar but send the message mStart to all its children.

This message is respected by both batch servers and views. For batch servers, it will result in the batch to be started. Views will just activate.

Every module that has been completed (e.g. a view being deacti- vated or a batch that has finished) will notify the desktop by sending the message mModule_Ready. As soon as all modules have fin- ished their actions, the desktop itself will deactivate and the program will finish.

This allows you to create stand-alone FLX files containing a minimal desktop and one or more batches. These programs can then be started by the externals function or menu options.

Page B.6 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix B: Enhancing and modifying Classify Changing the actionbar

B.5. Changing the action- Many people have requested us for a more detailed description of the steps involved in changing the default Classify action bar. To bar illustrate this, I have used an action bar as provided by on of our users.

File menu &Save Record F2 &Delete Record Shift+F2 &Reports... &Print Screen &Validate Data File &FlexQL df&Query r&Un a DataFlex Program &Operating System Shell &Email &Notepad &Calendar e&Xit Alt+F4 Edit Menu &Clear / Add F5 clear &All Ctrl+F5 &Prompt F4 &Zoom Alt+F9 &Delete line del to &Field end Ctrl+BkSpc &Read in &Write out cu&T &Copy &Paste column &Mode start &Blocking &End blocking Search menu &Find F9 firs&T Ctrl+Home &Previous F7 &Next F8 &Last Ctrl+End superfind f&Ind Shift+F9 superfind pre&Vious Shift+F7 superfind ne&Xt Shift+F8 text &Search text &Replace Navigate &Previous view Ctrl+F6 &Next view Alt+F6 previous &Area Shift+F6 next a&Rea F6 previous &Item Shift+Tab next i&Tem Tab &Begin text Ctrl+Home &End text Ctrl+End begin &Line / field Home en&D line / field End &Goto line Options &System parameters" &Program parameters" set &Active BS" select a &BS" select &Language" Maintenance Views Varies by program Inquiry Views Varies by program View-Options Original options pull down Help As standard

I have made two slight alternation to his requested action bar. The first one is the addition of the View-Options. Without that, we would also need to provide an alternate means of displaying those, which would confuse two topics. The second one is the devision of VIEW in Maintenance views and Inquiry views. This is done to illustrate the use of multiple view pull-downs.

The first step is to copy all the files needed into our users directory. These files are: » \DATA\HDSMEN.* » \PKG\USAGE.INC » \PKG\MIDACT.PKG » \PKG\LEFTACT.PKG » \PKG\RIGHTACT.PKG » \IMG\MIDACT.IMG

(c) '92 - '95 Calvin Consultancy May 1995 Page B.7 Appendix B: Enhancing and modifying Classify Classify Handbook Changing the actionbar

» \IMG\LEFTACT.IMG » \IMG\RIGHTACT.IMG » \IMG\STRING.INC

From the above package names, you might already gather that we have split the action bar into three sections. This is done to facilitate easier extension of the initial two items (Functions and Reports) to allow more flexable menu’s there, and to be able to resize the menu for different screen widths.

The right action bar actually only includes the help pull down, but we will use this one for some explanations. Here is the code from that file:

Class cRight_action_bar Is A cPartial_action_bar

Procedure Construct_object Integer Image Forward Send Construct_object Image Use_Extend Cascade0.Img

Object oHelp_pd is a cVariable_pull_down Cascade_0 Set pID To @HELP_PD_ID End_object // oHelp_pd

Item_list On_item @Help Send Activate_pull_down To (oHelp_pd(Current_object)) End_item_list

End_procedure // Construct_object

End_class // cRight_action_bar

As you can see, we create the object for one pull down. We set the pID to @HELP_PD_ID. This is a constant that is specified in USAGE.INC as HELP_PD. This pID is used to link the contents of this pull down to the HDSMEN file. If you look in SYSTEM, menu & buttons, you will find the menu-id HELP_PD and find the choices for this pull down. We will go over the menu file in detail later.

You could use

Set pID To “HELP_PD”

as well, but we have a policy not to include constant texts directly into the source code. Hence the indirection. The same applies to the @HELP reference in the item list. Since this is language dependant, we have put this in STRING.INC. Just look in there and you will find the substitution to “Help”.

Of course, again you could just put in the following code if you don’t mind coding language specific things:

On_Item “Help” Send Activate_Pull_Down To (oHelp_Pd(Current_Object))

So far the basic explanation of this package. Now if you take a look at the MIDACT.PKG file, you will immediately recognize the same structure. As you might see, there are two compiler directives that canbesetinUSAGE.INC to simple exclude the navigation pull down and/or the desktop pulldown. I have included the code without the compiler directives.

Page B.8 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix B: Enhancing and modifying Classify Changing the actionbar

Class cMiddle_action_bar Is A cPartial_action_bar

Procedure Construct_object Integer Image Forward Send Construct_object Image

Use_Extend Cascade0.Img Use_Extend Cascade1.Img

Object oStd_Navigation_PD is a cVariable_pull_down Cascade_0 Set pID To @NAVIGATE_PD_ID

Object oWindow_Navigation is a cVariable_pull_down Cascade_1 Set pID To @WINDOW_CASCADE_ID End_Object

Object oEdit_Functions is a cVariable_pull_down Cascade_1 Set pID To @EDIT_CASCADE_ID End_Object

Object oRecord_Functions is a cVariable_pull_down Cascade_1 Set pID To @FILE_CASCADE_ID End_Object

Object oMisc_Functions is a cVariable_pull_down Cascade_1 Set pID To @MISC_CASCADE_ID End_Object End_Object

Object oOption_pd_default is a cOption_pull_down Cascade_0 Set pID To @DEFAULT_OPTION_PD_ID End_object // oOption_pd_default

Object oDesktop_pd is a cVariable_pull_down Cascade_0 Set pID To @DESKTOP_PD_ID End_object // oDesktop_pd

Item_list On_item @Navigate Send Activate_pull_down To (oStd_Navigation_pd(Current_object)) On_item @Options Send Activate_pull_down To (oOption_pd_default(Current_object)) On_item @Desktop Send Activate_pull_down To (oDesktop_pd(Current_object)) End_item_list End_procedure // Construct_object

Procedure mAdjust_navigation_pull_down String Class_type Broadcast Send mUpdate_Shadow Class_Type End_procedure // mAdjust_navigation_pull_down

End_class // cLeft_action_bar

We will discard the mAdjust_Navigation_Pull_Down message be- cause it is not important for the modification of menu’s.

You will see the same structure, with the added complexity of cascading pull downs in the Navigate pull down. As you can see, it is just another level of object definitions and the inclusion of an extra image (CASCADE1)

The original idea behind creating a left and a middle action bar was to allow us to have the “fixed” menu choices in the middle action bar and to be able to add as many “program specific” menu choices as we needed in the left pull down. Since we will tailor this menu anyway, we will just delete the Navigation and the desktop pull down. This will result in the following:

Class cMiddle_action_bar Is A cPartial_action_bar

Procedure Construct_object Integer Image Forward Send Construct_object Image

Use_Extend Cascade0.Img

Object oOption_pd_default is a cOption_pull_down Cascade_0 Set pID To @DEFAULT_OPTION_PD_ID End_object // oOption_pd_default

Item_list On_item @Options Send Activate_pull_down To (oOption_pd_default(Current_object)) End_item_list End_procedure // Construct_object

Procedure mAdjust_navigation_pull_down String Class_type Broadcast Send mUpdate_Shadow Class_Type End_procedure // mAdjust_navigation_pull_down

End_class // cLeft_action_bar

We also need to adjust the image, which is in MIDACT.IMG.Yousee there arethree sets of underscores there. Just delete two of them!

(c) '92 - '95 Calvin Consultancy May 1995 Page B.9 Appendix B: Enhancing and modifying Classify Classify Handbook Changing the actionbar

Nowwemovetotheleft action bar. If we go back to the original example, we see we need seven pull downs: » File menu » Edit Menu » Search menu » Navigate » Options » Maintenance Views » Inquiry Views

None of the “fixed” ones have cascades. We don’t have to worry about the cascades for Maintenance Views and Inquiry Views.

The LEFTACT.PKG currently looks like this:

Class cLeft_action_bar Is A cPartial_action_bar

Procedure Construct_object Integer Image Forward Send Construct_object Image

Use_Extend Cascade0.Img

Object oFunction_pd Is A cVariable_pull_down Cascade_0 Set pID To @FUNCTION_PD_ID End_object // oFunction_pd

Object oReport_pd is a cVariable_pull_down Cascade_0 Set pID To @REPORT_PD_ID End_object // oReport_pd

Item_list On_item @Functions Send Activate_pull_down To (oFunction_pd(Current_object)) On_item @Reports Send Activate_pull_down To (oReport_pd(Current_object)) End_item_list End_procedure // Construct_object

End_class // cLeft_action_bar

We need to extend that, and will use the constants directly for ease of example.

Page B.10 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix B: Enhancing and modifying Classify Changing the actionbar

Class cLeft_action_bar Is A cPartial_action_bar

Procedure Construct_object Integer Image Forward Send Construct_object Image

Use_Extend Cascade0.Img

Object oFile_pd Is A cVariable_pull_down Cascade_0 Set pID To “FILE_PD” End_object // oFunction_pd

Object oEdit_pd is a cVariable_pull_down Cascade_0 Set pID To “EDIT_PD” End_object // oReport_pd

Object oSearch_pd is a cVariable_pull_down Cascade_0 Set pID To “SEARCHPD” End_object // oReport_pd

Object oNavigate_pd is a cVariable_pull_down Cascade_0 Set pID To “NAV_PD” End_object // oReport_pd

Object oOption_pd is a cVariable_pull_down Cascade_0 Set pID To “OPTIOM_PD” End_object // oReport_pd

Object oMaintenance_pd is a cVariable_pull_down Cascade_0 Set pID To “MAINT_ID” End_object // oReport_pd

Object oInquiry_pd is a cVariable_pull_down Cascade_0 Set pID To “INQ_ID” End_object // oReport_pd

Item_list On_item “File” Send Activate_pull_down To ; (oFile_pd(Current_object)) On_item “Edit” Send Activate_pull_down To ; (oEdit_pd(Current_object)) On_item “Search” Send Activate_pull_down To ; (oSearch_pd(Current_object)) On_item “Navigate” Send Activate_pull_down To ; (oNavigate_pd(Current_object)) On_item “Options” Send Activate_pull_down To ; (oOption_pd(Current_object)) On_item “Maintenance” Send Activate_pull_down To ; (oMaintenance_pd(Current_object)) On_item “Inquiry” Send Activate_pu ll_down To ; (oInquiry_pd(Current_object))

End_procedure // Construct_object

End_class // cLeft_action_bar

And we need to change the image (LEFTACT.IMG).

Okay, now we have created the action bar and pull downs, but we still need to put something in them. This is done through the HDSMEN file, which can be specified in SYSTEM.

The need to specify the menu id, the menu entry number (anything above 90 is just appended at the end) and the description. Next you need to specify what sort of entry this menu item is (TYPE). If you press prompt (F4) you will see the available choices: » Cascade Not used in this example » Draw line Used to seperate blocks, as seen in the FILE pull down between Delete record and Reports » External application Can be chain, chain wait or run program, for instance Reports and FlexQL. » Message Not used from menu file » None Just display the description, do nothing » Service Request One of a set of services offered by the desktop such as Calendar, error view and help; can be extended » Emulate Key stroke Specify the key which behaviour you want to mimic.

(c) '92 - '95 Calvin Consultancy May 1995 Page B.11 Appendix B: Enhancing and modifying Classify Classify Handbook Changing the actionbar

In “Command” you can specify the command, cascade pull down ID or key name. In the STATUS field, you can specify things like single or double line and the type of service request.

Going through the example: » &Save Record: F2 Emulate Key » &Delete Record: Shift+F2 Emulate Key » Blank: Draw line » &Reports...: External Program » &Print Screen: Emulate Key » &Validate Data File: Emulate Key (or Service?) » Blank: Draw line » &FlexQL: External Program » df&Query: External Program » r&Un a DataFlex Program: NEW Service » &Operating System Shell: External Program » Blank: Draw line » &Email: External Program (or service) » &Notepad: Service » &Calendar: Service » Blank: Draw Line » e&Xit: Alt+F4 Emulate Key

The other pull downs can be specified in the same way. We appar- ently need to create a new service (maybe more). How to do this is specified in the manual and falls a bit outside of the scope of this message.

Now what is left is to tell views to show up in either the pull down Maintenance Views or Inquiry Views.Thisisdonebysetting pPull_Down_Number (which is a property of View, Batch_Server, View_Group and Batch_Group) to either 5 or 6, depending on the one we want to use (pull down items start counting at 0). Of course you can use constants as we do (see CONSTANT.INC).

This lists all the steps you need to do, to create a special pull down menu, except for the recompile. Remember that this is just one of the many examples of how you can tailor Classify to your needs and preferences.

Page B.12 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix C: Introduction to Object Oriented Concepts

C. Introduction to Switching from procedural programming to object oriented program- ming takes more than just learning a couple of new commands. In Object Oriented order to make optimal use of the advantages of object oriented programming, it is necessary to adapt your way of thinking to the Concepts object oriented way of approaching a problem.

Although object orientation should be more natural to you than procedural programming, most developers show a ‘professional deformation’ that makes it hard for them to approach any subject which needs their professional attention in an object oriented man- ner.

However, for most other other subjects, you will find you are already thinking object oriented. In the upcoming paragraphs I will try to illustrate this and I will also cover some of the base concepts of object orientation.

(c) '92 - '95 Calvin Consultancy April 1995 Page C.1 Appendix C: Introduction to Object Oriented Concepts Classify Handbook The object

C.1. The object Obviously, the object is a key concept within object oriented tech- nologies. It is so important that its name is used to identify the entire philosophy. Yet, you will find that the concept ‘object’ is not very well defined. There might be differences in definition based on whose theory you are reading.

A very general description however (and one I find very practical) is:

An object is a combinating of characteristics and possible behaviors that uniquely identifies/describes something from the world you are describ- ing.

This means an object contains both data and procedures or func- tions (methods) that will act upon this data. An object is a whole, independent fully functional module.

Examples of objects would be: » Acar » A person » An engine » An article

Every object mentioned above has its ‘real life’ counterpart. If we would include objects like ‘sale’ and ‘order’, this would mean we created a sort of ‘virtual object’.

Some object oriented definitions will state that these ‘virtual objects’ should not be defined. Instead the object article should have a message ‘being sold’, a salesperson should have a method to ‘close sale’ and a customer should be able to ‘purchase article’.

On the other hand, while a purchase might be a transaction between people from an analyst perspective studying people, a sales person will see the purchase as the main object (as well as his objective), and the person he made the sale to might not even be important to him (e.g. when selling candy in a department store).

This leads to the conclusion that the objects we want to model cannot be limited to “real life” counterparts. There will be situations where we will need to create objects for concepts that have no “touchable” form.

A second important conclusion is that the objects we will derive in a certain situation depends on our perspective: what do we want to model? At first sight, this might seem contra dictionary with the OO principle and the hope of a better re-usability of our products (both analysis, design and program-code). But if we look a bit closer, we will find that again the difference in perspective is another thing you will find in daily life as well.

One of the best commercials I’ve ever seen featured an English business man (with umbrella, hat and attache-case) waiting for the bus and a skinhead. The camera focuses in on the business man holding his attache case close to his body and the skinhead running towards him, with his arms outstretched. This is shown from several different angles.

The next shot states “News can be shown from many perspectives” and at this point, the viewer is quite convinced the skinhead is going to mug the business man. The next shot allows a wide-angle view of the same situation, but now a piano hanging on a ragged rope is shown over the head of the business man, and the skinhead pushing the other man out of the way just before the piano scatters on the very spot the business man was standing.

Page C.2 April 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix C: Introduction to Object Oriented Concepts The object

The last shot is the slogan “Only we give you the broader perspec- tive”. In a sense we should be like the reporter from this newspaper. We should be able to see the complete picture, and then present it in a way that will appeal to our customers.

Having said this, I want to caution you as well. Taking a broader perspective is good, but if you had filmed the same scene with a wide-angle lens showing all of England as well, the picture had been totally meaningless to anyone interested in this event.

Finding the best focal distance depends on the project underhand, but also on other projects you might involve yourself in. If your company specializes in inventory control systems, it will definitely pay off to take a more general approach to inventory control than necessary for one customer.

If the US-army asks you to develop a system to keep track of nuclear missiles, changes are very slim you will ever need to expand this system beyond their wishes. Even though there might be other parties interested, your contract would inhibit delivery to them.

(c) '92 - '95 Calvin Consultancy April 1995 Page C.3 Appendix C: Introduction to Object Oriented Concepts Classify Handbook Nested objects

C.2. Nested objects One of the examples we used for an object was a car. Another example was ‘engine’. Even though an engine can be part of a car, it is still an object in its own right. This means that an object can have components that can be objects themselves.

In practice, you will find that this is very common. Most objects are built using other objects as their building blocks. This means objects will get ‘nested’.

A very nice real-life example of ‘nested objects’ is a large corpo- ration. The entire corporation is one single object if looked at from the outside. But if we take a look inside, we will see several depart- ments. In every department we will find persons.

This example shows us two very important things. First of all, we find that we will treat the company as a whole if we are not involved with the company ourselves: how it is divided in departments is not of our concern.

Once we get down to department level, we will see the structure of the departments and their specific task. At that point in structure we are already ‘inside’ the company, however, we will not yet distinguish the people in the departments. This shows that “nesting” can take place on many levels and is in fact a recursive process.

This “decomposition” allows you to treat almost every part of an object as a child-object. Some object oriented languages will even treat an integer as an object, having data and methods (add, sub- tract, divide etc.).

C.2.1. Primitives Obviously, this process can not go on forever (like a mirror within a mirror). At some point in the design we will have to specify that the object is constructed of a primitive and operations on this primitive. A primitive will usually be a storage cell for simple information. By definition, it is impossible to perform operations on a primitive. Only by creation of a class supplying the necessary operations, this primitive can be accessed.

Approaching data elements as objects gives us a very high level of language and machine independence, as well as flexibility.

Page C.4 April 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix C: Introduction to Object Oriented Concepts Encapsulation

C.3. Encapsulation In the previous chapter we already used a corporation as an example of encapsulation, even if we did not call it that. Encapsulation (or data hiding) means that one is only able to see the outside of an object. This means that whenever we deal with an object, we are using/observing external characteristics.

The means to achieve encapsulation is to allow access of data only through the use of methods (which will be discussed in more detail later). In general, there will be more methods than data-elements. Some methods will access multiple data elements, some methods will retrieve data elements and others will store data in data-ele- ments.

Please note that I mention data elements rather than primitives: how data is stored or manipulated internally in the object is hidden: only the methods are known. If a method states that information is stored, the mechanics of this should be fully transparent.

The list of methods available to the user of the object is called the interface of the object, all other parts of the object are considered internal implementation.

The nice thing about encapsulation is that the entire internal work- ings of an object might change, and still we would be able to use it just like before. Just think of your own PC for a moment as an object. When they changed it from the good old Intel 8086 to a high speed 80486/50, you were still able to use the same PC. The complete interior was refurnished, but the interface stayed the same. Sure, you problabe blew your hat at the speed this new machine delivers and you might find some new interface features (toggle turbo, insert CD-ROM), but the base interface remained unchanged.

Another example of a good user-interface is the engine of the good-old Volkswagen Beetle. You could take out the engine and put in a porsche-engine (who happened to have the same interface as the beetle-engine) and this would speed up your ‘bug’ to a perform- ance way beyond a corvette.

But encapsulation is a two-edged sword. The advantages of pure encapsulation stand out clearly. But encapsulation by itself does The engines of these two cars share a common interface not give you the benefits from the above examples. These can only be obtained if the developers also stick to the designed interface. If they deliver every version fully encapsulated, but also create a new interface for every release, this will still mean you cannot switch from one object to another.

So in order to benefit from encapsulation, you should design the interface in a way that will support future revisions as well. Or with a new version, you can extend the interface to support new func- tionality.

Another potential weak spot of encapsulation is illustrated by the above examples. I could buy the new computer from almost any vendor and still feel comfortable: the object interface for a personal computer is pretty much standardized. But if I wanted to put a Buick-engine in the Beetle, I would have a hard time. While Volk- swagen internally used encapsulation principles, their encapsulated objects are not compatible with Buick-objects.

Does this example proof object orientation, or at least encapsulation, will only work on a limited scale? No! Because of the encapsulation, it becomes relatively simple to design an “interfacer”, a special wrapper around an object that translates incoming signals to signals that can be understood by the “wrapped” object. Creating an API is

(c) '92 - '95 Calvin Consultancy April 1995 Page C.5 Appendix C: Introduction to Object Oriented Concepts Classify Handbook Encapsulation

a redundant task in an object oriented environment: every interface definition for an object is basically an API in its own right.

The importance of encapsulation automatically leads to an emphasis on interface design. An object should have an interface that provides all the external functionality needed, yet it should not be overly complex because that would inhibit change. Encapsulation is en- forced in some languages, but in most, it is just “good manners”. How easy it is to work within these guidelines depends on your interface.

Example: Let’s take a look at the design for an object “computer monitor”. Basically, we need to create an interface and describe what we expect each method to do. The basic function of a monitor is the translation of incoming video signals to a visible image.

So the most basic version of the monitor would consist of only one message: VIDEO_SIGNAL. Whenever this message was received, the monitor trans- lates the signal to an image and displays this signal for a part of a second. As long as new video-signals keep coming, the display will be refreshed. If no VIDEO_SIGNAL messages are received any more, the screen goes blank.

If you would buy a monitor like this, it would mean that it would be turned on automatically if it receives some video signal. If you want to attach this monitor to a computer acting as a fax-server, you’d problabe want to turn off the monitor during normal operations. However, with this particular monitor, the only way to do this would be to cut the video signals.

So obviously, as a monitor user, I require a bit more control and in order to meet my needs, the manufacturer should implement an on/off feature. Now this can be done in two ways: create one method ACTIVE_STATE with an argument “on” or “off”, or implement two separate methods ON and OFF (both implementations are equally valid, as long as the approach is consistent).

Now I have a monitor I can turn on and off at will. Problabe I wouldn’t mind some additional external controls such as BRIGHTNESS_LEVEL and CON- TRAST_LEVEL. On the other hand, if the designer would decide to make all controls external (such as HORIZONTAL_SYNCHRONIZATION_THRESH- OLD), the user would problabe not know which button to press or which knob to turn. At best, he would ignore all buttons except those he explicitly needed. But he might decide to “play” with the controls and mess up the display and probably blame the monitor rather than himself. In the worst case, he would not buy the monitor to start with because it is “too complicated”.

All these designs are still fully encapsulated, but the first monitor will tempt the user to breach encapsulation (= find some way to turn it off, like pulling the plug) more easily than the “complex version”, in which case he can even adapt it to an exotic video-card without any breach of encapsulation. There is no “best design” from a technical point of view. The “best design” is determined by the response of the user to the interface. If many people complain about the absence of an on/off button, you have provided a too “narrow” interface. If people find it “too complex”, the interface is problabe too broad.

Then again, the target-user also plays a major role in this decision. If the target monitor buyer is an apple user, you might get best response on the fully automatic version, while a technical oriented CAD user, using to high-pow- ered (but non-standard) video card, will not consider anything with less control than the most complex interface design we can come up with.

A final consideration in this would be to provide multiple levels in the interface, ranging from “novice” to “expert”. This can allow tuning of your objects without the need to breach encapsulation principles.

When working in an OO-environment, one might come upon an object with a too limited interface, like the above monitor without ON/OFF function. It seems very tempting to take this monitor, breach encapsulation and install a ON/OFF switch. This would seem to be far less work than designing a monitor from scratch.

On the other hand, it will also breach warranty: you will not be able to complain to the original manufacturer about malfunctions (even if

Page C.6 April 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix C: Introduction to Object Oriented Concepts Encapsulation

we know it has nothing to do with our own changes). And we cannot use his “updates” to the product (or we have to spend more time on them to make them compatible with our new features.

So while it might be very tempting to “go into the black box and change it” (especially if you have source-code for the class), you will have to make a careful consideration whether you really want to do this in the long run.

(c) '92 - '95 Calvin Consultancy April 1995 Page C.7 Appendix C: Introduction to Object Oriented Concepts Classify Handbook Messages and methods

C.4. Messages and As we already stated, all communications with an object should be channeled through its interface. These communications are called methods messages, while the code that will handle the messages are called methods. This means the interface for an object basically consists of a list of messages that can be sent to the object.

A message consists of the message identifier (name), the object the message is sent to and a parameter-list (optional). The object oriented kernel will take this message and “deliver” it to the ad- dressed object. This means it will trigger a method listed in the interface of the object. If the message does not exist within this interface, an error condition will occur. How this error is handled depends on the OO-platform in use (e.g. DataFlex will use automatic delegation, which will be discussed later).

The arguments passed with the message are passed to the method, and any resulting value from the method will be handed back to the object sending the message.

The actual destination of a message is determined at runtime. This gives a designer a large amount of flexibility. Message can be sent to be objects without the need for the compiler to know about those objects. This means that objects can be created and destroyed at runtime. And again, this represents real life situations, where all objects have a limited life cycle. It also means that the syntax of the method (number and type of the arguments) is not (necessarily) known during compilation and checking for number and type of arguments needs to be done at runtime.

This technique to establish the link between message and method at runtime is called “late binding”. It is one of the most powerful characteristics of an object oriented system. Yet, many OO-lan- guages use “static binding” (= link message and method during compilation) because of the performance penalties involved with late binding. Using static binding obviously puts some constrains on the system design (objects need to be known at compile time). An often used compromise is to offer both techniques and ask the program- mertoindicatewhichtechniquehewantstouse,thusallowinghim to optimize between performance and flexibility.

Page C.8 April 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix C: Introduction to Object Oriented Concepts Polymorphism

C.5. Polymorphism Since methods are specific for an object, it is quite possible to have multiple messages with the same name, but with different implemen- tations. This again reflects real-life situations. After all “fill ‘r up”’ sent to the gas-station attendant definitely means something else than the same message to our friendly bartender. Or did you like a glass of petrol and some beer in your car’s tank?

In object oriented theory this just means the same messages can be sent to both bartender and gas-station attendant, but they are handled by different methods, each defined within this particular object. So while the message might be the same, the method handling the message could be thoroughly different.

The use of a good naming scheme for messages can drastically reduce learning time. If you want to activate some (electrical) appli- ance, you will probably look for a knob labeled “ON/OFF”. Regard- less of what happens internally, you know this knob will kick some life into the equipment. Even to the extend where some switches labeled “Off” do not really turn off the system, but put it in “minimum energy” mode. But as far as the user is concerned it is “Off”. To use a computer related example: most software packages have a “Help” Fill ‘r up message. All packages will implement help differently, but activating the help systems is consistent over all packages. For ages, this has enabled me to call up help information from within systems I’d never seen before by pressing [F1]. It also implemented a deep resistance towards software that decided to use another key for help.

This structure implies a two level approach to documentation of messages: one central list with messages and their global descrip- tion (e.g. activate help-system) and a more detailed description of just how that message will react in a given object.

Also, a centralized registration of message names will be necessary to ensure an consistent naming.

(c) '92 - '95 Calvin Consultancy April 1995 Page C.9 Appendix C: Introduction to Object Oriented Concepts Classify Handbook Delegation

C.6. Delegation If we send a message to a particular object, this does not mean that this particular message can be handled by this object. If the mes- sage is not a part of the interface (there is no method available to handle the message), the sender created an error condition. How this error condition is handled depends on the implementation of the object oriented kernel.

Onewayofhandlingthisistopassthemessageontotheparent object (= the object that contains the object that received the original message). All arguments passed with the original messages are passed as well. This technique is called delegation and is fully automatic in some languages (such as DataFlex), but left to the responsibility of the programmer in others (such as C++).

Obviously, this means that if a non-existing message is sent, this message keeps on being delegated to a parent object until no parent object is available. This is why DataFlex creates a special object that encapsulates the entire program (called Desktop). This object will generate an error whenever a non-existing message is sent to this object, either direct or through delegation. In C++, this problem is non-existing. The programmer needs to supply delegation explicitly. If he chooses not to delegate, an error is generated at whatever level the error occurs.

Again, delegation is something we see in day to day situations. If you ask an employee a question he cannot answer, that question gets delegated to his boss, and up until somebody can answer the question. Now usually, the boss does not know the answer, but he knows who knows it. This means the boss will receive the question, and then passes to one of his subordinates. In object terms, this means the message is send to another child-object, not delegation!

This means there must be a method specified for this particular message, even though the only action for this method is sending the message on to a child object. In this example, where the original A message incoming to the sales-person gets delegated to the manager. If the manager has no way of dealing with it, message gets delegated, the message is not necessari a part from he will delegate it to the president. the visible interface for the object (e.g. no one asks this question The president might send the message to another man- ager, but this is no longer delegation. directly from the boss). This also means that we will need to specify

The company President

DELEGATION EXPLICIT SEND

Sales department Technical services Sales manager Service manager

DELEGATION EXPLICIT SEND

Sales persons Technical support staff

Page C.10 April 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix C: Introduction to Object Oriented Concepts Delegation

both an external interface and an internal interface. We will discuss this in more detail later.

(c) '92 - '95 Calvin Consultancy April 1995 Page C.11 Appendix C: Introduction to Object Oriented Concepts Classify Handbook Classes

C.7. Classes A final concept we need to discuss is class-definition. If we talk about objects, we always refer to one specific instance of this object. If we had to re-create each and every object separately, object orientation would never become very popular.

But again like in real life, object orientation offers us a way to generalize, a way to provide standard descriptions on which objects are based. These general descriptions are called classes and have the same characteristics as an object, they just lack the data.

So while a class can specify that any object of that class has a characteristic ‘serial number’, the class could never store the serial number while the object can.

Classes are used to make stamps, objects are the prints.

The definition of classes and the definition of objects involves the same problems and decisions. Actually, I would argue that in almost all cases, one should only design classes. Objects should be directly derived from classes with no additional characteristics or capabili- ties; just data. Creating additional characteristics at the object level should be avoided in all cases but those where it is absolutely impossible to have multiple instances of a particular class/object. An example of this is the Desktop object in DataFlex. By design this is the outermost object containing an entire application. This also means that (at least per application) there can only be one such object.

On the other (just to proof the initial statement), many “newer” software products allow the user to set up multiple desktops. If one has designed the desktop as a class, this is easy to do. If the desktop is implemented as an object......

In all cases, the overhead of creating a new class is minimal, while the chance that you will need another object based on the same class is larger than you would think during class-construction (80 to 90%).

Page C.12 April 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix C: Introduction to Object Oriented Concepts Class inheritance

C.8. Class inheritance But the advantage of classes goes even beyond this. If I need to create a new class (Train) I can base this on an existing class (Vehicle) and just describe the differences between the two. The new class (subclass) inherited all the characteristics from the exist- ing class (parent).

Using this technique repeatedly, we can construct quite complex class-trees, showing a greater level of detail with every level. An example of a class tree is drawn in this picture.

General Vehicle Class

General Ground Vehicle Class

General Vehicle Class

General Vehicle Class General Vehicle Class

Setting up a proper class-tree is the most difficult part of designing an object oriented application. And if the class-tree is well designed, it will even spawn multiple applications, giving you the benefit of being able to use the efforts put into one project in another.

(c) '92 - '95 Calvin Consultancy April 1995 Page C.13 Appendix C: Introduction to Object Oriented Concepts Classify Handbook Event driven user interface

C.9. Event driven user An event driven user interface is not characteristic of object orien- tation. Event driven user interfaces can be constructed using tradi- interface tional, procedural programming techniques, while process-driven user interfaces can be built using an object oriented language.

But since the object oriented languages offer a great platform for event driven interfaces, the two are often mentioned together. And indeed, creating a reliable system with an event driven user interface and a procedural language is a harsh task. But doing the same with an object oriented language is much easier. Which results in many programs written using object oriented techniques having an event driven user-interface.

The event driven user interface is directed at the “power user”. This is a new type of computer user that requires more flexibility and usually will have at least a broad experience in using computers. Preferably, the interface offered is compliant with standards such as IBM’s CUA. This means the power-user can immediately start to use the system, even if he is not familiar with this specific program; the skills from other applications will help him in this application as well.

But by enabling the user to set his own path throughout an applica- tion, we will also need to change our own perspective about the design of applications. While we used to take the user and “drag” him through a program, we now have to be prepared for every trick the user can think of. We need to start programming in a “defensive” manner, providing life-nets in case the user drops, rather than restricting him to one corridor.

Page C.14 April 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix D: Language additions

D. Language addi- Classify adds a number of commands to the standard DataFlex syntax. This chapter contains a listing of these commands and their tions use. You can find these macros in MACROS.INC in the PKG directory.

We have also extended the three “message” commands GET, SET and SEND by allowing three extra arguments. This extention is also discussed in this appendix.

All modifications are done in the MACROS.INC file and no changes in the FMAC are necessary.

Many of these commands were designed for very specific reasons. They are documented here for completeness, but we want to stress that we do not support these commands outside their recommended use. They are not designed as general extensions of the language definition (unless explicitely mentioned).

(c) '92 - '95 Calvin Consultancy May 1995 Page D.1 Appendix D: Language additions Classify Handbook Extensions

D.1. Extensions As said, we have added a couple of extensions to the Send, Get and Set command syntax. This additions basically allow you to use special argument types in these commands.

D.1.1. Field As is listed in numerous places in the manual, you can add the FIELD keyword to indicate that you want to use the field number as argu- ment rather than the contents of the field.

Lets use the example of HdsUse.User_Id and assume the filenum- ber for HdsUse is 248 and the fieldnumber for User_Id is 1.

Example: Send mAdd_Option Field HdsUse.User_Id To @_Capslock

will “translate” into:

Send mAdd_Option 1 To @_Capslock

D.1.2. FileField This keyword resembles field, but now sets up two arguments, the file number and the fieldnumber.

Example: Get pCreate_Item FileField HdsUse.User_Id To Void

would “translate” into

Get pCreate_Item 248 1 To Void

D.1.3. Exp This keyword can be used to avoid the need for the symbol table at runtime. If you would specify a default for a field as:

Set pDefault_Value Field Article.Price To ; “(pStandardprice(pData_Dictionary(Curr ent_Object)))”

But this would require the symbol table to be able to evaluate the expression at runtime. If you use the Exp keyword, the expression is converted to internal symbols by the compiler, but will be evalu- ated at runtime. But since the compiler handled the symbol substi- tution, the runtime now does not require a symbol table.

The above example would now look as:

Example: Set pDefault_Value Field Article.Price To ; Exp (pStandardprice(pData_Dictionary(Current_Object)))

Please note the absence of the quotes!

Page D.2 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix D: Language additions New commands

D.2. New commands This section lists the new commands we have added to DataFlex.

D.2.1. Dynamic_Image This command is designed to allow reuseability of image definitions. It is used to create image-definitions for zoom-classes and is used in conjunction with the zoom class and the Next_Image keyword on the object definition line of the zoom object.

Syntax: Dynamic_Image

D.2.2. Extract_Field_Nr This is a special command that extracts the fieldnumber from a File.Field reference at compile time.

Syntax: Extract_Field_Nr [File.Field]To[Var]

D.2.3. FGet This command provides an alternative for the standard GET com- mand. The difference lies in the compiler processing: this command will internally convert the GET syntax to a MOVE command using the expression evaluator. This will result in a decrease of usage for the static message space area, but will increase the use of the static data area.

Since the expression evaluator expects all the arguments and also requires a function to be typed, it might be possible that certain functions are not convertable. This might result in compiler errors. There is a list of compiler directives that tell the compiler not to try conversion and retain the original syntax. You can use additional functions to this list by specifying:

#REPLACE MSG_NAME$UNTYPED YES

where you specify the name of the property or function instead of “MSG_NAME”. There is no need to use the GET_ prefix in this.

Syntax: fGet Function_Name {Of Object_Id} {Item ItemNr}{Arguments}ToVar

This command is designed for your convenience. It will allow you to balance the usage of message area and data area. This is especially important for environments using pre-3.05 version of DataFlex.

D.2.4. Fill_Wrap This command will fill an image line by line.

D.2.5. Default_Output This command is a slight modification of the standard Output com- mand that will use the current image by default if no image is specified.

Syntax: Default_Output {Channel}{Image}

D.2.6. Indirect_File_Size Similar to the standard File_Size, but this command will take a file number as argument rather than the name.

Syntax: Indirect_File_Size FileNr To Current_Size Max_Size Field_Count

D.2.7. Push_Parameter This command is used internally by the expression evaluator build into Classify. We do not recommend (nor support) other usage.

D.2.8. Indirect_Reread Reread, but now capable of working with Indirect_File.

Syntax: Indirect_Reread FileNr

D.2.9. Indirect_File_Mode Operates as filemode, but accepts indirect file numbers.

Syntax: Indirect_File_Mode FileNr [Default|Read_Only|Alias|Master_Alias]

(c) '92 - '95 Calvin Consultancy May 1995 Page D.3 Appendix D: Language additions Classify Handbook New commands

D.2.10. Transaction This command is used to provide TTS compatibility. In the provided file (TTS_MAC.INC), the command is just dummied. To enable, you will have to replace this command with the appropiate command defini- tions for your specific flavor of TTS (DFTTS, DF4BTRIEVE, VINGA).

The actual syntax might depend on the TTS system used.The sup- plied arguments are: » BEGIN Start the transaction » END Transaction succesfully completed » ABORT Transaction aborted, trigger rollback

D.2.11. Use_Extend This is an extension to the existing use command that will except a full filename, including the file-extension. Like the standard USE command, it will only include a file once.

Syntax: Use_Extend Filename.Ext

This command is designed to allow you to use different extensions for your packages, thus making the naming a bit more intuitive.

D.2.12. Use_Extend_Img This command is used to include image definitions. It works with the Dynamic_Image command and the zoom classes to create multiple instances of the same image to be used by multiple objects.

It should not be confused with the standard Use or Use_Extend command!

Syntax: Use_Extend_Img Filename.Ext

This command actually has a different use as well. If used in the above syntax, it will just include the image file. But the alternate syntax will attach the whole set of images to a view object. In order to be able to do this, you must specify the object name as well.

Alternate: Use_Extend_Img Filename.Ext For|For_View Object_Name

The FOR_VIEW syntax is added to support compatibility with DF_Editor. The regular FOR keyword will conflict with its indentation logic.

D.2.13. Use_File This file is also found in some Data Access packages and will read an .FD file without opening the file, thus enabling the compiler to recognize the file and fieldnames

Syntax: Use_File Filename

Page D.4 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix D: Language additions Compiler directives

D.3. Compiler directives We have added a number of compiler directives to Classify. All these compiler directives are specified in the file USAGE.INC. A number of these directives are intended to make “customized” versions of Classify and are discussed in appendix B2. Others are intended for use by developers extending Classify or trying to provide additional functionality.

D.3.1. Framework ID We added this compiler directive with 3rd party developers in mind who want to make their classes aware of avialable frameworks. You can use it in the following way:

Example: #IFSAME FRAMEWORK$ID CLASSIFY Get pRequest_Channel To Channel_Id #ELSE Move 8 To Channel_Id #ENDIF

D.3.1.1. Classify version We have also added a compiler directive to determine the Classify version. Again, this can be used to check for certain features.

We use a version ID consisting of 5 digits:

XYYZZ

X is the most significant version number. YY is major version number, ZZ can be used for minor update units.

Examples: » 1.05b: 10520 » 1.06: 10600

Example: #IF (CL$VERSION > 10599) Set pError_Handler To mCreate_Error_File #ENDIF

This will only set this property if you use Classify 1.06 or above. This will in general not be very usefull for Classify developers, but might be important for 3rd party developers who want to make their product available to as many developers as possible.

D.3.2. DataFlex version Again, like with the Classify version, we added a version ID for DataFlex as well. It uses the same structure and offers more detail than the standard DataFlex directives.

Examples: » 3.01b: 30120 » 3.05: 30500 » 3.05.2: 30502

Example: #IF (DF$VERSION > 30499) Direct_Input “RESIDENT:CL_MAIN.INI” #ELSE Direct_Input “CL_MAIN.INI” #ENDIF

This idrective is used internally within Classify to determine whether 3.05 specific features can be used or not. It is important that it corersponds with the DataFlex version you are using.

D.3.3. Runtime access There are also three global functions defined: Framework_Id, CL_Version and DF_Version. They return the value as set up in the compiler directives. Remember this is compile time information and does not tell you anything about the runtime DataFlex license! All id’s are returned as strings.

Syntax: Move (Framework_Id()) To [Var] Move (Cl_Version()) To [Var] Move (DF_Version()) To [Var]

(c) '92 - '95 Calvin Consultancy May 1995 Page D.5 Classify Handbook Appendix E: Global functions

E. Global functions Classify offers a small library with global functions that can be used throughout your program. In this appendix we give an overview of the available functions and their usage.

The functions are grouped based on their functionality.

(c) '92 - '95 Calvin Consultancy May 1995 Page E.2 Appendix E: Global functions Classify Handbook String operations

E.1. String operations This paragraph contains the string manipulation functions

E.1.1. Last pos Determine the last position of a character in a string.

Syntax: fLast_Pos(String, Character)

E.1.2. Right justify Right-justifies a string by prefixing spaces.

Syntax: fRight_Justify(String, Length)

E.1.3. Left justify Pads the string to the specified length.

Syntax: fleft_Justify(String, Length)

E.1.4. Left pad string Left justifies a string using a specified character as leader rather than space.

Syntax: fLeft_Pad_String(Prefix, Length, String)

E.1.5. Capitalize Turns first character into uppercase, all others into lowercase

Syntax: fCapitalize(String)

E.1.6. String type Checks the type of the contents of the passed string. Possible return values: » NP: Number, positive » NN: Number, negative » IP: Integer positive » IN: Integer, negative » NC: No characters, only 0..9 or “.,/+*() #”

Syntax: fString_Type(Type)

Page E.3 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix E: Global functions Numeric functions

E.2. Numeric functions This paragraph lists the numeric functions specified in Classify.

E.2.1. Round Rounds to a given number of decimal positions

Syntax: fRound(Value, Nr_Of_Places)

(c) '92 - '95 Calvin Consultancy May 1995 Page E.4 Appendix E: Global functions Classify Handbook Date functions

E.3. Date functions All date functions are independent of the date-setting in the DataFlex configuration.

E.3.1. Date Type Returns the setting in the configuration. Possible return values: » @_American » @_European » @_Military

Syntax: fDate_Type()

E.3.2. Today Return the system date in 4-digit year representation

Syntax: fToday()

E.3.3. Year Return the year-part of a date

Syntax: fYear(Date)

E.3.4. Month Return the month-part of a date

Syntax: fMonth(Date)

E.3.5. Day Return the day-part of a date

Syntax: fDay(Date)

E.3.6. Date DMY To String Appends the given day, month and year into a string using the specified date format

Syntax: fDate_DMY_To_String(Date_Format, Day, Month, Year)

E.3.7. Compose date Take date, month and year and combine it into a date

Syntax: fCompose_Date(Day, Month, Year)

E.3.8. Day number Returns the day in the week: » @_Monday » @_Tuesday » @_Wednesday » @_Thursday » @_Friday » @_Saturday » @_Sunday

Syntax: fDay_Number(Date)

E.3.9. Week number This function takes a date and calculates the weeknumber (weeks starting on a Monday).

Syntax: fWeek_Number

E.3.10. Date to string Converts a date to string using the specified date format.

Syntax: fDate_To_String {Date} {Date_Type}

Page E.5 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix E: Global functions Desktop functions

E.4. Desktop functions Classify offers a number of desktop functions. These are different from the global functions provided because they need and rely on the desktop functionalities of Classify.

A number of these message have been discussed in various parts of the manual, so there might be a number of duplications. We have grouped them here together because they provide a very powerfull toolset that can be called upon from any situation.

Theoretically, you should always be able to activate these functions through automatic delegation of messages. Unfortunately, delega- tion is turned off (to long) during a broadcast which could result in a message not being delegated in every situation.

To prevent problems with this, you can direct the messages directly to PROGRAM_DESKTOP. So instead of:

Get pRequest_Channel To Channel_Id

Youshoulddo

Get pRequest_Channel Of Program_Desktop To Channel_Id

This will make sure your messages reach the desktop, and it also makes it easy to track down all references to Program_Desktop once this bug is fixed.

E.4.1. I/O channel management Classify offers I/O channel management. This is necessary because objects are written independently and can therefore not rely on a hardcoded channel number: the risk of conflicts would be to big.

Classify offers “standard” channel management and “device con- trol”. The standard channel management only returns the ID of a free channel. The device control also takes care of opening and initializ- ing the device.

E.4.1.1. Request Channel Request the ID of an unused channel from the desktop. If the return value is -1, there is no free channel available.

Warning: You should check for the return value and take proper action. The channel manager does not issue an error message itself!

Syntax: get pRequest_Channel To [Var]

E.4.1.2. Release Channel This is the counterpart of request channel and restores a channel to the list of available channels. You should always release a channel once you are finished with the ID operations.

Syntax: Send mRelease_Channel [Channel_Nr]

E.4.1.3. Open device This function is especially designed for output to printers and files. It is a highly complex function with a lot of parameters and return values. To be able to handle all these, we pass an array as argument back and forth.

If you send the open device message, the desktop will interrogate the devices file, and handle all output according to that. Please also lookup the file description.

In the array you can store the following parameters: » 0: Default device The Id of the device to select as a default » 1: Prompt user Should the user be prompted to select a device or not. The following options are accepted: 1: Yes

(c) '92 - '95 Calvin Consultancy May 1995 Page E.6 Appendix E: Global functions Classify Handbook Desktop functions

2: No, never 3: Only if the default device is not available » 2: Redirect_Allowed

Once the device is selected, the desktop will perform the necessary pre-print actions and open the device for output. It will then return the channel_Id. If the message returns -1, there was no free channel available. If the return values equals -2, the user aborted the selec- tion. A -3 return value indicates the requested device was not available and user prompts where disabled. Once again, the mes- sage itself will not generate an error message.

Upon completion, the array will contain the following information: » 0: Device ID The ID of the selected device » 1: Device_Name The actual device name » 2: Printer type The type of the printer specified for this device

Syntax: Get pOpen_Device [Array_Id] To [Var]

Example: Local Integer Array_Id Local Integer Channel_Id Local String Printer_Type

Move (fCreate_Array(1)) To Array_Id Set Value Of Array_Id Item 0 To “HP-OFFICE” Set Value Of Array_Id Item 1 To 1 Get pOpen_Device Array_Id To Channel_Id Get Value Of Array_Id Item 2 To Printer_Type Send Destroy_Object To Array_Id

E.4.1.4. Close Device This is the counterpart message of open device. It will close the output channel and release the channel, as well as perform any post-print commands specified in the device setup.

Syntax: Send mClose_Device [Channel_Id

E.4.2. Showing a “busy” status Classify has a standard feature to show the user the program is busy. We offer several “modes” of operating, all controlled by a single set of messages.

E.4.2.1. Start Busy Object This message activates the “busy object”. If the object is already active, the object remains active, but a counter is updated so that the object is only deactivate when the start & stop messages are finished. This allows you to use this message, even if you are not sure about the current status.

Syntax: Send mStart_Busy_Object [Mode] [Description] [Count]

The following modes are supported: » @_Busy_Display This mode just shows the description passed with a second line “please wait”. » @_Busy_Counters This mode allows you to use a set of counters and to display their values. You must set up the counter-labels using mSet_Counter and the counters are updated by mUpdate_Counter. » @_Busy_Percentage This mode will show a progress bar indicating a percentage completed. When you use this mode, you must indicate the “maximum” number in Counter, and indicate progress using mUpdate_Counter with counter number 0. » @_Busy_Running The visual representation of this mode is similar to the percent- age mode, but rather than a percentage, it will show a pointer. This pointer will loop indefinitely. This is ideal if you do not know the number of iterations of a loop.

Page E.7 May 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix E: Global functions Desktop functions

The Counter now needs to indicate the number of iterations between indicator movements (so Counter 10 means it will ad- vange every 10 iteraritions). You can send mUpdate_Running to signal the next iteration.

E.4.2.2. Stop Busy Object This message removes the busy object. However, if you have send mStart_Busy_Object multiple times, this message will only deacti- vate the object once the number of start-messages is matched.

Syntax: Send mStop_Busy_Object

E.4.2.3. Kill Busy Object This message is similar to the stop busy message but will remove the busy object independent of the activation count.

Syntax: Send mKill_Busy_Object

E.4.2.4. Update Busy Description This message allows you to change the main description (first line) of the busy object. If you send this message and the busy object is not yet activated, it will automaticlayy be activated.

So it is perfectly legal to send a number f update busy description messages followed by stop busy object. This is especially handy if you do not know up front whether you will need the busy object or not (e.g. constraints).

Syntax: Send mUpdate_Busy_Description [Text]

E.4.2.5. Update Busy Detail This message allows you to set the detail line (3rd) of the busy object. This message will not activate the busy object (unlike the update busy description) and should only be send when the object is active.

Syntax: Send mUpdate_Busy_Detail [Text]

E.4.2.6. Set Busy Counter You can have the busy object display one or more counters on the 3rd line. They are displayed as “label: value”. Before you can use this, you should set the label and initial value using this message.

Syntax: Send mSet_Busy_Counter [CounterNr] [Label] [Initial value]

E.4.2.7. Update Busy Counter This message is used to update the counters as well as the percent- age indicator.

Syntax: Send mUpdate_Busy_Counter [CounterNr] [Delta]

In delat you specify the change in the counter you want (usually, this will be 1). The CounterNr identiefies which counter should be changed. If you specify CounterNr zero (0), the specified Delta will be added to the counter displayed as a percentage bar.

The display of the values is updated automatically. However, if you use the percentage bar, adding 1 will not always result in an updated display (if the high count is set to 400, the display is only updated every 40 “ticks”).

(c) '92 - '95 Calvin Consultancy May 1995 Page E.8 Classify Handbook Appendix F: Windows considerations

F. Windows con- When you are developing for Windows, or intend to port your appli- cation to Windows there are a number of features you might want to siderations implement that are not of any importance in a character mode version. These things apply mostly to the appearance of your appli- cation.

The most important items discussed here are: » Compatibilty considerations » Screen design: DYNPRESS » INI settings » Resource files

(c) '92 - '95 Calvin Consultancy June 1995 Page F.1 Appendix F: Windows considerations Classify Handbook Source compatibility

F.1. Source compatibility Eventhough source code compatibility between charactermode (CM) and graphical (GUI) versions of Classify programs was a paramount concern in the development, tghis does not mean that you will be able to take any CM program, recompile it and produce a GUI version. The first major concern is that only the Classify classes will offer source code compatibility. So if you have used other (base) classes (e.g. LIST or FORM), these parts of the program must be converted manually.

While we do plan to implement some “code compatible base classes” these are not available in the current release.

The second consideration is looks. If you would take a standard CM application and recompile it, Classify would convert all the zooms to their own panels and list all the fields in them in a single column from top to bottom.

By using the pCreate_Dynpress_Item or pCreate_Dyn- press_Style_Item messages rather tha the standard pCreate_Item you are building a CM application that will port easily to Windows. The same applies to the use of the View Panel class rather than the View class.

As you can see the view panel provides its own visable container around the view. The zoom with options (“Included in price”) is not auto activated, so it has its own border. The 3d border around the whole find object (upper left) is created by setting the pEffect prop- erty of the zoom.

The buttons are moved to the top of the main panel automatically (when compared to the CM version where they apprear at the bottom). The “Window” pull down is also created automatically in the windows environment.

The “prompt icons” are also added automatically at runtime for all index fields and all fields with a prompt object.

Page F.2 June 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix F: Windows considerations Screen design

F.2. Screen design In character mode, designing images was easy. In general, you used 80 columns by 25 lines (24 to play it save, 50 if you like it wild) and that was about it. Maybe some linedrawing characters to make it look fancy and allowances for color or monochrome monitors.

In Windows, we are looking at a totally different environment. Reso- lutions on the average desktop range from 640 * 800 to over twice as much; physical screen size varies from a small 14" monitor to a huge 21" workplace and the number of installed fonts could vary from 4 to 400 while colors run from 16 to 16M.

One approach to this problem is the use of visual screen designers. Like an artist you can “paint” your application on your computer “exactly as it should look”. But that only applies if the user has exactly the same configuration. Needless to say that this is hardly ever the case.

Now several mechanisms are used to adapt the painting to the users workplace. Either we assume a fixed size, making the application appear “smaller” under higher resolutions and potentially “overflow” the screen in lower resolutions. The other technique is to size the application relative to the resolution. But this will result in huge looking applications when run on high resolutions, while the some application might be to tiny an low resolutions.

Just imagine Rembrand’s famous Nightwatch painting reduced to a mere postcard. Or the Mona Lisa enlarged to 4 times its size.

Another important consideration is ofcourse the avialbility of fonts. If you want to make sure your application runs on every Windows nstallation, you should limit yourself to the four standard fonts. But than what use is the 200-fonts collection on the machine of the end-users (so he happens to like courier characters).

Confronted with this problem we have analysed the data entry screens from a large number of applications and we have found that all these scrrens could be reduced to a set of rows and columns. The columns are not evenly spaced, and sometimes one data entry field will spawn multiple columns, but rows and columns nevertheless. Using this as the basis, we developed a way of specifying images independent of font, font size or even field and text length called DYNPRESS. Dynpress stands for DYNamic PRESentation Specification and basically specifies all images using rows and columns.

In Dynpress, you will need to specify a row and a column for every field you want to display. At runtime, Classify will take the informa- tion about this field (type, length, font, capslock state) and based on

(c) '92 - '95 Calvin Consultancy June 1995 Page F.3 Appendix F: Windows considerations Classify Handbook Screen design

this data calculate its width and height. Once it has calculated the width and height of all the entries in an object it will than calculated the width for every column and the height of every row.

Once the width and height have been calculated, Classify will assign absolute coordinates to every object. It will at that point also calcu- late the needed size of the container.

In the figure on the previous page you can see the result of a dynpress specified image. Please note that in the “address informa- tion” zoom contains 3 columns.

Theoretically we could (and intend to) apply the same logic to the containers, but this is not implemented in the current version.

There are a number of advantages to the use of DYNPRESS: » Easy screen design » Allows the user to select any font and will adopt automatically » Screen layout will adapt to changes in description length for instance for translated versions » Screen layout will automatically adapt when you change field lengths (e.g. for currencies or for different product codes)

Dynpress is not the only feature that supports the end-user configu- ration of programs. Of course Classify allows “drag and save” of any zoom. But additionally, it also allows the user to save the sizes of those objects that appear with a “thick” border (such as the view panel and edit objects). These are saved automatically together with the location.

Classify saves different sets of locations for GUI and CM versions of the program, so the user can save different screen layouts in CM and GUI. However, the positions in GUI are save in pixels. This means that saved locations are specific to the resolution used. Saving by pixel is done to allow repositioning at the exact location where the user saved the window. However, pixel positioning is relative to the DataFlex desktop, not absolute.

In the view panel class, all auto-activated panels appear without a panel. This means there is no standard way to drag/resize these objects. To allow you to do this anyway, you can activate the floating menu and select “rubberband”. The rubberband will allow you to drag (left mouse button) and resize (corner) the object. Once you agree with size and position you can deactivate the rubberband by clicking on the right mouse button again. You can than save the window positions.

Of course, the locations in a view panel are saved relative to the position of the view panel itself.

A final consideration in the runtime formatting of GUI applications are the INI file settings. These will control a lot of the algoritms used. The details of these settings are discussed in the next paragraph.

Page F.4 June 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix F: Windows considerations INI settings

F.3. INI settings The CL_MAIN.INI file can contain a number of additional settings specific for Classify For Windows. For the most up to date informa- tion, please check the on-line documentation in the CID file or in the system program. However, the following settings are the most im- portant.

F.3.1. Windows This section contains general windows preferences.

F.3.1.1. Calendar Rather than using our own calendar we think that it is more “windows like” to use available windows applications. Using this setting you can specify the program to activate when the user selects the calendar option from the desktop pulldown.

F.3.1.2. Editor Likewise, you can specify your favorit editor.

F.3.1.3. Calculator And finally the calculator.

F.3.1.4. Icondir The directory in which the icon files are located.

F.3.1.5. PromptIcon The name of the file containing the icon to display when a prompt is available for a field (default the looking glass). If you leave this field blank, the prompt item will be omitted (and the screen layout will adjust to use the now un-needed space).

You must specify the name as “filename.x” where “x” is the sequence number of the icon you want.

F.3.1.6. ButtonBarSize Using this setting you can control the size of the buttonbar. We suggest you use values based on the formula ( (16 * x) + 4) for best results.

F.3.1.7. DesktopHeight & -Width The initial size of the DataFlex desktop can be controlled using these settings. They are specified as a percentage of the full screen.

F.3.1.8. DesktopRow(Column)Loca- These settings control the initial location of the desktop (again in tion percentages).

F.3.2. Windows spacing Since DYNPRESS is a dynamic process, it can easily be “tuned” at runtime. To allow you to adopt it to your preferences, we have made a large number of the parameters used external. Please check the CID file for defaults as these might change more frequently than this documentation

F.3.2.1. Horizontal spacing When creating a text or entry object, this is number specifies the horizontal “white space” in the object (left & right margin). It is expressed in a factor of the character width of that object. So a value of 2 means a total margin of 1 character. A value 1 indicates no margin.

Important: This margin is part of the object. So any borders are drawn OUTSIDE of this space.

F.3.2.2. Vertical spacing When creating a text or entry object, this is number specifies the vertical “white space” in the object (top & bottom margin). It is expressed in a factor of the character height of that object. So a value of 2 means a total margin of 1 line, a value of 1 means no white space.

Important: This margin is part of the object. So any borders are drawn OUTSIDE of this space.

F.3.2.3. Item spacing The number of pixels to be left blank at the end of a text box before another object can be displayed. This effectively determines the horizontal spacing between columns when text boxes are involved.

(c) '92 - '95 Calvin Consultancy June 1995 Page F.5 Appendix F: Windows considerations Classify Handbook INI settings

If you have a text box followed by an entry, this setting determines the space between the two.

F.3.2.4. Column spacing The number of pixels to be left blank at the end of an entry box before another object can be displayed. This effectively determines the horizontal spacing between columns when entry objects are in- volved.

This separate setting allows you to have a wider spacing between “columns” consisting of text box / entry object combinations. By setting item spacing low and column spacing high, you will create a small gap between the description and the actual entry object and a larger gap between the entry object and the next description.

F.3.2.5. Line spacing This is the number of pixels left blank between two objects.

F.3.2.6. Prompt spacing The number of pixels left blank between the entry form and the prompt icon. By setting this to “0", you can force the prompt icon to ”attach" to the entry object.

F.3.3. User styles Classify uses styles to describe how an object looks. The style description currently looks like this:

Font name, Font size, Font style, 3d effect

The font name and font size can contain any valid Windows font that is installed on the machine. The font style is an integer that indicates the presentation of the font. You can specify the following effects: » 1: Bold » 2: Italic » 4: Underline

You can specify combinations by adding them. So “6" would mean italics and underline.

You can specify the following 3d effects: » 1: Chiseled » 2: Raised » 3: Raised beveled » 4: Creased beveled » 5: Shadowed

As a programmer, you can create as many different styles as you want. In the program you can reference the styles by number. By default, Classify will use 6 different styles: » Style 0 The default for all column oriented descriptions » Style 1 The default style for all column oriented entry fields » Style 2 The default style for all table oriented descriptions » Style 3 The default style for all table oriented entries » Style 4 The default style for all form descriptions (login etc.) » Style 5 The default for all form entries (login etc).

Page F.6 June 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix F: Windows considerations Resource files

F.4. Resource files Since all the building of images is done dynamically in Classify, it is also possible to determine at runtime the contents of an image. Although this is a bit slower than using compiled image descriptions it is highly flexable and ideal for prototyping.

In the resource file, you specify the name of the file, the name of the field, the row & column, the style, desciption and length of the field you want to use (much like the pCreate_Dynpress_Style_Item).

Currently, the resource files are ASCII based but we do intend to move them to the database as soon as possible. We will include fuller documentation at that point in time. If you want to use this feature in the meantime, please request the white paper on resource files.

(c) '92 - '95 Calvin Consultancy June 1995 Page F.7 Appendix F: Windows considerations Classify Handbook CFN files

F.5. CFN files Since all the images are build at runtime, we decided to keep the field descriptions outside the program as well. The TAG file however provides only one description and usually you will want to have the ability to use different descriptors depending on whether you use a form or a table.

This is why we introduced the CFN file. This file can contained two descriptions per field (comma delimited, fields are line delimited like the TAG fiels). The first description is used for forms, the second for table oriented objects.

The above pictures show the table descriptions and differences in description styles between form and table.

Page F.8 June 1995 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix A: Dynamic use of the filelist

A. Dynamic use of Some developers have run into the 250-file limitation of the filelist. Although we cannot totally remove the filelist, we have developed a the filelist technique that will allow you to expand your projects beyond the traditional filelist boundaries.

Eventhough we have tested this extensively, we do want to remind you that this is bleeding edge technology. Although we are using only native DataFlex commands, we do not feel this is “DAC sup- ported usage”. So unless you absolutely need this, do not use it for fun.

While we were able to lift the filelist limit, there are some other limitations & considerations you must stick to when you want to use this: » Every instantiation of the runtime must have its own copy of the filelist. This is the most important requirement. Classify will dynamically update this filelist. If the same filelist would be used by several processes, the result would be unpredictable (but might be spectacular). » The location of the filelist should be identified by the environment setting CLFLIST. This setting should contain a full path including “filelist.”, but excluding “cfg”. » This filelist should be the first one in your DFPATH » The user should have full access rights to this directory (read, write, create). » You cannot use “Export Files” when doing chain waits » The “Index X” argument for the open command will be ignored. » You cannot use DataFlex relationships. If you want, you can still put them in the file as well as in the DDO but than you must set the pUse_Df_File_Relations to FALSE. » Do not mix programs using the filelist and not using the filelist in CHAIN_WAITs. If you do mix them via a menu system, make sure that you are using the correct filelist! » You cannot use more than 250 files per program (230 excluding the Classify files). » This is primarily intended for record locking environments.If you you are using a file locking environment, this can still work, but the following is required: ° Create one extra file (just one field, one record Always open this file as the first file in your program. ° Do not use this file in Classify (which migh make the file read-only). This does imply that one file is shared among all LOCKS, which might have a negative effect on network performance. On the other hand, if you do not do this, it might result in DEADLOCK situations. ° You could also manually prevent deadlocks by putting all OPEN statements in a “fixed” order in “header” of the programs. You can than delete the files you don’t need in that program. This will also effectively prevent deadlocks.

Now that we have the horror stories out of the way, there are two ways of using it which we will discuss in the upcoming two para- graphs.

(c) '92 - '95 Calvin Consultancy August '95 Page A.1 Appendix A: Dynamic use of the filelist Classify Handbook Using standard Classify pre-compiles

A.1. Using standard Using this technique, the files opened in the standard Classify pre-compiles (basically all HDS* files) are opened using the “regu- Classify pre-com- lar” method. All the program-specific files are opened using our piles special bag of tricks. To use this methodology, you must do the following: » Put the following statement in your source file after “USE CLASS- IFY”:

#INCLUDE DYNFLIST.INC » Create the “*.cfd” files from the WorkBench and put them in the DEF directory. » Compile the program » Run the program based on the above conditions, using as a start filelist the FILELIST.CFG from Classify\Data. It is not necessary to renew the filelist.

Page A.2 August '95 (c) '92 - '95 Calvin Consultancy Classify Handbook Appendix A: Dynamic use of the filelist Using pre-compiles

A.2. Using pre-compiles This means all files will be opened using dynamic filelist allocation. To do this you must follow the following steps: » Put the following statement in your MINDESK.PKG prior to any OPEN statement:

#INCLUDE DYNFLIST.INC » Create the “*.cfd” files for all Classify files (from the example workbench project). » Precompile all the packages » Put the “#INCLUDE DYNFLIST.INC” statement in helpsys as well. » Recompile helpsys.

For your programs, follow step 1b through 1d. As filelist you can now use anything.

Because of simplicity, we suggest you use option 1 wherever possi- ble (if you want to chain wait to SYSTEM, using option 1 this will be possible with the standard SYSTEM program; if you use option 2, it must be recompiled).

(c) '92 - '95 Calvin Consultancy August '95 Page A.3 Appendix A: Dynamic use of the filelist Classify Handbook Special notes

A.3. Special notes We have decided to not integrate this feature in the Classify US- AGE.INC file because of the potential risks of mis-us.

If your system does not use “COPY from to > NUL” as the command to copy a file, please specify the CLCOPY environment variable like this:

SET CLCOPY="CP %FROM% TO %TO% > NUL"

using the appropiate syntax for your platform.

You can create .CFD files from Workbench 1.x using MAKCFD.FLX

To allow you to enter multiple files in the WorkBench 1.x, you must change the index 3 for CCFILE to include the filename.

Page A.4 August '95 (c) '92 - '95 Calvin Consultancy Classify Workbench / ClassDoc Handbook Chapter I: WorkBench & ClassDoc

I. WorkBench & The Classify WorkBench and ClassDoc provide you with a meta database that can contain a full description of your project. ClassDoc ClassDoc features full class, file and business rules specification, comple- mented with package generation and multi-lingual user reference manuals.

Workbench takes this a step further and allows you to specify the entire data entry environment as well and will generate not only documentation, but also source code and a helpsystem.

Installation We suggest you create a CD_WB directory in your “application envi- ronment”. If you unzip the distribution file using the -d directive, the following directory will be created: » CD_WB ° CMP · 64C ° DAT ° EMPTY

The CMP\64C directory contains the actual program files, compiled for DataFlex 3.1. If we deliver versions compiled for other DataFlex versions, these can reside in their own subdirectory.

The DAT directory contains all the data files common to all projects (e.g. helpfiles, manual texts).

The EMPTY directory finally contains the project related data files.

Starting a new project To start a new project, you should create a new directory (preferably inside your project environemt) and copy the files from CD_WB\EMPTY to this new directory. Now you are all set!

Starting the program Before you can start the program, make the newly created project directory your current directory. Next, you must set DFPath to point to the current directory, the DAT anb CMP\64C directory and to your regular DataFlex directories.

Example: CD \DEVELOP\MYRPOJ\WBD Set DFPath=.;\APPS\CD_WB\DAT;\APPS\CD_WB\CMP\64C;%DFPath%

Registration If you have not registered your version, or you use it with a DataFlex serial number different from the one you provided for registration, the application will automaticallly switch to demo mode. You can register it through the desktop pulldown.

If you have obtained your copy with filled datafiles, it might be that the message “demo limits exceeded” appears during load. Obvi- ously, at that time it is not possible to register through the desktop pull down and you need to obtain the CCREG.FLX registration program (freely available from Calvin Consultancy).

(c) '92 - '96 Calvin Consultancy May 1996 Page I.1 Chapter I: WorkBench & ClassDoc Classify Workbench / ClassDoc Handbook Setup

I.1. Setup The main area for setup is the “source locations”. Both ClassDoc and the WorkBench can generate several types of output files. For ClassDoc this is limited to documents, packages and DEF files. WorkBench will also generate various types of source code.

You can specify where these files must be generated to (directory) in the “source locations” view.

Page I.2 May 1996 (c) '92 - '96 Calvin Consultancy Classify WorklBench Handbook Chapter II: Class documentation

II. Class documen- Documentation is even more important in object oriented environ- ments than it is in procedural environments. Since the advantages tation of object orientation include re-use and a longer software lifecycle, having quick access to up-to-date documentation is very important.

You will find that the documentation is centered around a “Message base” and a “Class definition”. This makes the best use of object oriented principles.

(c) '92 - '96 Calvin Consultancy May 1996 Page II.1 Chapter II: Class documentation Classify WorklBench Handbook

II.1. Message base An important characteristic of object orientation is polymorphism. The advantage of polymorphism is a shorter learning curve because it reduces the number of message one needs to learn. But to implement polymorphism, it is important to have quick access to a list of all messages already defined.

This is why we provide a “Message base”. The message base contains a list of all methods (procedures and functions) specified in the entire system, with the arguments for these methods.

The description you can enter here for the method should be “ge- neric” and apply to the method and not to the implementation. For instance, “Construct Object” would at this level be documented as

This message will be executed during creation of the object. It will create the properties, set default values and create child objects when necessary.

When you build a new class, you can look at the message base to see whether there is already a message-definition available that would suite your requirements. This will help you to create a consis- tent naming conventient throughout your class library (e.g. you will always use mInitialize rather than mInit, mInitialise, mInitialize and mPreform_Initialisation in different classes). This methodology will also make sure that the use of parameters (type, number, order, naming) is consistent throughout the entire class library.

You will find the message definitions in the Functions pull down, Class definitions, Method specifications. You will also see a list containing the classes in which the message is implemented. How- ever, in general this list will be informational here rather than used for data entry (although you can of course do that if you want to).

If you specify a message, you will be asked to specify a “Type”. The three most common types are: » Generic Function (GF) » Generic Procedure (GP) » Generic Procedure Set (GS)

If you select one of these three types, you can enter the arguments (order, name, type and description). The other message types are predefined and have a fixed set of arguments. Classify WorklBench Handbook Chapter II: Class documentation

II.2. Classes Next to the message base, the second very important module is the class-specification. Here you can enter the classes you have speci- fied, along with their parent class, mix in classes and the imple- mented messages. There are also some special settings that are important for the WorkBench generators (such as “type” and the zoom settings).

For the class, you will also see a list with implemented messages for the class. In the option pull down of the message definition you will find the subsystem to specify the mixin statements, header code for the class as well as a change-log subsystem. In the option pull down for the implementations, you will find additional options for the arguments (read only) and the source code of the procedure.

The change-log can be used to log changes on a functional level. You can specify date, programmer, tester, date tested, and more. This information can be used for your information and will also be included in the source code. Please see the appropiate chapter for more information.

The mixin definitions provide you with the ability to specify the mixin statements for the class.

In the header code, you can place any source code statements that need to preceed the actual class definition (such as additonal USE commands, REGISTER statements and REPLACE commands. It is not necessary to include the USE statement for the base class, this is included automatically by the generator.

On the implementation level, you can specify the usage of the message as well as the scope. The scope can be: » External The method can be used from within the object as well as send to the object from another object. An example of this type of method is “Activate” which can be send to an object from any other object. » Internal The method can be used only from nested (child) objects of an object of this class. The message is not part of the external (visable) interface of the object. An example of this would be the pError message in Classify. It can delegated to the desktop from any object within the desktop, but should not be send to the oDesktop object from an object outside it. » Object/Subclass The method should only be used in class construction or sub- classing. It is not intended to be used by external classes. An example of this would be Set pMain_File in the cData_Dictionary. No other object should SET this property. It can only be set either

(c) '92 - '96 Calvin Consultancy May 1996 Page II.3 Chapter II: Class documentation Classify WorklBench Handbook

in the object definition or in a subclass based on the cData_Dic- tionary.

The usage of the message can also be specified. This can be: » Public Any object can send this message to this object to request a service. This message is “open” to usage and should idealy remain constant in interface and actions throughout many ver- sions. » Framework This message is intended for communication between a set of collaborating objects (framework). Only the developers re- sponsable for the maintenance of the framework should use this message. » Technical The message is purely technical and should be treated as a local 3GL function rather than as a message or property. No one rely on this message existing in the next release (or have the same syntax). Classify WorklBench Handbook Chapter II: Class documentation

II.3. Automated proce- We provide functionality to write source code and to read existing dures source code back into the database.

II.3.1. Generating Packages You can have the class definition (PKG) file generated for you. This will include a file header, a log of changes (if specified, see appropi- ate chapter), the header code, class definition and all the methods implemented in the class. Per method, we will also output a comment block. Plus of course, if you have specified it, the source code.

II.3.2. Reading packages You can not only generate packages, you can also read a package file. This will create the appropiate entries in the class, message base and implementation files. You can find the package reader under “Report”, “Import”, “Packages”. You will be asked to select the data file and than the reader is started.

After the complete file is read, it will check for any messages specified in the implementation file that were not encountered during the read phase. These will be deleted from the implementation file, not from the message base.

II.3.3. Reader directives There are certain pieces of information available in the database definitions that cannot be abstracted from the source file during the read-process. The most noteable is the availability of a “method type”. To make sure the reader assigns the correct type, you can use reader directives. These reader directives are put on the end of the method definition line.

Example: Function pBlank_Or_Table Integer FieldNr String Field_Value Returns String //$$FM

The following directives are available: » FM: Field Message » DEP: Dependency function » FUN: General function » GF: Generic function » GP: Generic procedure » GS: Generic procedure set

Another reader directive is the BASECLASS. This is put after the USE statement to include the class definition for the base class of the current class. Since this is put in automatically during source generation, it is important that it is not read and interpreted during the read process.

Example: Use DATADIC //$$BASECLASS

A final reader directive allows you to exclude parts of the code from the reader. This means that they are totally ignored. Obviously, this should only be done with information that is generated automatically in the source code. This directive is mainly used when the generator writes a class definition. To avoid compiler problems and to provide a quick overview of functions available in a class, the generate will automatically create REGISTER statements for all methods in the class.

These commands are put in a NOREAD, NOREADEND block to prevent the reader to read them and add them to the header block.

Example:

//$$NOREAD

Register_Function pBlank_Or_Table Integer FieldNr String FieldValue Returns String

//$$NOREADEND

(c) '92 - '96 Calvin Consultancy May 1996 Page II.5 Chapter II: Class documentation Classify WorklBench Handbook

II.4. Suggestions for use We have found the following method to work very well: » Create the class definition » Create the method definitions (if necessary) » Specify the implementated messages (only documentation) » Generate the packages » Implement the code in the package » Read the package back into the tool » Optionally document the messages added during development » Optionally generate again to reflect any changes in the documen- tation made during development Classify WorkBench & ClassDoc Handbook Chapter III: File definition

III. File definition WorkBench and ClassDoc provide a special section for the docu- mentation of file and field information. There are four views dedi- cated to this. The first view contains type definitions, the second view provides field templates, the third allows you to specify the actual file and field information and the last view allows you to specify the file “environment”, such as indices, relationships and dependencies.

(c) '92 - '96 Calvin Consultancy May 1996 Page III.1 Chapter III: File definition Classify WorkBench & ClassDoc Handbook Types

III.1. Types We allow you to specify your own field types. Later when creating the file definition, you can use these types. Of course, the standard DataFlex types are predefined, but you can also create your own types.Any setting you specify for a given type will be automatically copied to the field definition. And changes in the type definition are propagated to all the fields of that type. So if you create a type “Amount”, numeric 8.2, all the fields based on Amount will have size 8.2. If you at some point need to extend the field, you can go to the type definition and change it to 12.2 and the change will automat- ically be applies to all the fields based on Amount.

The settings for a type are a subset of the settings for a field and while be discussed there.

Page III.2 May 1996 (c) '92 - '96 Calvin Consultancy Classify WorkBench & ClassDoc Handbook Chapter III: File definition Templates

III.2. Templates Templates are intended to provide a base for field definitions. While a field type creates a permanent link between field definition and type definition, the link from template to field-template is only mo- mentarily. The template settings are copied to the link definition, after which the link is broken again. Any changes in the template will not propagate to the field unless you manually re-apply the template.

Again, the information for the template is similar to the field informa- tion, which will be discussed later.

(c) '92 - '96 Calvin Consultancy May 1996 Page III.3 Chapter III: File definition Classify WorkBench & ClassDoc Handbook File and field information

III.3. File and field infor- The first thing you need to specify is the filename and the base class. This base class is important since it will include any “manual” code mation for this file (validations, dependencies).

Next, you can specify a number of simple settings such as compres- sion, lock type and transaction type. These settings get translated directly into DF-File settings. Other settings are for the program, such as synchronisation and linked list support.

The next section contains a number of toggles for the file. » Delete children This flag indicates that the parent record can only be deleted if all children can be delete as well. If the flag is set to false, the parent record can only be deleted if there are no child records left. » Ok to delete children If this flag is set, the data dictionary for this file will attempt to delete all children for a given parent based on the parents request. If not, the data dictionary will only allow deletion of the parent if no child records exist for that parent. » Change key allowed Is it allowed to change the key value in this file? Of course, if it is allowed, it will always progress though the entire database. » Copy child records allowed If this flag is set, it is allowed to copy a record along with all its child records.

The other flags are simple access rights and self-explanatiory.

Next, you can specify a number of functions or procedures to be executed on save and delete actions. Available are: » Ok to delete/save This procedures should check whether the action can be taken or not. A non-zero return value indicates failure.

Page III.4 May 1996 (c) '92 - '96 Calvin Consultancy Classify WorkBench & ClassDoc Handbook Chapter III: File definition File and field information

» Before/After save/delete These are “hook procedures” that should perform additional functions during the save or delete operations. These functions can not be used to abort the operations.

III.3.1. Field information The next level of the screen allows you to specify the information per field. If you press [F4] on the field name, you get the list of field templates. If you select one, all settings will be copied from the template to the field definition. If you want to select an existing field, you can use [sF4] to call up a prompt list with all the fields in the file.

The validation and range information is the next step. You can use several mechanisms to check the data: » Specify a validation procedure » Specify a range (minimum and/or maximum) » Specify a validation table

If you select the validation table approach, there are two types oof tables available:

Limited tables These tables have some limitations. If your requirements fit within these limiattions, this is your best choice: » A maximum of 9 choices » One character return values » No additional values can be specified

Normal tables If your requirements are more demanding, we have also a more advantaged normalised table structure for you. For normal tables, the following applies: » Unlimited number of options (although there is a “practical” limit) » Up to 24 characters return value » Up to 10 additional values per table entry

After you have specified the validation option, you can specify the default value for the field followed by the various entry options that should apply to the field.

The following section allows you to setup additional field-related messages such as entering, exiting and prompt messages. The last section allows you to specify end-user descriptions as well as form and table tags (if different from the fieldname).

III.3.2. Extra file information This second view allows you to specify the “environment” of the file: » Indices » Relationships » Dependencies » Prompt fields

We support a formal relational model. This means that every file has to have a single key, plus optionally a number of additional indices. The key is the (set of) field(s) that uniquely identifies every record. All relationship will reference this key, and there must be an index that contains the key and only the key. This is identifed as the “main index”.

Hence, relationships are specified as a “from fields in child file to parent file” basis; the fileds in the parent file are always the key fields.

We also allow you to specify multiple relationships to the same parent. To differentiate between the two, we use the relationship number and the name (both must be unique in combination with the “to file”). Classify will automatically support these relationships.

(c) '92 - '96 Calvin Consultancy May 1996 Page III.5 Chapter III: File definition Classify WorkBench & ClassDoc Handbook File and field information

Dependencies are specified as functional relationships between fields.If the main trigger field (“From”) is changed, the dependency should be executed and the dependant field (“To”) should be up- dated. So for instance, trigger field would be “Order.Amount”, while the dependant field would be “Customer.Ordertotal”. If any other field is changed, the dependency should not be executed.

In this exapmle however, changed Order.Customer (though unlike) would also have to trigger the dependency (move the amount from one customer to another). So Order.Customer is added as an addi- tional trigger field. It is important to keep the Order.Amount as main trigger because the contents of this field is used in the dependency procedure.

These dependency procedures can be specified based on the type of event triggering the dependency. Delete, Create, Backout and Update are all obvious. Purge is a special event in that it will delete a record without executing the backout and delete dependency procedures. Instead it will execute the purge dependency. This is usefull to provide cleaning actions of databases.

Example: If you keep track of inventory through a dependency from delivery to stcok, deleting a delivery will obviously decrease the stock. But suppose you want to delete all deliveries over 5 years old? This would clean out your stock! So rather than deleting these records, you “purge” them.

The purge dependency could be emnpty, but it could also create a summary record per year.

The prompt fields are again fairly self-explanatory.

Page III.6 May 1996 (c) '92 - '96 Calvin Consultancy Classify WorkBench & ClassDoc Handbook Chapter III: File definition File and field information

III.3.3. DEF-Files You can generate the DEF file for any file through the “Options” pull down while you are in the main panel of the file & field information view. If you want to read existing DEF files, you can do this through the “Report” pull down in the “Import” cascade.

(c) '92 - '96 Calvin Consultancy May 1996 Page III.7 Classify WorkBench/ClassDoc Handbook Chapter IV: The change log

IV. The change log The WorkBench and ClassDoc provide a “change log facility” that will allow you to keep track of changes made to the software. The change log facility is available for a number of modules: » Packages » Files » Programs » Views » Subsystems » Zooms

The log must be maintained manually. This allows you to keep a level of detail that provides good management information. The change provides a number of fields specifically for this purpose, such as the time spend, a reason code (DAR, APAR, Change Request) and an extra field attached to a normal table you can modify to fit your own needs.

The change log can be accessed from the option pull down of each of the views for the modules the log is kept for. If you specify change log records, these will also be included in the generated source code.

There is only a single log file. In the file, we store the type of the module (package, view etc.) and the module id. You can use stand- ard query tools to output your required management reports. Since all changes are in a single file, it is easy to create (consolidated) reports on various criteria.

(c) '92 - '96 Calvin Consultancy April 1996 Page IV.1 Classify Handbook Appendix G: Index A-F

Data entry options 6.15 Index See: Data Dictionary DataFlex version D.5 Date DMY To String E.5 A Date to string E.5 Date Type E.5 AutoBack 6.15 Day E.5 Autoclear 6.15 Day number E.5 Autofind 6.15 DDO AutoReturn 6.15 See: Data Dictionary DDO setup 6.33 Default_Output D.3 B Delete 11.16 Deleting a record Batch report 4.6 See also: pDelete_File Batch server 4.6 Denpendency Batches 4.6 See also: pMay_Modify_Indirect Bitmap 7.18 Dependency 6.22 Desktop 4.7 DF-File 6.1 C Display_Subtotal 8.8 DisplayOnly 6.15 Capitalize E.3 Dynamic image 7.2 Capslock 6.15 Dynamic_Image 7.7, D.3 cBatch_Group 9.3 DYNPRESS F.3 cBitmap_Zoom 7.18 cCheckbox_Zoom 7.14 cDesktop 9.2 E cEntry_Find 7.7, 7.23 cEntry_Memo 7.16 Edit fields cEntry_Zoom 7.13 See also: cEntry_Memo cFile_Handler 6.10, 6.13 See also: cGeneral_Text_Memo cFilebuffer 11.3 Entering fields 6.7 cGeneral_Text_Memo 7.21 Entry 7.7 CL_MAIN.INI 3.11 Environment variable 8.10 Class_De.Pkg 9.1 Error Classify version D.5 See also: pError Classify.Pkg 9.1 Exiting a field 6.7 Clearing a file Exp keyword D.2 See also: mClear_File External 9.6 Close Device E.7 Extract_Field_Nr D.3 cMulti_Line_Entry 7.9, 7.23 Compose date E.5 Constraint 7.25, 8.2 F cOption_Group 7.23 cRadio_Zoom 7.15 FGet D.3 cSpecial_Multi_Line 7.11 Field display length 6.18 cSpecial_Zoom 7.19 Field entry name 6.18 cSubsystem 7.22 Field keyword D.2 cTable_Zoom 7.17 Field name 6.18 cView 7.33 Field option cView_Group 9.3 Auto prompt 6.15 cView_Panel 7.33 Infrequent field 6.15 Field options Entering 6.7 D Exiting 6.7 Field update function 6.7 Data dictionary 4.3, 6.1, 7.32 Prompt message 6.7 Data entry 4.4, 7.1 Zoom message 6.7

(c) 1992, 1993 Calvin Consultancy June 3, 1996 Page G.1 Appendix G: Index Classify Handbook I-O

Field table name 6.18 mAfter_Update_Msg 6.6, 7.28, 8.4 Field validation mAfter_Validate_Msg 11.3 See: Data Dictionary mAttach 10.7, 11.12 File buffer 7.23, 8.6 mBefore_Delete 11.16 File mode 11.17 mBefore_Save 11.13 File_Mode 6.31 mBefore_Update 11.13 FileField keyword D.2 mBefore_Update_Msg 11.3 Find operator 7.25, 8.2 mCheck_Page 8.6 FindReq 6.15 mClear_File 11.6 Forceput 6.15 mCustom_Index_Lookup 6.13 Foreign key 10.3 mCustom_Related_Lookup 6.13 Forms mFind 11.4 See: Images mGlobal_Lookup 6.11 Framework ID D.5 mInit_Object 11.5 Function key in menu 9.6 mNew_Page 8.8 Modal_Insert 6.15 Month E.5 I mRelate 10.7 mRelease_Channel 7.20 Images 7.6 - 7.7, 7.9, 7.11, 7.13 - 7.17, 7.29 mReport_Write 8.6 Indirect_File_Mode D.3 mReport_Writeln 8.6 Indirect_File_Size D.3 mRequest_Clear 11.4 INI files 3.11 mRequest_Clear_All 11.4 Intelliwrite 6.31 mRequest_Delete 11.4 Intelliwrites 11.10, 11.13 mRequest_Filemode_Dflt 11.17 Item_Changed_State 7.7 mRequest_Save 11.4 mSave 8.7 mSerNr 6.24 K mSet_Breakpoint 8.5 mSetHighVal 6.24 Key 6.3, 10.2 mSetLowVal 6.24 mSpecial_Clear 11.6 mSpecSerNr 6.24 L mStart_Intelliwrites 11.10 mSubtract_Integer 6.24 Last pos E.3 mSubtract_Number 6.24 Left justify E.3 mUpdate_Field 6.25 Left pad string E.3 Limited Table 6.16 Location 7.22 N See also: pLocation Lock 6.31, 11.17 Next_Image 7.23 No_Calc 6.15 No_Image 7.23 M NoEnter 6.15 NoPut 6.15 mAdd_Child_File 6.2 - 6.3 Normal table 6.16 See also: pDelete_Range Normal tables 7.17 mAdd_Foreign_Key_Field 6.19, 10.6 mAdd_Integer 6.24 mAdd_Item_Trigger 7.5 O mAdd_List_Field 6.17 mAdd_Number 6.24 Open 6.2 mAdd_Option 6.15 Open device E.6 mAdd_Retain_Template_Field 6.32 Options 7.7 mAdd_Trigger_Field 6.23 mAfter_Delete 11.16 mAfter_Save 11.13 mAfter_Update 11.13

Page G.2 June 3, 1996 (c) 1992, 1993 Calvin Consultancy Classify Handbook Appendix G: Index P - P

P pMay_Change_Key 6.5 pMay_Change_Parent 7.29 pAfter_Delete_Msg 7.28, 11.16 pMay_Copy 6.4 pAfter_Save_Msg 6.6, 7.28, 8.5, 11.3, 11.13 pMay_Create 6.4 pAfter_Update_Msg 6.6, 7.28, 8.4, 11.8, 11.13 pMay_Destroy_Function 7.31, 9.2 pAfter_Validate_Msg 6.5, 7.27, 8.4 pMay_Modify 6.4 Page numbers 8.11 pMay_Modify_Indirect 6.4 pAt_Top_Of_Page 8.8 pNo_Delete 6.4 pAuto_Activate 7.22 pNon_Blank 6.8 pAuto_Activate_State 7.3, 7.23, 7.26 pNumber_Of_Lines 7.9 pBefore_After_Msg 6.6, 8.5 pOk_To_Delete 11.3 pBefore_Delete_Msg 6.6, 7.28, 8.5, 11.16 pOk_To_Delete_Check 6.5, 7.27, 8.4 pBefore_Save_Msg 6.6, 7.28, 8.4, 11.3, 11.13 pOk_To_Delete_Check_Func 6.5, 7.27, 8.4 pBefore_Update_Msg 6.6, 7.28, 8.4, 11.8, 11.13 pOk_To_Delete_Range 10.6, 10.10 pBefore_Validate_Msg 6.5, 7.27, 8.4, 11.3 pOk_To_Save 11.3 pBegin_Of_Text 7.16 pOk_To_Save_Check 6.5, 7.27, 8.4, 11.12 pBlank_Or_Table 6.8 pOk_To_Save_Check_Func 6.5, 7.27, 8.4 pButton_Bar 7.3 pOutput_File 8.10 pConstraint_Msg 7.25, 8.2, 11.8 pPage_Bottom_Message 8.11 pCreate_Date_Field 6.27 pPage_Footer_Message 8.10 pCreate_Dependency 6.22, 10.11, 11.8 pPage_Header_Message 8.10 pCreate_Dynpress_Item 7.4, F.2 pPage_Number 8.11 pCreate_Dynpress_Style_Item 7.4, F.2 pPage_Title_Message 8.11 pCreate_Item F.2 pPage_Top_Message 8.11 pCreate_Time_Field 6.27 pPage_Total_Message 8.11 pData_Dictionary 7.29 pParent_Field_Value 6.11 pDefault_Value 6.18 pPost_Child_Detail_Message 8.3 pDelete_File 11.6 pPre_Child_Detail_Message 8.3 pDelete_Flag 6.27 pPrompt_Object 6.14 pDelete_Range 6.3, 10.6 pPrompt_Relation 6.21 pDemo_Limit 9.8 pRead_Only 6.4 pDemo_Version 9.8 pRedirect_Errors 7.19, 8.13 pDetail_Message 8.6 pRelate 10.8 pDisplay 10.9 pRelate_Field 10.8 pEffect 7.6, F.2 pRelate_Key 10.7 pError 6.10 pReport_Footer_Message 8.8, 8.10 pError_Handler 8.3 pReport_Header_Message 8.8, 8.10 pFalse_ID 7.14 pReport_Write_Image 8.6 pField_Buffer 6.9, 11.6 pReport_Write_Image_Wrap 8.6 pField_Information 6.18 pRequest_Channel 7.20 pField_Message 6.7 pRetain_Template 6.32 pField_Number 6.18 Program_Desktop 6.11 pField_Range 6.17 Prompt 6.11, 6.14, 6.17 pFile_Scan 11.8 Prompt message 6.7 pFiller_Image 8.11 Prompt_Object 7.7 pFind_File 11.7 Prompts pFind_Mode 7.26 See: Data Dictionary pID 7.3, 7.23 - 7.25, 7.31, 8.2, 9.5 pSave 11.13 pIndex 7.26, 8.3 pSave_File 11.6, 11.11 pKey_Nr 7.26, 8.3, 10.6 - 10.7 pSelection_Message 8.10 pLink_Parent 6.30 pSimple_Lookup 6.13 pLink_Relation 6.30 pSlave_State 11.4 pLocal_Field_Buffer 8.6 pSpecial_Proc 7.19 pLocal_Field_Value 7.26, 8.3 pStop_Intelliwrites 11.10 pLocal_Field_Values 7.23 pSubsystem 6.10 pLocation 7.3 pSync_Level 6.27 pMain_Field 7.17 - 7.18 pTable_Id 6.16, 7.17 pMain_File 6.2 - 6.3, 7.25, 8.2 pTable_Validate 6.8 pMain_Index 6.2 - 6.3, 10.2 pTrue_ID 7.14

(c) 1992, 1993 Calvin Consultancy June 3, 1996 Page G.3 Appendix G: Index Classify Handbook R-Z pUpdate_Date_Field 6.27 U pUpdate_State 6.10, 7.28, 11.13 Usage (DDO - Ini keyword) 6.33 pUpdate_Time_Field6.27 Use_Extend 6.2, 7.22, 7.24, D.4 pUse_DF_File_Relations10.2, 10.6 Use_Extend_Img 7.29, 7.32 pValidate11.13 Use_File 6.2, D.4 pVersion7.3, 7.28 User configuration pZoom_Object6.14 See also: pMay_Modify_Indirect See also: pNo_Delete See also: pRead_Only R User hooks 6.5, 7.27, 8.4

Relat ionships See also: Key V Relatio nships See also: pCreate_Dependency Field options 6.7 Relations 4.5, 7.26, 8.3 Validation of fields 6.7 Relationships 4.3, 6.19, 10.1 View panel 7.3, 7.6 See: Data Dictionary Views 7.31 See also: Dependency See also: m Add_Foreign_Key_Field See also: mAdd_Dependency W See also: mAdd_Trigger See also: pMain_Index Warning See also: pMay_Modify_Indirect See also: See also See also: pOk_To_Delete_Range Week number E.5 See also: pParent_Field_Value Relationships See also: pDelete_Range Y Release Channel E.6 Request Channel E.6 Year E.5 Required 6.15 Retain 6.15, 6.32 Right justify E.3 Z Round E.4 Zero suppress 6.15 Zoom 4.4, 6.14 S Zoom message 6.7 Zooms 7.2 Sav e See also: User hooks Save 11.12 See also: pOk_To_Save_Check_Function See also: pRead_Only See also: User hooks Saving a file See also: pSave_File Services 9.7 Skipfound 6.15 String type E.3 Subsystem 4.4

T

Temporary files 8.10 Today E.5 Transaction D.4

Page G.4 June 3, 1996 (c) 1992, 1993 Calvin Consultancy