home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-03-01 | 613.1 KB | 12,283 lines |
- %@1@%%@AB@%Microsoft QuickPascal - Pascal by Example%@EH@%%@AE@%%@NL@%
- %@NL@%
- %@NL@%
- %@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@NL@%
- %@NL@%
- %@AB@%MICROSOFT(R) QUICKPASCAL%@AE@%
- %@AB@%PASCAL BY EXAMPLE%@AE@%%@NL@%
- %@NL@%
- %@NL@%
- %@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@NL@%
- %@NL@%
- Information in this document is subject to change without notice and does
- not represent a commitment on the part of Microsoft Corporation. The
- software described in this document is furnished under a license agreement
- or nondisclosure agreement. The software may be used or copied only in
- accordance with the terms of the agreement. It is against the law to copy
- the software on any medium except as specifically allowed in the license or
- nondisclosure agreement. No part of this manual may be reproduced or
- transmitted in any form or by any means, electronic or mechanical, including
- photocopying and recording, for any purpose without the express written
- permission of Microsoft.%@NL@%
- %@NL@%
- (c)Copyright Microsoft Corporation, 1989. All rights reserved.
- Simultaneously published in the U.S. and Canada.%@NL@%
- %@NL@%
- Printed and bound in the United States of America.%@NL@%
- %@NL@%
- Microsoft, MS, MS-DOS, CodeView, GW-BASIC, QuickC, and XENIX are registered
- trademarks of Microsoft Corporation.%@NL@%
- %@NL@%
- IBM is a registered trademark of International Business Machines
- Corporation.%@NL@%
- %@NL@%
- Intel is a registered trademark of Intel Corporation.%@NL@%
- %@NL@%
- Document No. LN0114-200-R00-0689 Part No. 06792 10 9 8 7 6 5 4 3 2 1%@NL@%
- %@NL@%
- %@NL@%
- %@1@%%@AB@%Table of Contents%@AE@%%@EH@%%@NL@%
- %@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@AB@%Introduction%@BO: 3f28@%%@AE@%%@NL@%
- About This Book%@BO: 4493@%%@NL@%
- Using the Example Programs%@BO: 5185@%%@NL@%
- Key to Document Conventions%@BO: 5795@%%@NL@%
- Other Books on Pascal Programming%@BO: 6284@%%@NL@%
- Getting Assistance or Reporting Problems%@BO: 6f9c@%%@NL@%
- %@NL@%
- %@AB@%Part 1%@BO: 71ed@% Pascal Basics%@AE@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@AB@%Chapter 1%@BO: 7513@% Your First Pascal Program%@AE@%%@NL@%
- 1.1%@BO: 79e2@% Sample Pascal Program%@NL@%
- 1.2%@BO: 82df@% Parts of a Pascal Program%@NL@%
- 1.3%@BO: 9096@% Some Terms You Should Know%@NL@%
- 1.3.1%@BO: 922a@% Keywords%@NL@%
- 1.3.2%@BO: 9d71@% Identifiers%@NL@%
- 1.3.3%@BO: a769@% Constants and Variables%@NL@%
- 1.3.4%@BO: abdd@% Data Types%@NL@%
- 1.3.5%@BO: b140@% Operators and Expressions%@NL@%
- 1.4%@BO: b575@% Input and Output%@NL@%
- 1.5%@BO: bc89@% Moving On%@NL@%
- %@NL@%
- %@AB@%Chapter 2%@BO: bdde@% Programming Basics%@AE@%%@NL@%
- 2.1%@BO: c018@% Data Types%@NL@%
- 2.1.1%@BO: c379@% Integer Types%@NL@%
- 2.1.2%@BO: d12d@% Floating-Point Types%@NL@%
- 2.1.3%@BO: da04@% Character Type%@NL@%
- 2.1.4%@BO: df20@% String Types%@NL@%
- 2.1.5%@BO: ed5c@% Boolean Type%@NL@%
- 2.2%@BO: f248@% Constants%@NL@%
- 2.2.1%@BO: f483@% Simple Constants%@NL@%
- 2.2.2%@BO: ff0c@% Typed Constants%@NL@%
- 2.3%@BO: 109d4@% Simple Variables%@NL@%
- 2.4%@BO: 11422@% Pascal Operators%@NL@%
- 2.4.1%@BO: 11673@% Kinds of Operators%@NL@%
- 2.4.2%@BO: 12303@% Operator Precedence%@NL@%
- 2.5%@BO: 12f1f@% Simple Pascal Expressions%@NL@%
- 2.5.1%@BO: 13216@% Arithmetic Expressions%@NL@%
- 2.5.2%@BO: 13806@% String Expressions%@NL@%
- %@NL@%
- %@AB@%Chapter 3%@BO: 13ad7@% Procedures and Functions%@AE@%%@NL@%
- 3.1%@BO: 13e04@% Overview%@NL@%
- 3.2%@BO: 145ab@% Procedures%@NL@%
- 3.2.1%@BO: 14e12@% Calling Procedures%@NL@%
- 3.2.2%@BO: 1522e@% Declaring Procedures%@NL@%
- 3.2.3%@BO: 16069@% Declaring Local Variables%@NL@%
- 3.2.4%@BO: 16f16@% Passing Arguments%@NL@%
- 3.3%@BO: 1927a@% Functions%@NL@%
- 3.3.1%@BO: 19aaf@% Calling Functions%@NL@%
- 3.3.2%@BO: 19f8d@% Returning Values from Functions%@NL@%
- 3.3.3%@BO: 1a1ff@% Declaring Functions%@NL@%
- 3.4%@BO: 1a604@% Nested Procedures%@NL@%
- 3.5%@BO: 1b35f@% Recursion%@NL@%
- %@NL@%
- %@AB@%Chapter 4%@BO: 1beca@% Controlling Program Flow%@AE@%%@NL@%
- 4.1%@BO: 1c11f@% Relational and Boolean Operators%@NL@%
- 4.2%@BO: 1cf98@% Looping Statements%@NL@%
- 4.2.1%@BO: 1d0d3@% WHILE Loops%@NL@%
- 4.2.2%@BO: 1daa5@% REPEAT Loops%@NL@%
- 4.2.3%@BO: 1e6c8@% FOR Loops%@NL@%
- 4.3%@BO: 1f1a6@% Decision-Making Statements%@NL@%
- 4.3.1%@BO: 1f2fc@% IF Statements%@NL@%
- 4.3.2%@BO: 1f9e9@% ELSE Clauses%@NL@%
- 4.3.3%@BO: 20767@% CASE Statements%@NL@%
- %@NL@%
- %@AB@%Chapter 5%@BO: 21492@% User-Defined Data Types%@AE@%%@NL@%
- 5.1%@BO: 21a50@% Enumerated Data Types%@NL@%
- 5.1.1%@BO: 2228d@% The First Function%@NL@%
- 5.1.2%@BO: 228e4@% The Last Function%@NL@%
- 5.1.3%@BO: 22a58@% The Succ Function%@NL@%
- 5.1.4%@BO: 22f68@% The Pred Function%@NL@%
- 5.1.5%@BO: 23484@% The Inc Procedure%@NL@%
- 5.1.6%@BO: 2382a@% The Dec Procedure%@NL@%
- 5.1.7%@BO: 23bc9@% The Ord Function%@NL@%
- 5.2%@BO: 24018@% Subrange Types%@NL@%
- 5.2.1%@BO: 24a6b@% Integer Subranges%@NL@%
- 5.2.2%@BO: 253a2@% Character Subranges%@NL@%
- 5.2.3%@BO: 256fa@% Enumerated Subranges%@NL@%
- 5.3%@BO: 25a4e@% Sets%@NL@%
- 5.3.1%@BO: 261cb@% Declaring Set Types%@NL@%
- 5.3.2%@BO: 26ba8@% Assigning Set Elements to Variables%@NL@%
- 5.3.3%@BO: 26f86@% Set Operators%@NL@%
- %@NL@%
- %@AB@%Chapter 6%@BO: 29b51@% Arrays and Records%@AE@%%@NL@%
- 6.1%@BO: 2a0e9@% Arrays%@NL@%
- 6.1.1%@BO: 2a47d@% Declaring Arrays%@NL@%
- 6.1.2%@BO: 2b109@% Accessing Array Elements%@NL@%
- 6.1.3%@BO: 2be3c@% Declaring Constant Arrays%@NL@%
- 6.1.4%@BO: 2c39a@% Passing Arrays as Parameters%@NL@%
- 6.1.5%@BO: 2cd87@% Using the Debugger with Arrays%@NL@%
- 6.2%@BO: 2d29a@% Records%@NL@%
- 6.2.1%@BO: 2d6c1@% Declaring Records%@NL@%
- 6.2.2%@BO: 2e043@% Accessing Record Fields%@NL@%
- 6.2.3%@BO: 2ed4f@% Using the WITH Statement to Access Fields%@NL@%
- 6.2.4%@BO: 2f368@% Constant Records%@NL@%
- 6.2.5%@BO: 2fa5c@% Assigning Records to Record Variables%@NL@%
- 6.2.6%@BO: 2fe0f@% Using the Debugger with Records%@NL@%
- 6.3%@BO: 30028@% Variant Records%@NL@%
- 6.3.1%@BO: 30582@% Declaring Variant Records%@NL@%
- 6.3.2%@BO: 30df6@% Accessing Variant Record Fields%@NL@%
- %@NL@%
- %@AB@%Chapter 7%@BO: 31ac9@% Units%@AE@%%@NL@%
- 7.1%@BO: 31dd4@% Understanding Units%@NL@%
- 7.2%@BO: 32500@% Using Units in a Program%@NL@%
- 7.3%@BO: 32a17@% Standard QuickPascal Units%@NL@%
- 7.4%@BO: 33158@% Creating Your Own Units%@NL@%
- 7.4.1%@BO: 33318@% Writing a New Unit%@NL@%
- 7.4.2%@BO: 34a58@% Compiling a Unit%@NL@%
- 7.4.3%@BO: 35177@% Tips for Programming with Units%@NL@%
- %@NL@%
- %@AB@%Part 2%@BO: 35989@% Programming Topics%@AE@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@AB@%Chapter 8%@BO: 35d22@% The Keyboard and Screen%@AE@%%@NL@%
- 8.1%@BO: 36061@% Basic Input and Output%@NL@%
- 8.1.1%@BO: 36a44@% Read and Readln Procedures%@NL@%
- 8.1.2%@BO: 37b4e@% Write and Writeln Procedures%@NL@%
- 8.1.3%@BO: 384b0@% Formatted Output with Write and Writeln%@NL@%
- 8.1.4%@BO: 394eb@% DOS Redirection: Input and Output Files%@NL@%
- 8.2%@BO: 3a5eb@% The Crt Unit%@NL@%
- 8.2.1%@BO: 3a956@% Using the Crt Unit%@NL@%
- 8.2.2%@BO: 3cbf9@% Character Input%@NL@%
- 8.2.3%@BO: 3dc1c@% Cursor and Screen Control%@NL@%
- 8.2.4%@BO: 3e432@% Using Windows%@NL@%
- %@NL@%
- %@AB@%Chapter 9%@BO: 3efa5@% Text Files%@AE@%%@NL@%
- 9.1%@BO: 3f3c9@% Working with Text Files%@NL@%
- 9.1.1%@BO: 3f8c2@% Declaring a File Variable and File Name%@NL@%
- 9.1.2%@BO: 401de@% Opening a Text File%@NL@%
- 9.1.3%@BO: 40db1@% Writing Text to a File%@NL@%
- 9.1.4%@BO: 411c8@% Reading Text from a File%@NL@%
- 9.1.5%@BO: 41bbe@% Closing a Text File%@NL@%
- 9.2%@BO: 42062@% Increasing the Speed for Input and Output%@NL@%
- 9.3%@BO: 42ab2@% Redirecting Text Output%@NL@%
- 9.4%@BO: 43606@% Standard Procedures and Functions for Input and Output%@NL@%
- %@NL@%
- %@AB@%Chapter 10%@BO: 43fd9@% Binary Files%@AE@%%@NL@%
- 10.1%@BO: 4456a@% Typed Files%@NL@%
- 10.1.1%@BO: 449bb@% Declaring Typed Files%@NL@%
- 10.1.2%@BO: 45029@% Accessing Data in a Typed File%@NL@%
- 10.1.3%@BO: 45fb4@% Using Random Access%@NL@%
- 10.2%@BO: 46ff6@% Untyped Files%@NL@%
- %@NL@%
- %@AB@%Chapter 11%@BO: 48f3e@% Pointers and Dynamic Memory%@AE@%%@NL@%
- 11.1%@BO: 495bb@% Declaring and Accessing Pointers%@NL@%
- 11.1.1%@BO: 4978e@% Declaring Pointers%@NL@%
- 11.1.2%@BO: 49b6b@% Initializing Pointers%@NL@%
- 11.1.3%@BO: 4a2d1@% Manipulating Pointers%@NL@%
- 11.2%@BO: 4af71@% Dynamic-Memory Allocation%@NL@%
- 11.2.1%@BO: 4b365@% Allocating a Single Object%@NL@%
- 11.2.2%@BO: 4bb28@% Allocating a Memory Block%@NL@%
- 11.3%@BO: 4cd58@% Linked Lists%@NL@%
- 11.4%@BO: 4fc62@% Binary Trees%@NL@%
- %@NL@%
- %@AB@%Chapter 12%@BO: 517ed@% Advanced Topics%@AE@%%@NL@%
- 12.1%@BO: 51c30@% The Bitwise Operators%@NL@%
- 12.2%@BO: 52d18@% QuickPascal Memory Map%@NL@%
- 12.3%@BO: 548d8@% Managing the Heap%@NL@%
- 12.3.1%@BO: 55258@% Using Mark and Release to Free Memory%@NL@%
- 12.3.2%@BO: 55b90@% Determining Free Memory and Size of the Free List%@NL@%
- 12.3.3%@BO: 563da@% Preventing Deadlock with the Free List%@NL@%
- 12.3.4%@BO: 568f3@% Writing a Heap-Error Function%@NL@%
- 12.4%@BO: 5721f@% Internal Data Formats%@NL@%
- 12.4.1%@BO: 574ac@% Non-Floating-Point Data Types%@NL@%
- 12.4.2%@BO: 58bd3@% Floating-Point Data Types%@NL@%
- 12.5%@BO: 59c8d@% Linking to Assembly Language%@NL@%
- 12.5.1%@BO: 5a2af@% Setting Up a Link to Assembly Language%@NL@%
- 12.5.2%@BO: 5a798@% Segment and Data Conventions%@NL@%
- 12.5.3%@BO: 5ad07@% Entering the Procedure%@NL@%
- 12.5.4%@BO: 5b2ab@% Accessing Parameters%@NL@%
- 12.5.5%@BO: 5c7bc@% Returning a Value%@NL@%
- 12.5.6%@BO: 5ccd5@% Exiting the Procedure%@NL@%
- 12.5.7%@BO: 5cf03@% A Complete Example%@NL@%
- %@NL@%
- %@AB@%Part 3%@BO: 5d7d0@% Graphics and Objects%@AE@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@AB@%Chapter 13%@BO: 5dac7@% Using Graphics%@AE@%%@NL@%
- 13.1%@BO: 5e065@% Getting Started with Graphics%@NL@%
- 13.1.1%@BO: 5e1f2@% Graphics Terms%@NL@%
- 13.1.2%@BO: 5e8fb@% For More Information%@NL@%
- 13.2%@BO: 5eefe@% Writing Your First Graphics Program%@NL@%
- 13.3%@BO: 63072@% Using Video Modes%@NL@%
- 13.3.1%@BO: 63cb8@% Selecting a Video Mode%@NL@%
- 13.3.2%@BO: 6586d@% CGA Color Graphics Modes%@NL@%
- 13.3.3%@BO: 66a86@% EGA, MCGA, and VGA Palettes%@NL@%
- 13.3.4%@BO: 675cb@% EGA Color Graphics Modes%@NL@%
- 13.3.5%@BO: 68574@% VGA Color Graphics Modes%@NL@%
- 13.3.6%@BO: 697e7@% Using the Color Video Text Modes%@NL@%
- 13.4%@BO: 6ac8a@% Understanding Coordinate Systems%@NL@%
- 13.4.1%@BO: 6afe1@% Text Coordinates%@NL@%
- 13.4.2%@BO: 6b49b@% Physical Screen Coordinates%@NL@%
- 13.4.3%@BO: 6c75c@% Viewport Coordinates%@NL@%
- 13.4.4%@BO: 6ca35@% Real Coordinates in a Window%@NL@%
- 13.5%@BO: 717c6@% Animation%@NL@%
- 13.5.1%@BO: 71b98@% Video-Page Animation%@NL@%
- 13.5.2%@BO: 734df@% Bit-Mapped Animation%@NL@%
- %@NL@%
- %@AB@%Chapter 14%@BO: 76456@% Using Fonts%@AE@%%@NL@%
- 14.1%@BO: 7682b@% Overview of QuickPascal Fonts%@NL@%
- 14.2%@BO: 7768c@% Using Fonts in QuickPascal%@NL@%
- 14.2.1%@BO: 77ccb@% Registering Fonts%@NL@%
- 14.2.2%@BO: 783ef@% Setting the Current Font%@NL@%
- 14.2.3%@BO: 7a3e5@% Displaying Text Using the Current Font%@NL@%
- 14.3%@BO: 7a7dd@% A Few Hints on Using Fonts%@NL@%
- 14.4%@BO: 7b054@% Example Program%@NL@%
- %@NL@%
- %@AB@%Chapter 15%@BO: 7c122@% Object-Oriented Programming%@AE@%%@NL@%
- 15.1%@BO: 7c365@% Overview%@NL@%
- 15.2%@BO: 7cd69@% Object Programming Concepts%@NL@%
- 15.3%@BO: 7d4fb@% Using Objects%@NL@%
- 15.3.1%@BO: 7d6e2@% Setting the Method Compiler Directive%@NL@%
- 15.3.2%@BO: 7d93f@% Creating Classes%@NL@%
- 15.3.3%@BO: 7e4cd@% Creating Subclasses%@NL@%
- 15.3.4%@BO: 7ee55@% Defining Methods%@NL@%
- 15.3.5%@BO: 7f80c@% Using INHERITED%@NL@%
- 15.3.6%@BO: 7fcc6@% Declaring Objects%@NL@%
- 15.3.7%@BO: 7ff59@% Allocating Memory%@NL@%
- 15.3.8%@BO: 80182@% Calling Methods%@NL@%
- 15.3.9%@BO: 8047c@% Testing Membership%@NL@%
- 15.3.10%@BO: 80673@% Disposing of Objects%@NL@%
- 15.4%@BO: 808ff@% Object Programming Strategies%@NL@%
- 15.4.1%@BO: 80b96@% Object Style Conventions%@NL@%
- 15.4.2%@BO: 811ab@% Object Reusability%@NL@%
- 15.4.3%@BO: 81412@% Modularity%@NL@%
- 15.4.4%@BO: 815a6@% Methods%@NL@%
- 15.4.5%@BO: 81792@% Data Fields%@NL@%
- 15.5%@BO: 8198a@% Example Program%@NL@%
- %@NL@%
- %@AB@%Appendixes%@AE@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@AB@%Appendix A ASCII Character Codes and Extended Key Codes%@BO: 829c0@%%@AE@%%@NL@%
- A.1%@BO: 82a85@% ASCII Character Codes%@NL@%
- A.2%@BO: 84573@% Extended-Key Codes%@NL@%
- %@NL@%
- %@AB@%Appendix B Compiler Directives%@BO: 857d9@%%@AE@%%@NL@%
- B.1%@BO: 85aff@% Switch Directives%@NL@%
- B.2%@BO: 87cb0@% Parameter Directives%@NL@%
- B.3%@BO: 8865e@% Conditional Directives%@NL@%
- %@NL@%
- %@AB@%Appendix C Summary of Standard Units%@BO: 8964c@%%@AE@%%@NL@%
- %@NL@%
- %@AB@%Appendix D Quick Reference Guide%@BO: 8a285@%%@AE@%%@NL@%
- D.1%@BO: 8a333@% Keywords, Procedures, and Functions%@NL@%
- D.2%@BO: 91a8b@% Crt Procedures and Functions%@NL@%
- D.3%@BO: 925b1@% Dos Procedures and Functions%@NL@%
- D.4%@BO: 93c84@% Printer Unit Interface%@NL@%
- D.5%@BO: 93ebf@% MSGraph Procedures and Functions%@NL@%
- %@NL@%
- %@AB@%Tables%@AE@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- Table 2.1%@BO: c523@% Integer Data Types%@NL@%
- Table 2.2%@BO: d3d7@% Floating-Point Data Types%@NL@%
- Table 2.3%@BO: 11a7d@% Arithmetic Operators%@NL@%
- Table 2.4%@BO: 11ea9@% Relational Operators%@NL@%
- Table 2.5%@BO: 12531@% Operator Precedence%@NL@%
- Table 4.1%@BO: 1c848@% Relational Operators%@NL@%
- Table 4.2%@BO: 1caf6@% Boolean Operators%@NL@%
- Table 5.1%@BO: 273ef@% Relational Operators%@NL@%
- Table 8.1%@BO: 3abde@% Crt Text-Mode Constants%@NL@%
- Table 8.2%@BO: 3afb0@% Crt Color Constants%@NL@%
- Table 8.3%@BO: 3b42e@% Variables Provided by the Crt Unit%@NL@%
- Table 8.4%@BO: 3bfd0@% Procedures and Functions Provided by the Crt Unit%@NL@%
- Table 8.6%@BO: 3e005@% Statement Effects%@NL@%
- Table 9.1%@BO: 43776@% Standard Procedures and Functions for All File Types%@NL@%
- Table 9.2%@BO: 43bda@% Standard Procedures and Functions for Text Files%@NL@%
- Table 11.1%@BO: 4c9f4@% Pointer Procedures%@NL@%
- Table 13.1%@BO: 60246@% Constants Set by _SetVideoMode%@NL@%
- Table 13.2%@BO: 636da@% Constants for Graphics Adapters%@NL@%
- Table 13.3%@BO: 63a63@% Constants for Monitors%@NL@%
- Table 13.4%@BO: 65aa1@% Available CGA Colors%@NL@%
- Table 13.5%@BO: 65e9f@% CGA Colors: _MResNoColor Mode%@NL@%
- Table 13.6%@BO: 6a0ff@% Text Colors%@NL@%
- Table 14.1%@BO: 7735c@% Typefaces and Type Sizes in QuickPascal%@NL@%
- Table B.1%@BO: 884e4@% Minimum and Maximum Memory Allocation Parameters%@NL@%
- Table B.2%@BO: 88b7f@% QuickPascal Predefined Conditional Identifiers%@NL@%
- %@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP00000@%%@1@%%@AB@%Introduction%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQP00001@%%@4@%Congratulations on your purchase of Microsoft(R) QuickPascal. By now you%@EH@%
- should have read the other book in this package, %@AI@%Up and Running%@AE@%, and
- installed the software. And you're getting a feel for the many features of
- the product and the power that QuickPascal places at your fingertips. Now
- you're ready to use that power as you learn how to program in Pascal.
- QuickPascal makes learning easy with%@NL@%
- %@NL@%
- %@CR:MQP00002@% ■ An integrated programming environment. You can write and edit code with%@NL@%
- the built-in editor, and then compile, run, and save your programs with%@NL@%
- easy-to-use menus.%@NL@%
- %@NL@%
- ■ A powerful on-line help system, the QuickPascal Advisor. By pressing%@NL@%
- one key, the F1 key, you can access everything you need to know about%@NL@%
- the QuickPascal environment and about the Pascal language itself.%@NL@%
- %@NL@%
- ■ An excellent debugger. You can find out exactly where a syntax error%@NL@%
- occurred, or trace through a program to find errors in logic.%@NL@%
- %@NL@%
- ■ Object-oriented extensions. You can use QuickPascal to learn and use%@NL@%
- the newest concept in programming: object-oriented programming.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP01000@%%@2@%%@AB@%About This Book%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP01001@%%@4@%This book, %@AI@%Pascal by Example%@AE@%, complements the on-line features of%@EH@%
- QuickPascal to teach you how to program in this language. In discussing
- programming terms and processes, this book refers frequently to example
- programs that are located on-line. Fragments of the example code are often
- quoted in text, thus teaching you as you read along. You can also load the
- whole example, so you can compile and experiment with working code.%@NL@%
- %@NL@%
- %@CR:MQP01002@%%@4@%As you read the book and run the example programs, you'll learn about these%@EH@%
- QuickPascal programming features:%@NL@%
- %@NL@%
- %@CR:MQP01003@% ■ Programming basics such as variables, operators, and expressions%@NL@%
- %@NL@%
- ■ Specific programming features such as strings, loops, units,%@NL@%
- procedures, data types, and input/output%@NL@%
- %@NL@%
- ■ Powerful graphics capabilities and object-oriented programming%@NL@%
- %@NL@%
- %@CR:MQP01004@%%@4@%%@AI@%Pascal by Example%@AE@% makes certain assumptions about your knowledge. It does%@EH@%
- not explain programming concepts and terms in their simplest form. This book
- assumes you have programmed in other programming languages but are not
- familiar with Pascal. The following list summarizes the book's contents:%@NL@%
- %@NL@%
- %@CR:MQP01005@% ■ Part 1, "Pascal Basics," covers basic Pascal language fundamentals such%@NL@%
- as procedures and data types. These chapters are designed to be read in%@NL@%
- order, from beginning to end.%@NL@%
- %@NL@%
- ■ Part 2, "Programming Topics," covers practical programming topics such%@NL@%
- as using pointers and files. An advanced topics chapter discusses%@NL@%
- bitwise operators, calling assembly language routines, and similar%@NL@%
- problems.%@NL@%
- %@NL@%
- ■ Part 3, "Graphics and Objects," covers QuickPascal graphics, which%@NL@%
- include graphics primitives and font support. The final chapter%@NL@%
- introduces you to the object extensions in QuickPascal. If you've never%@NL@%
- seen object-oriented programming before, this will get you started.%@NL@%
- %@NL@%
- ■ Appendix A%@BO: 829c0@%, "ASCII Character Codes and Extended Key Codes," provides%@NL@%
- valuable reference information on ASCII codes and the extended key%@NL@%
- codes returned by the %@AB@%Crt%@AE@% unit function %@AB@%ReadKey%@AE@%.%@NL@%
- %@NL@%
- ■ Appendix B%@BO: 857d9@%, "Compiler Directives," lists all QuickPascal directives.%@NL@%
- %@NL@%
- ■ Appendix C%@BO: 8964c@%, "Summary of Standard Units," briefly describes each unit%@NL@%
- provided with QuickPascal.%@NL@%
- %@NL@%
- ■ Appendix D%@BO: 8a285@%, "Quick Reference Guide," lists all QuickPascal keywords and%@NL@%
- the standard units' procedures and functions.%@NL@%
- %@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@AI@%NOTE%@AE@%%@NL@%
- Microsoft documentation uses the term "DOS" to refer to both the%@NL@%
- MS-DOS(R) and IBM Personal Computer DOS operating systems. The name of a%@NL@%
- specific operating system is used when it is necessary to note features%@NL@%
- that are unique to that system.%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP02000@%%@2@%%@AB@%Using the Example Programs%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP02001@%%@4@%The QuickPascal Advisor includes all of the significant program examples in%@EH@%
- this book (although it doesn't include all of the code fragments). This
- feature allows you to load, run, and experiment with example programs as you
- read.%@NL@%
- %@NL@%
- %@CR:MQP02002@%%@4@%Every complete program in this book starts with a comment of this general%@EH@%
- form:%@NL@%
- %@NL@%
- %@AS@% { %FTOC.PAS: converts temperatures }%@NL@%
- %@NL@%
- %@CR:MQP02003@%%@4@%The comment contains the program's name and a brief description of what it%@EH@%
- does. This program can be found in the QP Advisor as FTOC.PAS.%@NL@%
- %@NL@%
- %@CR:MQP02004@%%@4@%You must be using the QuickPascal environment to load an example. To load%@EH@%
- the example program, open the Help menu and choose the Contents command.
- Choose the title of this book from within the Contents screen. Then find the
- desired program in the list of %@AI@%Pascal by Example%@AE@% programs, and copy it into
- the source window using the Copy and Paste commands from the Edit menu.%@NL@%
- %@NL@%
- %@CR:MQP02005@%%@4@%After you copy an example program into the QuickPascal source window, treat%@EH@%
- it as you would any Pascal source program. You can compile or edit the
- program, save it on disk, and so on.%@NL@%
- %@NL@%
- %@CR:MQP02006@%%@4@%Note that you can easily print out an example program, in whole or in part,%@EH@%
- from Help or from your file, by choosing the Print command from the File
- menu.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP03000@%%@2@%%@AB@%Key to Document Conventions%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP03001@%%@4@%This book uses the following document conventions:%@EH@%%@NL@%
- %@NL@%%@NL@%
- %@TH: 48 2568 2 23 53 @%
- %@AB@%Example%@AE@% %@AB@%Description%@AE@%
- ────────────────────────────────────────────────────────────────────────────
- COPY TEST.OBJ C: UPPERCASE type represents DOS commands and filenames.
- %@NL@%
- %@AB@%BEGIN%@AE@% Boldface type (whether in all uppercase or in both
- upper- and lowercase letters) indicates standard
- features of the QuickPascal language: keywords,
- operators, and standard procdures and functions.
- %@NL@%
- %@AS@%PROGRAM FtoC%@AE@% This typeface is used for example programs, program
- %@AS@%CONST%@AE@% fragments, and the names of user-defined procedures,
- %@AS@% Factor = 32.0%@AE@% functions and variables. It also indicates user input
- and screen output.
- %@NL@%
- %@AI@%ArrayName%@AE@% Words in italics indicate placeholders for
- information that you must supply. A file name is an
- example of this kind of information.
- %@NL@%
- «%@AI@%Option%@AE@%» Items inside chevrons are optional.
- %@NL@%
- {%@AI@%Choice1%@AE@% | %@AI@%Choice2%@AE@%} Braces and a vertical bar indicate a choice among two
- or more items. You must choose one of the items
- unless all of the items are also enclosed in
- chevrons.
- %@NL@%
- Repeating elements... Three dots following an item indicate that more items
- having the same form may be entered.
- %@NL@%
- %@AS@%REPEAT%@AE@% A column of three dots indicates that part of the
- %@AS@%.%@AE@% example program has intentionally been omitted.
- %@AS@%.%@AE@%
- %@AS@%.%@AE@%
- %@AS@%UNTIL%@AE@%
- %@NL@%
- F1 Small capital letters denote names of keys on the
- keyboard. A plus (+) indicates a combination of keys.
- For example, SHIFT+F5 tells you to hold down the
- SHIFT key while pressing the F5 key.
- %@NL@%
- "array pointer" The first time a new term is defined, it is enclosed
- in quotation marks. Since some knowledge of
- programming is assumed, common terms such as memory
- or branch are not defined.
- %@NL@%
- American National An acronym is spelled out the first time it appears.
- Standards Institute
- (ANSI)
- ────────────────────────────────────────────────────────────────────────────%@NL@%
- %@TE: 48 2568 2 23 53 @%
- %@NL@%
- %@CR:MQP03002@%
- %@NL@%
- %@CR:MQP04000@%%@2@%%@AB@%Other Books on Pascal Programming%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP04001@%%@4@%This book introduces the Pascal language and some practical programming%@EH@%
- topics. It does not attempt to teach you basic computer programming or
- advanced Pascal programming techniques. The following books cover a variety
- of topics that you may find useful. They are listed only for your
- convenience. With the exception of its own publications, Microsoft does not
- endorse these books or recommend them over others on the same subject.%@NL@%
- %@NL@%
- %@CR:MQP04002@%Cooper, Doug. %@AI@%Standard Pascal: User Reference Manual%@AE@%. New York, NY: W.W.
- Norton & Company, 1983.%@NL@%
- %@NL@%
- ■ A complete and concise reference manual to standard Pascal.%@NL@%
- %@NL@%
- Cooper, Doug and Michael Clancy. %@AI@%Oh! Pascal!%@AE@% 2d ed. New York, NY: W. W.
- Norton & Company, 1985.%@NL@%
- %@NL@%
- ■ A beginner's introduction to standard Pascal.%@NL@%
- %@NL@%
- Craig, John Clark. %@AI@%Microsoft QuickPascal Programmer's%@AE@% %@AI@%Toolbox.%@AE@% Redmond, WA:
- Microsoft Press. In press.%@NL@%
- %@NL@%
- ■ A sourcebook that beginners will find useful for learning by example.%@NL@%
- Seasoned professionals using QuickPascal as a development system will%@NL@%
- find the routines to be valuable and immediately useful extensions to%@NL@%
- the Pascal language.%@NL@%
- %@NL@%
- Grogono, Peter. %@AI@%Programming in Pascal.%@AE@% rev. ed. Menlo Park, CA:
- Addison-Wesley, 1980.%@NL@%
- %@NL@%
- ■ A good teaching source, but one that also covers sophisticated topics.%@NL@%
- %@NL@%
- Jamsa, Kris. %@AI@%Microsoft QuickPascal Programming.%@AE@% Redmond, WA: Microsoft
- Press. In press.%@NL@%
- %@NL@%
- ■ A comprehensive introduction to mastering QuickPascal programming for%@NL@%
- the beginning- to intermediate- level programmer complete with hands-on%@NL@%
- examples.%@NL@%
- %@NL@%
- Jamsa, Kris. %@AI@%Microsoft QuickPascal: Programmer's Quick Reference.%@AE@% Redmond,
- WA: Microsoft Press. In press.%@NL@%
- %@NL@%
- ■ This alphabetical reference provides concise descriptions of all%@NL@%
- QuickPascal procedures and functions.%@NL@%
- %@NL@%
- Kernighan, Brian W., and P.J. Plauger. %@AI@%Software Tools%@AE@% %@AI@%in Pascal%@AE@%. Menlo Park,
- CA: Addison-Wesley, 1981.%@NL@%
- %@NL@%
- ■ A beginning- to intermediate-level guide to software tools and%@NL@%
- programming techniques.%@NL@%
- %@NL@%
- Ladd, Robert Scott. %@AI@%Learning Object-Oriented Programming%@AE@% %@AI@%with Microsoft%@AE@%
- %@AI@%QuickPascal.%@AE@% Redmond, WA: Microsoft Press. In press.%@NL@%
- %@NL@%
- ■ Provides an example-rich introduction to the philosophy and procedures%@NL@%
- of object-oriented programming for the beginning- to intermediate-level%@NL@%
- QuickPascal user.%@NL@%
- %@NL@%
- Leestma, Sanford, and Larry Nyhoff. %@AI@%Pascal: Programming%@AE@% %@AI@%and Problem%@AE@% %@AI@%Solving%@AE@%.
- New York, NY: Macmillan Publishing Company, 1987.%@NL@%
- %@NL@%
- ■ A beginner's guide to Pascal programming. The book also covers problem%@NL@%
- analysis, algorithm development, algorithm translation to Pascal, and%@NL@%
- program validation.%@NL@%
- %@NL@%
- Wirth, Niklaus, and Kathleen Jensen. %@AI@%Pascal User Manual%@AE@% %@AI@%and Report.%@AE@% 3d ed.
- New York, NY: Springer-Verlag, 1985.%@NL@%
- %@NL@%
- ■ The definitive source.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP05000@%%@2@%%@AB@%Getting Assistance or Reporting Problems%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP05001@%%@4@%If you feel you have discovered a problem in the software, please report the%@EH@%
- problem using the Product Assistance Request form at the back of this book.%@NL@%
- %@NL@%
- %@CR:MQP05002@%%@4@%If you have comments or suggestions reqarding any of the books accompanying%@EH@%
- this product, please use the Documentation Feedback Card, also at the back
- of this book.%@NL@%
- %@NL@%
- %@CR:MQP05003@%
- %@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@CR:MQPP1000@%%@1@%%@AB@%Part 1 Pascal Basics%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPP1004@%%@4@%Part 1 of %@AI@%Pascal by Example%@AE@% introduces you to the Pascal programming%@EH@%
- language and the basic elements of Pascal programs. The chapters in this
- part assume that you know some programming concepts but are not familiar
- with Pascal. Experienced Pascal programmers may want to skim these chapters.%@NL@%
- %@NL@%
- %@CR:MQPP1005@%%@4@%The information in Part 1 helps you start writing Pascal programs%@EH@%
- immediately. Chapters progress through such major topics as procedures,
- program flow, user-defined data types, and units. If you're new to Pascal,
- reading the chapters in this part sequentially will give you a thorough
- introduction to the fundamentals of programming in Pascal.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP10000@%%@1@%%@AB@%Chapter 1 Your First Pascal Program%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQP10001@%%@4@%You're probably eager to use QuickPascal and begin writing programs in%@EH@%
- Pascal. In this chapter, you'll compile and run your first Pascal program,
- FTOC.PAS, which is shown in Figure 1.1%@BO: 7b6b@%. As with all of the complete
- programs in this book, we've done the work of typing it in for you. You
- just need to use the Copy and Paste commands on the Edit menu to copy the
- program from the QuickPascal Advisor into a blank source window. Then you
- can press F5 to compile and run the program.%@NL@%
- %@NL@%
- %@CR:MQP10002@%%@4@%This chapter uses the sample program to introduce the parts of a Pascal%@EH@%
- program, some terms you should know, and input and output. Most of these
- terms are discussed in more detail in Chapter 2%@BO: bdde@%.%@NL@%
- %@NL@%
- %@CR:MQP10003@%%@4@%If you're an experienced programmer in another structured language such as%@EH@%
- C, you might want to skip this chapter and begin with Chapter 2%@BO: bdde@%,
- "Programming Basics," or Chapter 3%@BO: 13ad7@%, "Procedures and Functions."%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP11000@%%@2@%%@AB@%1.1 Sample Pascal Program%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP11001@%%@4@%FTOC.PAS is a simple program that converts temperatures from Fahrenheit to%@EH@%
- Celsius. Like all of the sample programs in this book, you'll find it in the
- QuickPascal Advisor. Figure 1.1%@BO: 7b6b@% contains the FTOC.PAS program code and
- illustrates the program parts.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPf0101@%%@4@%%@AB@%Figure 1.1 Parts of a Pascal Program%@AE@%%@EH@%%@NL@%
- %@AB@%┌─────%@AE@%
- %@FN@%
- Program declaration%@EF@%%@AB@%│%@AE@% %@AS@%PROGRAM FtoC;%@AE@%
- %@FN@%
- Comment%@EF@%%@AB@%│%@AE@% %@AS@%{ FTOC.PAS: converts temperatures }
- %@AB@%│%@AE@%
- %@FN@%
- Uses statement%@EF@%%@AB@%│%@AE@% %@AS@%USES%@AE@%
- %@AB@%│%@AE@% %@AS@%Crt;%@AE@%
- %@AB@%│%@AE@%
- %@AB@%Declara- │%@AE@% %@AS@%CONST%@AE@%
- %@AB@%tions │%@AE@% %@AS@%factor = 32.0;%@AE@%
- %@AB@%│%@AE@%
- %@AB@%│%@AE@% %@AS@%VAR%@AE@%
- %@FN@%
- Variable declaration%@EF@%%@AB@%│%@AE@% %@AS@%degrees_fahr, degrees_cel, answer : Real;%@AE@%
- %@AB@%│%@AE@%
- %@FN@%
- Function declaration%@EF@%%@AB@%│%@AE@% %@AS@%FUNCTION ConvertToCel( degrees : Real ) : Real;%@AE@%
- %@AB@%│%@AE@% %@AS@%BEGIN%@AE@%
- %@AB@%│%@AE@% %@AS@%ConvertToCel := ((degrees - factor) * 5.0) / 9.0;%@AE@%
- %@AB@%│%@AE@% %@AS@%END;%@AE@%
- %@AB@%└─────%@AE@%
- %@AB@%┌─────%@AE@%
- %@AB@%│%@AE@% %@AS@%BEGIN%@AE@%
- %@AB@%│%@AE@% %@AS@%ClrScr;%@AE@%
- %@AB@%│%@AE@% %@AS@%Writeln( 'Temperature Converter' );%@AE@%
- %@AB@%│%@AE@% %@AS@%Writeln( 'Fahrenheit to Celsius' );%@AE@%
- %@AB@%Main │%@AE@% %@AS@%Writeln;%@AE@%
- %@AB@%Program │%@AE@% %@AS@%Write( 'Temperature in degrees Fahrenheit? ' );%@AE@%
- %@AB@%│%@AE@% %@AS@%Readln( degrees_fahr );%@AE@%
- %@AB@%│%@AE@% %@AS@%degrees_cel := ConvertToCel( degrees_fahr );%@AE@%
- %@AB@%│%@AE@% %@AS@%Writeln( 'Equals ', degrees_cel:4:1, ' degrees Celsius' );%@AE@%
- %@AB@%│%@AE@% %@AS@%Writeln;
- %@AB@%│%@AE@% %@AS@%END.
- %@AB@%└─────%@AE@%
- %@NL@%
- %@NL@%
- %@CR:MQP12000@%%@2@%%@AB@%1.2 Parts of a Pascal Program%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP12001@%%@4@%Pascal is a highly structured language. Programs have parts, and the parts%@EH@%
- have a required order. This section explains the parts of a Pascal program.%@NL@%
- %@NL@%
- %@CR:MQP12010@%%@4@%%@AB@%The Program Declaration%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP12011@%%@CR:MQP12012@%%@4@%Traditionally, the first line of every Pascal program contains the program%@EH@%
- declaration. This declaration consists of the keyword %@AB@%PROGRAM%@AE@%, the name of
- the program, and a semicolon. With Microsoft QuickPascal, such a declaration
- is not required, but it is still helpful as a way of labeling a program.
- Also, a program declaration is necessary if you want your program to compile
- on compilers other than those developed by Microsoft.%@NL@%
- %@NL@%
- %@CR:MQP12020@%%@4@%%@AB@%The USES Statement%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP12021@%%@4@%The %@AB@%USES%@AE@% statement always follows the program declaration. It specifies%@EH@%
- which units are called from the program. Units are explained in detail in
- Chapter 7%@BO: 31ac9@%.%@NL@%
- %@NL@%
- %@CR:MQP12022@%%@4@%The %@AB@%USES%@AE@% statement in the FTOC.PAS program calls the %@AB@%Crt%@AE@% unit. This unit%@EH@%
- contains procedures and functions that allow you to control your computer
- screen.%@NL@%
- %@NL@%
- %@CR:MQP12030@%%@4@%%@AB@%Constant and Variable Declarations%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP12031@%%@4@%Pascal requires that you declare constants, types, and variables before%@EH@%
- using them. The keywords %@AB@%CONST%@AE@%, %@AB@%TYPE%@AE@%, and %@AB@%VAR%@AE@% are used for this purpose.
- Constant declarations are made with the %@AB@%CONST%@AE@% keyword and include both the
- constant identifier (a name) and its value. For example, the constant shown
- in the FTOC.PAS program is named %@AS@%factor%@AE@% and has the value %@AS@%32.0%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQP12032@%%@4@%The %@AB@%VAR%@AE@% keyword is used for variable declarations. Variable declarations%@EH@%
- include the variable identifier (a name) and its type. Multiple variables of
- the same type can be declared in the same statement.%@NL@%
- %@NL@%
- %@CR:MQP12040@%%@4@%%@AB@%Procedures and Functions%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP12041@%%@4@%Procedure and function declarations come after the constant and variable%@EH@%
- declarations. Each procedure or function has its own %@AB@%BEGIN...END%@AE@% block.
- FTOC.PAS uses the function %@AS@%converttocel%@AE@% to convert the temperature from
- Fahrenheit to Celsius.%@NL@%
- %@NL@%
- %@CR:MQP12050@%%@4@%%@AB@%The Program Body%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP12051@%%@4@%The body of the program, as shown in Figure 1.1%@BO: 7b6b@%, is enclosed by the keywords%@EH@%
- %@AB@%BEGIN%@AE@% and %@AB@%END%@AE@%. Pascal executes the instructions between %@AB@%BEGIN%@AE@% and %@AB@%END%@AE@%. The
- period after the %@AB@%END%@AE@% keyword tells Pascal that the program is over; anything
- that follows the period is ignored.%@NL@%
- %@NL@%
- %@CR:MQP12060@%%@4@%%@AB@%Comments%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP12061@%%@4@%Comments are notes to yourself or others that make your programs easier to%@EH@%
- understand and maintain. Braces tell QuickPascal to ignore comment text.
- Instead of braces, comments can also be enclosed in parentheses and
- asterisks, as shown in this example:%@NL@%
- %@NL@%
- %@AS@% (* This is a comment between the special symbols *)%@NL@%
- %@NL@%
- %@CR:MQP12062@%%@4@%The text on line 2 of FTOC.PAS is a comment.%@EH@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP13000@%%@2@%%@AB@%1.3 Some Terms You Should Know%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP13001@%%@4@%If you've never programmed before, the terms "keyword" and "identifier" may%@EH@%
- be confusing to you. These and other terms are discussed in this section. If
- you are an experienced programmer, you can skip this section and go on to
- Chapter 2%@BO: bdde@%, "Programming Basics."%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP13100@%%@3@%%@AB@%1.3.1 Keywords%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP13101@%%@4@%Pascal contains a set of "keywords," or words that it reserves for its own%@EH@%
- use. Whenever the Pascal compiler encounters a keyword, a specific action is
- performed. In the sample program FTOC.PAS, the words %@AB@%PROGRAM%@AE@%, %@AB@%VAR%@AE@%, %@AB@%BEGIN%@AE@%,
- and %@AB@%END%@AE@% are all keywords. A keyword always means the same thing to a
- program; for example, the keyword %@AB@%BEGIN%@AE@% always signals the beginning of a
- statement block, and the keyword %@AB@%END%@AE@% always signals the end of a statement
- block.%@NL@%
- %@NL@%
- %@CR:MQP13102@%%@4@%The QuickPascal environment gives you the option of displaying keywords in a%@EH@%
- special color. This makes your programs easier to read on screen. See %@AI@%Up and%@AE@%
- %@AI@%Running%@AE@% for more information on how to display in color.%@NL@%
- %@NL@%
- %@CR:MQP13103@%%@4@%Always remember that you cannot use a keyword as a variable name or for%@EH@%
- anything other than its intended purpose. Keywords are shown in all
- uppercase letters in this book, and in the sample programs. A list of
- QuickPascal keywords is shown below:%@NL@%
- %@NL@%
- %@CR:MQP13104@% %@AB@%ABSOLUTE%@AE@% %@AB@%IF%@AE@% %@AB@%RECORD%@AE@%%@NL@%
- %@AB@%AND%@AE@% %@AB@%IMPLEMENTATION%@AE@% %@AB@%REPEAT%@AE@%%@NL@%
- %@AB@%ARRAY%@AE@% %@AB@%IN%@AE@% %@AB@%SET%@AE@%%@NL@%
- %@AB@%BEGIN%@AE@% %@AB@%INHERITED%@AE@% %@AB@%SHL%@AE@%%@NL@%
- %@AB@%CASE%@AE@% %@AB@%INLINE%@AE@% %@AB@%SHR%@AE@%%@NL@%
- %@AB@%CONST%@AE@% %@AB@%INTERFACE%@AE@% %@AB@%STRING%@AE@%%@NL@%
- %@AB@%CSTRING%@AE@% %@AB@%INTERRUPT%@AE@% %@AB@%THEN%@AE@%%@NL@%
- %@AB@%DIV%@AE@% %@AB@%LABEL%@AE@% %@AB@%TO%@AE@%%@NL@%
- %@AB@%DO%@AE@% %@AB@%MOD%@AE@% %@AB@%TYPE%@AE@%%@NL@%
- %@AB@%DOWNTO%@AE@% %@AB@%NIL%@AE@% %@AB@%UNIT%@AE@%%@NL@%
- %@AB@%ELSE%@AE@% %@AB@%NOT%@AE@% %@AB@%UNTIL%@AE@%%@NL@%
- %@AB@%END%@AE@% %@AB@%OBJECT%@AE@% %@AB@%USES%@AE@%%@NL@%
- %@AB@%EXTERNAL%@AE@% %@AB@%OF%@AE@% %@AB@%VAR%@AE@%%@NL@%
- %@AB@%FILE%@AE@% %@AB@%OR%@AE@% %@AB@%WHILE%@AE@%%@NL@%
- %@AB@%FOR%@AE@% %@AB@%OVERRIDE%@AE@% %@AB@%WITH%@AE@%%@NL@%
- %@AB@%FORWARD%@AE@% %@AB@%PACKED%@AE@% %@AB@%XOR%@AE@%%@NL@%
- %@AB@%FUNCTION%@AE@% %@AB@%PROCEDURE%@AE@%%@NL@%
- %@AB@%GOTO%@AE@% %@AB@%PROGRAM%@AE@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP13200@%%@3@%%@AB@%1.3.2 Identifiers%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP13201@%%@4@%"Identifiers" are names that you use in your program. In the example%@EH@%
- program, the word %@AS@%degrees_cel%@AE@% is the identifier for a variable. You could
- call it %@AS@%celsiusdegrees%@AE@% or %@AS@%cd%@AE@% or %@AS@%fred%@AE@% if you wanted to; however, for the sake
- of good programming practice, the name should provide information about the
- purpose of the variable. Thus %@AS@%degrees_cel%@AE@% is preferable to %@AS@%cd%@AE@% or %@AS@%fred%@AE@%.
- QuickPascal requires that you follow three rules when creating identifiers:%@NL@%
- %@NL@%
- %@CR:MQP13202@% 1. The first character of an identifier must be a letter or underscore%@NL@%
- character (_).%@NL@%
- %@NL@%
- 2. Digits can be used within an identifier.%@NL@%
- %@NL@%
- 3. Identifier names can be of any length, but only the first 63 characters%@NL@%
- are significant.%@NL@%
- %@NL@%
- %@CR:MQP13203@%%@4@%Thus, the following are examples of valid identifiers:%@EH@%%@NL@%
- %@NL@%
- %@AS@%FirstTime%@AE@%%@NL@%
- %@AS@%first_time%@AE@%%@NL@%
- %@AS@%index0%@AE@%%@NL@%
- %@AS@%area233%@AE@%%@NL@%
- %@AS@%area_555%@AE@%%@NL@%
- %@AS@%A4_9RT4_98NNS%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP13204@%%@4@%By contrast, the following are examples of invalid identifiers:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP13205@% %@AB@%Identifier Reason It's Invalid%@AE@%%@NL@%
- %@NL@%
- %@AS@%First Time%@AE@% There is a space between %@AS@%First%@AE@% and %@AS@%Time%@AE@%.%@NL@%
- %@AS@%index0$%@AE@% The %@AS@%$%@AE@% sign is not a valid identifier character.%@NL@%
- %@AS@%area!233%@AE@% The %@AS@%!%@AE@% mark is not a valid identifier character.%@NL@%
- %@AS@%555area%@AE@% The first character is a digit.%@NL@%
- %@NL@%
- %@CR:MQP13206@%%@4@%Identifiers in Pascal are not case sensitive. This means that the%@EH@%
- identifiers %@AS@%First_Time%@AE@%, %@AS@%first_Time%@AE@%, %@AS@%first_time%@AE@%, and %@AS@%FIRST_TIME%@AE@% all refer to
- the same identifier. If these identifiers were typed in a program, the
- compiler would not generate an error. Instead, the compiler would treat them
- as the same identifier.%@NL@%
- %@NL@%
- %@CR:MQP13207@%%@4@%Some identifiers are defined by Microsoft. These identifiers name certain%@EH@%
- data types, standard procedures and functions, units, and variables and
- constants defined in standard units. In this manual and throughout the
- sample programs, these "standard identifiers" are shown with initial capital
- letters.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP13300@%%@3@%%@AB@%1.3.3 Constants and Variables%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP13301@%%@4@%"Constants" and "variables" are two different ways for your program to use%@EH@%
- data. A constant is defined at the beginning of your program and always has
- the same value. In the sample program FTOC.PAS, the constant %@AS@%factor%@AE@% is
- assigned the value %@AS@%32.0%@AE@%. After such an assignment is made (using the %@AB@%CONST%@AE@%
- keyword), QuickPascal replaces the identifier %@AS@%factor%@AE@% with the value %@AS@%32.0%@AE@%
- whenever the identifier is encountered. Constants can make your program more
- readable and understandable.%@NL@%
- %@NL@%
- %@CR:MQP13302@%%@4@%Programs operate on data. In Pascal, as in other programming languages, data%@EH@%
- are stored in variables. Variables must be declared in a Pascal program
- before being used. Variable declarations follow the keyword %@AB@%VAR%@AE@% and have two
- parts: a variable name (identifier) and type. Data types are discussed
- below. In our sample program, both %@AS@%degrees_fahr%@AE@% and %@AS@%degrees_cel%@AE@% are
- variables of type %@AS@%Real%@AE@%.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP13400@%%@3@%%@AB@%1.3.4 Data Types%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP13401@%%@4@%Pascal classifies data according to "type." Roughly speaking, data types%@EH@%
- allow the computer to determine how much memory a variable requires, and
- what level of precision should be maintained for a number. Type declarations
- keep you from making mistakes such as storing your zip code where your
- salary should be.%@NL@%
- %@NL@%
- %@CR:MQP13402@%%@4@%When you declare a variable, you must declare its type as well as its name.%@EH@%
- Data naturally falls into two general categories: text and numbers. Textual
- data items (which may include numbers, as in a street address) are referred
- to as "strings." Numbers can be integers (whole numbers such as 1 and 34) or
- real numbers (decimal numbers such as 29.5 and 3.14159). Four simple data
- types are illustrated below:%@NL@%
- %@NL@%
- %@CR:MQP13403@% %@AB@%Data Type%@AE@%%@NL@%
- %@NL@%
- %@AS@%Mary Smith%@AE@% String%@NL@%
- %@NL@%
- %@AS@%1413 Oak Lane%@AE@% String%@NL@%
- %@NL@%
- %@AS@%76%@AE@% Integer%@NL@%
- %@NL@%
- %@AS@%21.0987%@AE@% Real%@NL@%
- %@NL@%
- %@AS@%Y%@AE@% Character%@NL@%
- %@NL@%
- %@CR:MQP13404@%%@4@%Data types are discussed in more detail in Chapter 2%@BO: bdde@%, "Programming Basics."%@EH@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP13500@%%@3@%%@AB@%1.3.5 Operators and Expressions%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP13501@%%@4@%Operators are used in expressions to manipulate data within your program.%@EH@%
- Pascal includes many operators, but the simplest are already familiar to
- you: addition, subtraction, multiplication, and division. Another class of
- common operators are relational operators, such as "greater than," "less
- than," and "equal to." You'll use operators in your programs to do tasks
- such as counting how many lines you've printed on a page, or seeing if the
- number of hours someone worked in a week exceeds 40. More sophisticated uses
- for operators also exist, and those are discussed in Chapter 2%@BO: bdde@%,
- "Programming Basics."%@NL@%
- %@NL@%
- %@CR:MQP13502@%%@4@%Expressions combine operators with data, as shown in the example below:%@EH@%%@NL@%
- %@NL@%
- %@AS@% { Multiply the number of hours worked by the rate of%@NL@%
- %@AS@% pay. Store the answer in the variable 'Salary'%@NL@%
- %@AS@% }%@NL@%
- %@AS@%salary := hours * pay_rate;%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP14000@%%@2@%%@AB@%1.4 Input and Output%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP14001@%%@4@%At the risk of oversimplification, you could say that most programs get some%@EH@%
- data, manipulate that data in some fashion, and display some final data to a
- user. So far in this chapter you've learned a bit about data and data
- manipulation. "Input" and "output" refer to the processes of getting and
- displaying data.%@NL@%
- %@NL@%
- %@CR:MQP14002@%%@4@%%@AB@%Input%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP14003@%%@4@%Pascal programs frequently make use of the %@AB@%Read%@AE@% and %@AB@%Readln%@AE@% procedures for%@EH@%
- data input. %@AB@%Read%@AE@% is useful for getting a single keystroke──for instance,
- when you want the user to press a key to stop a process. %@AB@%Readln%@AE@% is useful
- when you want the user to be able to type and correct a complete line of
- text before the program accepts it. %@AB@%Readln%@AE@% doesn't do anything until the
- user presses ENTER, thus providing the user with the ability to edit the
- input line before sending it on to the program for processing.%@NL@%
- %@NL@%
- %@CR:MQP14004@%%@4@%In the example below, the first line that the user types is stored as the%@EH@%
- variable %@AS@%name%@AE@% and the next line is stored as %@AS@%address%@AE@%.%@NL@%
- %@NL@%
- %@AS@%Readln( name );%@NL@%
- %@AS@%Readln( address );%@NL@%
- %@NL@%
- %@CR:MQP14005@%%@4@%%@AB@%Output%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP14006@%%@4@%Just as %@AB@%Read%@AE@% and %@AB@%Readln%@AE@% handle data input, %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% handle output.%@EH@%
- %@AB@%Writeln%@AE@% differs from %@AB@%Write%@AE@% in that %@AB@%Writeln%@AE@% generates a carriage return at
- the end of the string (the line of text). Thus, %@AB@%Writeln%@AE@% moves the cursor to
- a new line on your output screen.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP15000@%%@2@%%@AB@%1.5 Moving On%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP15001@%%@4@%So far you have looked at and compiled your first program, and you have been%@EH@%
- exposed to some basic Pascal terms. The next chapter elaborates on the
- concepts introduced here and shows you how to create some more complex
- programs.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP20000@%%@1@%%@AB@%Chapter 2 Programming Basics%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQP20001@%%@4@%This chapter introduces you to some Pascal programming fundamentals, such as%@EH@%
- data types, constants, variables, operators, and expressions. If you're
- already an experienced programmer in another language, you may find most of
- this material to be familiar. In that case, you might want to skim this
- chapter quickly or just skip ahead to Chapter 3%@BO: 13ad7@%.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP21000@%%@2@%%@AB@%2.1 Data Types%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP21001@%%@4@%All data in your program is either a constant or a variable; each has an%@EH@%
- associated data type. Two kinds of data types exist in QuickPascal:
- predefined data types and user-defined data types. Predefined data types,
- such as %@AB@%Real%@AE@% and %@AB@%STRING%@AE@%, are a built-in part of the language and are
- discussed below. User-defined data types expand your programming power
- considerably. They are complex enough that Chapter 5%@BO: 21492@% of this book is
- devoted to them.%@NL@%
- %@NL@%
- %@CR:MQP21002@%%@4@%The predefined data types supported by QuickPascal and explained in the%@EH@%
- following sections are:%@NL@%
- %@NL@%
- %@CR:MQP21003@% ■ Integers%@NL@%
- ■ Floating-point numbers%@NL@%
- ■ Characters%@NL@%
- ■ Strings%@NL@%
- ■ Booleans%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP21100@%%@3@%%@AB@%2.1.1 Integer Types%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP21101@%%@4@%Integers are whole numbers like the numbers you use to count with; that is,%@EH@%
- they have no fractional parts. The number 12 is an integer; 12.0 and 12.5
- are not. Table 2.1%@BO: c523@% lists the five integer types that QuickPascal supports.
- Programs discussed later in this chapter show how these integers are used.%@NL@%
- %@NL@%
- %@CR:MQP2T100@%%@4@%%@AB@%Table 2.1 Integer Data Types%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Integer Type Range of Values Byte Size Examples%@AE@%%@NL@%
- %@NL@%
- %@AB@%ShortInt%@AE@% -128 to 127 1 -7, 55, 123, 0, $F%@NL@%
- %@NL@%
- %@AB@%Byte%@AE@% 0 to 255 1 55, 123, $F, 0%@NL@%
- %@NL@%
- %@AB@%Integer%@AE@% -32768 to 32767 2 -555, 30000, 0, $FF%@NL@%
- %@NL@%
- %@AB@%Word%@AE@% 0 to 65535 2 30000, 60000, $FFFF%@NL@%
- %@NL@%
- %@AB@%LongInt%@AE@% -2147483648 to 4 -100000, 100000, $FFFF%@NL@%
- 2147483647%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP21102@%%@4@%The integer types %@AB@%Byte%@AE@% and %@AB@%Word%@AE@% are called "unsigned" integers, while the%@EH@%
- other integer types are called "signed" integers. The word "unsigned"
- indicates that the integer includes values from zero to the upper positive
- limit. Signed integers include negative numbers.%@NL@%
- %@NL@%
- %@CR:MQP21103@%%@4@%You can see that the main difference between the different integer types is%@EH@%
- the range of the values that can be stored. In the %@AB@%VAR%@AE@% section of your
- program, you declare the variable identifier and the specific type.%@NL@%
- %@NL@%
- %@CR:MQP21104@%%@4@%As the examples in Table 2.1%@BO: c523@% show, QuickPascal allows you to write integers%@EH@%
- in either decimal (base 10) or hexadecimal notation (base 16). Hexadecimal
- numbers begin with the dollar sign ($) and use the characters 0-9 and A-F.%@NL@%
- %@NL@%
- %@CR:MQP21105@%%@4@%The INTTYPES.PAS program below demonstrates different types of integers.%@EH@%%@NL@%
- %@NL@%
- %@AS@% PROGRAM Inttypes;%@NL@%
- %@AS@% { INTTYPES.PAS demonstrates integer data types. }%@NL@%
- %@NL@%
- %@AS@% USES%@NL@%
- %@AS@% Crt;%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% short_int_val : ShortInt;%@NL@%
- %@AS@% byte_val : Byte;%@NL@%
- %@AS@% integer_val : Integer;%@NL@%
- %@AS@% word_val : Word;%@NL@%
- %@AS@% long_int_val : LongInt;%@NL@%
- %@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% short_int_val := -31;%@NL@%
- %@AS@% byte_val := 255;%@NL@%
- %@AS@% integer_val := -21212;%@NL@%
- %@AS@% word_val := $FFFF;%@NL@%
- %@AS@% long_int_val := 12918656;%@NL@%
- %@AS@% ClrScr;%@NL@%
- %@AS@% Writeln( 'short_int_val = ', short_int_val );%@NL@%
- %@AS@% Writeln( 'byte_val = ', byte_val );%@NL@%
- %@AS@% Writeln( 'integer_val = ', integer_val );%@NL@%
- %@AS@% Writeln( 'word_val = ', word_val );%@NL@%
- %@AS@% Writeln( 'long_int_val = ', long_int_val );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP21106@%%@4@%Here is the output from INTTYPES.PAS:%@EH@%%@NL@%
- %@NL@%
- %@AS@%short_int_val = -31%@AE@%%@NL@%
- %@AS@%byte_val = 255%@AE@%%@NL@%
- %@AS@%integer_val = -21212%@AE@%%@NL@%
- %@AS@%word_val = 65535%@AE@%%@NL@%
- %@AS@%long_int_val = 12918656%@AE@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP21200@%%@3@%%@AB@%2.1.2 Floating-Point Types%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP21201@%%@4@%Floating-point numbers are not integers; that is, they are written with a%@EH@%
- decimal point. Thus the number 12.5 is a floating-point number, as is
- .00021459862. Also, QuickPascal treats constants larger than its maximum as
- long-integer size floating-point numbers, even if they do not contain a
- decimal point. Floating-point numbers are also referred to as "real"
- numbers.%@NL@%
- %@NL@%
- %@CR:MQP21202@%%@4@%QuickPascal supports a group of floating-point types that vary in their%@EH@%
- precision, range of values, and storage requirements. They are shown in
- Table 2.2.%@NL@%
- %@NL@%
- %@CR:MQP2T200@%%@4@%%@AB@%Table 2.2 Floating-Point Data Types%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Type Range of Value Byte Size Significant Digits%@AE@%%@NL@%
- %@NL@%
- %@AB@%Single%@AE@% 1.5E-45 to 3.4E+38 4 7-8%@NL@%
- %@NL@%
- %@AB@%Real%@AE@% 2.9E-39 to 1.7E+38 6 11-12%@NL@%
- %@NL@%
- %@AB@%Double%@AE@% 5.0E-324 to 1.7E+308 8 15-16%@NL@%
- %@NL@%
- %@AB@%Extended%@AE@% 3.4E-4951 to 1.1E+4932 10 15-16%@NL@%
- %@NL@%
- %@AB@%Comp%@AE@% -9.2E+18 to 9.2E+18 8 15-16%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP21203@%%@4@%By default, QuickPascal assumes that your computer does not use a math%@EH@%
- coprocessor, resulting in fewer significant digits than if it did use a
- coprocessor. However, if you have a math coprocessor available (any member
- of the 8087 family of processors), you can increase the precision of %@AB@%Comp%@AE@%
- and %@AB@%Extended%@AE@% data types by 4 significant digits by including the %@AB@%{$N+}%@AE@%
- compiler directive in your program.%@NL@%
- %@NL@%
- %@CR:MQP21204@%%@4@%Unlike some other Pascal compilers, QuickPascal makes all real number types%@EH@%
- available for your use, whether or not your computer has a numeric
- coprocessor.%@NL@%
- %@NL@%
- %@CR:MQP21205@%%@4@%The %@AB@%Comp%@AE@% type is a little different from the other floating-point types.%@EH@%
- %@AB@%Comp%@AE@% is designed to count very large numbers, and so it stores only the
- integer part of a number between -(2^63)+1 and (2^63)-1.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP21300@%%@3@%%@AB@%2.1.3 Character Type%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP21301@%%@4@%The character data type %@AB@%Char%@AE@% stores only one character. Each character%@EH@%
- occupies one byte of storage. You can represent characters using the
- following formats:%@NL@%
- %@NL@%
- %@CR:MQP21302@%%@AB@%Characters Representation%@AE@%%@NL@%
- %@NL@%
- Readable characters Can be represented by using same letters,%@NL@%
- (that is, the alphabet, digits, and punctuation.%@NL@%
- digits, and punctuation %@NL@%
- characters) %@NL@%
- %@NL@%
- Control characters Can be represented using the carat symbol (^)%@NL@%
- (ASCII characters 0 followed by the control letter. For example, the%@NL@%
- through 31) form feed is represented by ^L, since form feed%@NL@%
- is ASCII 12 and L is the 12th letter in the%@NL@%
- alphabet. Appendix A%@BO: 829c0@% contains a chart of all%@NL@%
- ASCII codes.%@NL@%
- %@NL@%
- All characters, Can be represented by using the number sign (#)%@NL@%
- including those in the followed by the ASCII code number. Thus, #65 is%@NL@%
- extended ASCII table the letter A, #12 is the form feed, and so on.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP21400@%%@3@%%@AB@%2.1.4 String Types%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP21401@%%@4@%This data type stores a string of characters such as a name or an address.%@EH@%
- QuickPascal strings can hold up to 255 characters. Many of the examples in
- this book use strings to display messages and store input. The STRINGS.PAS
- program demonstrates how to create, read, and write simple strings.%@NL@%
- %@NL@%
- %@AS@% PROGRAM Strings;%@NL@%
- %@NL@%
- %@AS@% { STRINGS.PAS demonstrates basic string operations. }%@NL@%
- %@NL@%
- %@AS@% USES%@NL@%
- %@AS@% Crt;%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% str_constant = 'Type something and press Enter: ';%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% prompt_one : STRING;%@NL@%
- %@AS@% prompt_two : STRING;%@NL@%
- %@AS@% input_str : STRING;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% prompt_one := str_constant;%@NL@%
- %@AS@% prompt_two := 'You typed: ';%@NL@%
- %@NL@%
- %@AS@% ClrScr;%@NL@%
- %@AS@% Write( prompt_one );%@NL@%
- %@AS@% Readln( input_str );%@NL@%
- %@AS@% Write( prompt_two );%@NL@%
- %@AS@% Writeln( input_str );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP21402@%%@4@%Here is typical output from STRINGS.PAS:%@EH@%%@NL@%
- %@NL@%
- %@AS@%Type something and press Enter: QuickPascal!%@AE@%%@NL@%
- %@AS@%You typed: QuickPascal!%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP21410@%%@4@%%@AB@%2.1.4.1 Declaring Strings%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP21411@%%@4@%Pascal strings are usually of the %@AB@%STRING%@AE@% type. In STRINGS.PAS, the%@EH@%
- statements%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% prompt_one : STRING;%@NL@%
- %@AS@% prompt_two : STRING;%@NL@%
- %@AS@% input_str : STRING;%@NL@%
- %@NL@%
- %@CR:MQP21412@%%@4@%declare three string variables named %@AS@%prompt_one%@AE@%, %@AS@%prompt_two%@AE@%, and %@AS@%input_str%@AE@%.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP21420@%%@4@%%@AB@%2.1.4.2 Initializing Strings%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP21421@%%@4@%You can initialize string variables by assigning string literals or%@EH@%
- constants to them:%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% str_constant = 'Type something and press Enter: ';%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% prompt_one := str_constant; { Assign string constant }%@NL@%
- %@AS@% prompt_two := 'You typed: '; { Assign string literal }%@NL@%
- %@NL@%
- %@CR:MQP21422@%%@4@%Pascal strings can contain as many as 255 characters. The first character of%@EH@%
- a string is a "length byte" that indicates the number of characters in the
- string. Procedures such as %@AB@%Writeln%@AE@% look at this byte to determine the
- string's size.%@NL@%
- %@NL@%
- %@CR:MQP21423@%%@4@%Thus, if you assign %@AS@%Hello%@AE@% to a string variable, the variable actually%@EH@%
- contains six characters: a length byte that contains the number 5, followed
- by the 5 characters of %@AS@%Hello%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQP21430@%%@4@%%@AB@%2.1.4.3 Reading and Writing Strings%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP21431@%%@4@%You can use the %@AB@%Read%@AE@% and %@AB@%Readln%@AE@% procedures to read a string:%@EH@%%@NL@%
- %@NL@%
- %@AS@% Readln( input_str );%@NL@%
- %@NL@%
- %@CR:MQP21432@%%@4@%and the %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% procedures to write a string:%@EH@%%@NL@%
- %@NL@%
- %@AS@% Write( prompt_two );%@NL@%
- %@AS@% Writeln( input_str );%@NL@%
- %@NL@%
- %@CR:MQP21433@%%@4@%These procedures read input from the keyboard and write output to the%@EH@%
- screen. See Chapter 8%@BO: 35d22@%, "The Keyboard and Screen," for more information on
- input and output.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP21500@%%@3@%%@AB@%2.1.5 Boolean Type%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP21501@%%@4@%A variable of type %@AB@%Boolean%@AE@% can be assigned a value of true or false.%@EH@%
- Variables of this type are often used as "flags" when a condition in your
- program becomes true (or false). Suppose, for example, that you wanted to
- check whether a user had finished entering data. If the variable %@AS@%all_done%@AE@%
- had been declared as type %@AB@%Boolean%@AE@%, you may use it like this:%@NL@%
- %@NL@%
- %@AS@% IF (x = 0) THEN all_done := true;%@NL@%
- %@NL@%
- %@CR:MQP21502@%%@4@%Later you may need to check the %@AS@%all_done%@AE@% variable:%@EH@%%@NL@%
- %@NL@%
- %@AS@% IF (all_done = True) THEN ...%@NL@%
- %@NL@%
- %@CR:MQP21503@%%@4@%A shorthand way of writing this statement is%@EH@%%@NL@%
- %@NL@%
- %@AS@% IF (all_done) THEN ...%@NL@%
- %@NL@%
- %@CR:MQP21504@%%@4@%It is understood that %@AS@%IF all_done%@AE@% means the same as %@AS@%IF (all_done = True)%@AE@%%@EH@%
- and by the same understanding, %@AS@%IF (NOT all_done)%@AE@% means %@AS@%IF (all_done =%@AE@%
- %@AS@%False%@AE@%).%@NL@%
- %@NL@%
- %@CR:MQP21505@%%@4@%For more information about %@AB@%Boolean%@AE@% types and what you can do with them, see%@EH@%
- Chapter 12, "Advanced Topics."%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP22000@%%@2@%%@AB@%2.2 Constants%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP22001@%%@4@%Fixed data, or "constants," are assigned a value which is never changed (an%@EH@%
- exception to this, called "typed constants," is discussed below). When you
- declare constants in Pascal, you assign them a name and value. This value,
- once assigned, cannot be changed in your program. The assignment of name and
- value to a constant is called a constant declaration.%@NL@%
- %@NL@%
- %@CR:MQP22002@%%@4@%QuickPascal supports two kinds of constants: simple and typed.%@EH@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP22100@%%@3@%%@AB@%2.2.1 Simple Constants%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP22101@%%@4@%Simple constants can be used for two purposes. First, they can store fixed%@EH@%
- values, like the number of inches in a foot. Second, they can store values
- you wish to use within your program, like the text of a title screen or your
- assumption for the rate of inflation. Since constants are all declared at
- the beginning of your program, it is easy to change any of those values and
- recompile your program. Remember, changing the value of a constant in its
- initial declaration gives that new value to the constant wherever it is
- used. In fact, any other constants that depend on the one you alter will
- also receive their updated values when you recompile the program.%@NL@%
- %@NL@%
- %@CR:MQP22102@%%@4@%The general syntax for declaring and initializing a constant is:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP22103@%%@4@%%@AB@%CONST%@AE@% %@AI@%ConstantIdentifier%@AE@% = {%@AI@%ConstantValue%@AE@%|%@AI@%Expression%@AE@%}%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP22104@%%@4@%For example:%@EH@%%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@NL@%
- %@AS@% ft_per_mile = 5280;%@NL@%
- %@NL@%
- %@CR:MQP22105@%%@4@%In this example, the %@AI@%ConstantIdentifier%@AE@% is %@AS@%ft_per_mile%@AE@% and the%@EH@%
- %@AI@%ConstantValue%@AE@% is %@AS@%5280%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQP22106@%%@4@%In QuickPascal, you can use an expression that contains a previously%@EH@%
- declared constant. You can also set a constant equal to an expression, as in%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@NL@%
- %@AS@% days_per_year = 365;%@NL@%
- %@AS@% seconds_per_day = 60 * 60 * 24;%@NL@%
- %@AS@% light_speed = 186282;%@NL@%
- %@AS@% light_year = light_speed * seconds_per_day%@NL@%
- %@AS@% * days_per_year;%@NL@%
- %@NL@%
- %@CR:MQP22107@%%@4@%However, if you declare a constant equal to an expression, that expression%@EH@%
- can only contain simple operations like addition, subtraction,
- multiplication, and division. More advanced Pascal functions like square
- root cannot be used.%@NL@%
- %@NL@%
- %@CR:MQP22108@%%@4@%Here are some more examples of constants:%@EH@%%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@NL@%
- %@AS@% max_row = 10;%@NL@%
- %@AS@% max_col = 10;%@NL@%
- %@NL@%
- %@AS@% { Uses previously declared constants }%@NL@%
- %@AS@% table_size = max_row * max_col;%@NL@%
- %@NL@%
- %@AS@% prompt = 'Press any key to resume...';%@NL@%
- %@AS@% byebye = 'Thank you for using the program...';%@NL@%
- %@NL@%
- %@AS@% euler_const = 0.577215664901;%@NL@%
- %@NL@%
- %@AS@% { An approximation of the Euler constant }%@NL@%
- %@AS@% euler_const2 = 228.0 / 395.0;%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP22200@%%@3@%%@AB@%2.2.2 Typed Constants%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP22201@%%@4@%QuickPascal lets you use another kind of constant called a "typed constant."%@EH@%
- In standard Pascal, you can't specify the data type of a constant. The
- compiler assigns the data a type according to how it is presented. For
- example, a constant called %@AS@%number_of_people%@AE@% with a value of 35 would be
- assigned an integer type by QuickPascal, which makes sense. However, if you
- declared %@AS@%number_of_people%@AE@% equal to 35.0, then the compiler would assign a
- real number type to %@AS@%number_of_people%@AE@%, which doesn't make much sense.%@NL@%
- %@NL@%
- %@CR:MQP22202@%%@4@%Fortunately, QuickPascal allows you to specifically state the data type%@EH@%
- associated with a constant, which is the typed constant. You may also see
- the terms "variable constant" or "static variable" used to describe such a
- constant. Declaring data with a typed constant actually changes the constant
- into an initialized variable. That is, the value associated with the
- typed-constant identifier can be changed in the program, unlike regular
- constants whose value cannot be changed within the program.%@NL@%
- %@NL@%
- %@CR:MQP22203@%%@4@%A typed constant can be thought of as a cross between a constant and a%@EH@%
- variable. A constant's value is declared but can never be changed. A
- variable, on the other hand, is not declared with a predefined value, and
- its value can change within the program. A typed constant is like a variable
- whose predefined value is declared but which can be redefined within the
- program.%@NL@%
- %@NL@%
- %@CR:MQP22204@%%@4@%The general syntax is shown below:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP22205@%%@4@%%@AB@%CONST%@AE@% %@AI@%ConstantIdentifier%@AE@% : %@AI@%TypeName%@AE@% = {%@AI@%ConstantValue%@AE@%|%@AI@%Expression%@AE@%}%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP22206@%%@4@%Examples of typed constant declarations are given below. Note that the%@EH@%
- %@AI@%ConstantValue%@AE@% or %@AI@%Expression%@AE@% assigned to the typed constant is much like a
- value or expression assigned to a regular variable. Note that you use the
- :%@AI@%TypeName%@AE@% to specify the type of the constant, as you would in a %@AB@%VAR%@AE@%
- declaration.%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@NL@%
- %@AS@% max_row : Word = 10;%@NL@%
- %@AS@% max_col : Word = 10;%@NL@%
- %@AS@% table_size : Word = max_row * max_col;%@NL@%
- %@NL@%
- %@AS@% prompt : STRING = 'Press any key to resume...';%@NL@%
- %@AS@% byebye : STRING = 'Thank you for using the program...';%@NL@%
- %@NL@%
- %@AS@% euler_const : Real = 0.577215664901;%@NL@%
- %@AS@% { An approximation to the Euler const }%@NL@%
- %@AS@% euler_const2 : Real = 228.0 / 395.0;%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP23000@%%@2@%%@AB@%2.3 Simple Variables%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP23001@%%@4@%While constants are identifiers that are declared and assigned a fixed%@EH@%
- value, variables are identifiers that are merely declared. They are assigned
- values in the main program or a subprogram. The general syntax for declaring
- a variable and identifying its type is as follows:%@NL@%
- %@NL@%
- %@AB@%VAR%@AE@% %@AI@%VariableName%@AE@% «, %@AI@%VariableName%@AE@%...» : %@AI@%DataType%@AE@%%@NL@%
- .%@NL@%
- .%@NL@%
- .%@NL@%
- %@NL@%
- %@CR:MQP23003@%%@4@%Some examples of declaring variables:%@EH@%%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% { Variables declared with predefined type }%@NL@%
- %@AS@% column_index : Word;%@NL@%
- %@AS@% area, circumference : Real;%@NL@%
- %@AS@% message : STRING;%@NL@%
- %@AS@% input_character : Char;%@NL@%
- %@NL@%
- %@CR:MQP23004@%%@4@%Once a variable is declared, QuickPascal sets aside the required amount of%@EH@%
- memory to store data associated with the variable. The amount of memory set
- aside is based on the variable's data type. For example, a variable declared
- with type %@AS@%STRING[40]%@AE@% gets 41 bytes of memory of which 40 bytes are available
- for data (the remaining byte holds the string length); a variable with type
- %@AS@%Integer%@AE@% gets 2 bytes of memory.%@NL@%
- %@NL@%
- %@CR:MQP23005@%%@4@%Once a variable is declared, you may assign it a value. Often you will use%@EH@%
- the assignment operator (%@AB@%:=%@AE@%), which should not be confused with the equality
- operator (%@AB@%=%@AE@%). The assigned value can be a constant, another variable, or an
- expression.%@NL@%
- %@NL@%
- %@CR:MQP23006@%%@4@%The VARS.PAS program shows a simple assignment of variables. The variable%@EH@%
- radius is assigned a value through user input (the %@AB@%Readln%@AE@% procedure). The
- variable area is assigned the value of an expression using the assignment
- operator.%@NL@%
- %@NL@%
- %@AS@% PROGRAM Vars;%@NL@%
- %@AS@% { VARS.PAS: variable declaration and use }%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% radius, area : Real;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'Enter radius' );%@NL@%
- %@AS@% Readln( radius );%@NL@%
- %@AS@% Area := (Pi * (radius * radius));%@NL@%
- %@AS@% Writeln( 'Area of the circle = ', area:8:2 );%@NL@%
- %@AS@% Writeln;%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP23007@%%@4@%Typical output from VARS.PAS looks like this:%@EH@%%@NL@%
- %@NL@%
- %@AS@%Enter radius%@AE@%%@NL@%
- %@AS@%12%@AE@%%@NL@%
- %@AS@%Area of the circle = 452.39%@AE@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP24000@%%@2@%%@AB@%2.4 Pascal Operators%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP24001@%%@4@%Operators let you manipulate data. Pascal operators are used to build%@EH@%
- expressions. This section describes some of the operators available in
- Microsoft QuickPascal. In addition to the ones discussed here, QuickPascal
- supports some operators for advanced use, including bitwise and set
- operators. The bitwise operators are discussed in detail in Chapter 12%@BO: 517ed@%,
- "Advanced Topics." Set operators are discussed in Chapter 5%@BO: 21492@%, "User-Defined
- Data Types."%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP24100@%%@3@%%@AB@%2.4.1 Kinds of Operators%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP24101@%%@4@%QuickPascal supports the following categories of operators:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP24102@% ■ Arithmetic%@NL@%
- ■ Relational%@NL@%
- ■ String%@NL@%
- ■ Address-of%@NL@%
- %@NL@%
- %@CR:MQP24110@%%@4@%%@AB@%2.4.1.1 Arithmetic Operators%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP24111@%%@4@%Table 2.3%@BO: 11a7d@% lists the arithmetic operators, which perform numeric %@EH@%
- manipulation of integer and floating-point types. While the addition (%@AB@%+%@AE@%),
- subtraction (%@AB@%-%@AE@%), and multiplication (%@AB@%*%@AE@%) operators work with both integers
- and floating-point types, the division (%@AB@%/%@AE@%) operator performs floating-point
- division (even if the operands are integers), and the %@AB@%DIV%@AE@% and %@AB@%MOD%@AE@% operators
- work with integers only.%@NL@%
- %@NL@%
- %@CR:MQP24112@%%@4@%While most of the operators take two operands, the unary plus and unary%@EH@%
- minus operators work with one operand only.%@NL@%
- %@NL@%
- %@CR:MQP2T300@%%@4@%%@AB@%Table 2.3 Arithmetic Operators%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Operator Purpose%@AE@%%@NL@%
- %@NL@%
- %@AB@%+%@AE@% Unary plus sign%@NL@%
- %@NL@%
- %@AB@%-%@AE@% Unary minus sign%@NL@%
- %@NL@%
- %@AB@%+%@AE@% Adds two numbers%@NL@%
- %@NL@%
- %@AB@%-%@AE@% Subtracts two numbers%@NL@%
- %@NL@%
- %@AB@%*%@AE@% Multiplies two numbers%@NL@%
- %@NL@%
- %@AB@%/%@AE@% Divides two floating-point numbers%@NL@%
- %@NL@%
- %@AB@%DIV%@AE@% Divides two integer numbers%@NL@%
- %@NL@%
- %@AB@%MOD%@AE@% Returns the remainder of integer division%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP24120@%%@4@%%@AB@%2.4.1.2 Relational Operators%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP24121@%%@4@%Relational operators are used to compare two operands, which may be%@EH@%
- constants, variables, functions, or expressions. The operands must be of the
- same or compatible types. Some useful relational operators are shown in
- Table 2.4.%@NL@%
- %@NL@%
- %@CR:MQP2T400@%%@4@%%@AB@%Table 2.4 Relational Operators%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Operator Purpose%@AE@%%@NL@%
- %@NL@%
- %@AB@%=%@AE@% Equal to%@NL@%
- %@AB@%<>%@AE@% Not equal to%@NL@%
- %@AB@%>%@AE@% Greater than%@NL@%
- %@AB@%>=%@AE@% Greater than or equal to%@NL@%
- %@AB@%<%@AE@% Less than%@NL@%
- %@AB@%<=%@AE@% Less than or equal to%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP24130@%%@4@%%@AB@%2.4.1.3 String Operators%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP24131@%%@4@%QuickPascal has one string operator, the (%@AB@%+%@AE@%) operator, for string and%@EH@%
- character concatenation. Other aspects of string manipulation are performed
- by predefined procedures and functions.%@NL@%
- %@NL@%
- %@CR:MQP24140@%%@4@%%@AB@%2.4.1.4 Address-Of Operator%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP24141@%%@4@%The address-of operator (%@AB@%@%@AE@%) is used to return the address of variables,%@EH@%
- routines, parameters, and so forth. The topic of pointers is covered fully
- in Chapter 11%@BO: 48f3e@%.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP24200@%%@3@%%@AB@%2.4.2 Operator Precedence%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP24201@%%@4@%Operators in expressions are evaluated in order of their precedence. Table%@EH@%
- 2.5%@BO: 12531@% lists the QuickPascal operators according to their precedence level.
- Although not all of the operators shown in the table are discussed in this
- section, they are in the table for the sake of completeness. For information
- on operators such as %@AB@%SHL%@AE@% or %@AB@%XOR%@AE@%, see Chapter 12%@BO: 517ed@%, "Advanced Topics," or use
- QP Advisor.%@NL@%
- %@NL@%
- %@CR:MQP2T500@%%@4@%%@AB@%Table 2.5 Operator Precedence%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Precedence Level Operators Operator Class%@AE@%%@NL@%
- %@NL@%
- 1 (highest) %@AB@%@%@AE@%, %@AB@%NOT%@AE@% Unary%@NL@%
- 2 %@AB@%*%@AE@%, %@AB@%/%@AE@%, %@AB@%DIV%@AE@%, %@AB@%MOD%@AE@%, %@AB@%AND%@AE@%, %@AB@%SHL%@AE@%, %@AB@%SHR%@AE@% Multiplying%@NL@%
- 3 %@AB@%+%@AE@%, %@AB@%-%@AE@%, %@AB@%OR%@AE@%, %@AB@%XOR%@AE@% Adding%@NL@%
- 4 (lowest) %@AB@%=%@AE@%, %@AB@%<>%@AE@%, %@AB@%<%@AE@%, %@AB@%<=%@AE@%, %@AB@%>%@AE@%, %@AB@%>=%@AE@%, %@AB@%IN%@AE@% Relational%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP24202@%%@4@%The following list interprets this table and gives examples of the use of%@EH@%
- operators.%@NL@%
- %@NL@%
- %@CR:MQP24203@% ■ The operation defined by the operator with highest precedence and its%@NL@%
- related operand is performed first. In the example%@NL@%
- %@NL@%
- %@AS@%2 * 4 + 3%@AE@%%@NL@%
- %@NL@%
- the number %@AS@%4%@AE@% is placed between two operators of different precedence.%@NL@%
- Since the (%@AB@%*%@AE@%) operator has a higher precedence, multiplication of %@AS@%2%@AE@% and%@NL@%
- %@AS@%4%@AE@% proceeds first. The addition is performed afterward.%@NL@%
- %@NL@%
- ■ Operations of the same precedence level are performed from left to%@NL@%
- right. In the example%@NL@%
- %@NL@%
- %@AS@%2 * 4 / 3%@AE@%%@NL@%
- %@NL@%
- the number %@AS@%4%@AE@% is placed between two operators of the same precedence.%@NL@%
- Since the (%@AB@%*%@AE@%) operator appears to the left of number %@AS@%4%@AE@%, it is applied%@NL@%
- before the (%@AB@%/%@AE@%) operator.%@NL@%
- %@NL@%
- ■ Parentheses are used to group operations. Expressions enclosed in%@NL@%
- parentheses are evaluated first. The most deeply nested expression is%@NL@%
- evaluated before any other. (Nested expressions are expressions within%@NL@%
- expressions.) Parentheses alter the "effective" or "working" precedence%@NL@%
- of an operator. In the example%@NL@%
- %@NL@%
- %@AS@%2 / ((3 + 4) * 5)%@AE@%%@NL@%
- %@NL@%
- the expression in the parentheses %@AS@%(3 + 4)%@AE@% is evaluated first, since it%@NL@%
- is the most nested expression in parentheses. The (%@AB@%*%@AE@%) operator is%@NL@%
- applied next, since it is enclosed in parentheses, giving it a higher%@NL@%
- effect precedence. Finally, the (%@AB@%/%@AE@%) operator is applied.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP25000@%%@2@%%@AB@%2.5 Simple Pascal Expressions%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP25001@%%@4@%Expressions are a special and very important part of any programming%@EH@%
- language. They are created to evaluate data in your program. Expressions use
- the operators described in Section 2.4%@BO: 11422@% and operands, which are the data
- types in your program, as their components. QuickPascal supports simple and
- advanced expressions.%@NL@%
- %@NL@%
- %@CR:MQP25002@%%@4@%This chapter briefly presents the simple expressions. Each type of%@EH@%
- expression follows a syntax rule which gives its components and syntax. The
- simple expressions explained in this chapter are%@NL@%
- %@NL@%
- %@CR:MQP25003@% ■ Arithmetic%@NL@%
- %@NL@%
- ■ String%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP25100@%%@3@%%@AB@%2.5.1 Arithmetic Expressions%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP25101@%%@4@%Arithmetic expressions combine constants, numbers, variables, and functions%@EH@%
- with arithmetic operators.%@NL@%
- %@NL@%
- %@CR:MQP25102@%%@4@%The syntax of an expression is%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP25103@%%@4@%{ %@AI@%Constant%@AE@% | %@AI@%Expression%@AE@% } |%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP25104@%%@4@%« %@AI@%Constant%@AE@% | %@AI@%Expression%@AE@% » { %@AI@%Operator%@AE@% %@AI@%Constant%@AE@% | %@AI@%Expression%@AE@% }%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP25105@%%@4@%For example%@EH@%%@NL@%
- %@NL@%
- %@AS@% (length * width)%@NL@%
- %@NL@%
- %@CR:MQP25106@%%@4@%Expressions combine with constants or variables and relational or assignment%@EH@%
- operators to make Pascal statements:%@NL@%
- %@NL@%
- %@AS@% area := (length * width)%@NL@%
- %@NL@%
- %@CR:MQP25107@%%@4@%In the example above, the expression %@AS@%length * width%@AE@% is evaluated, then the%@EH@%
- result is stored in the variable %@AS@%area%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQP25108@%%@4@%Expressions are evaluated according to operator precedence. Using%@EH@%
- parentheses to force the correct evaluation of an expression is always a
- good idea.%@NL@%
- %@NL@%
- %@CR:MQP25109@%%@4@%An expression may contain nested expressions, which are expressions within%@EH@%
- expressions. Examples are shown below:%@NL@%
- %@NL@%
- %@AS@% K := (1 + 6) DIV (55 - J);%@NL@%
- %@AS@% Z := (2 * X) + (Y / 4);%@NL@%
- %@AS@% T := (((2 * X + 2) * X - 5) * X + 1) * X - 10;%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP25200@%%@3@%%@AB@%2.5.2 String Expressions%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP25201@%%@4@%String expressions use the (%@AB@%+%@AE@%) operator to concatenate strings and%@EH@%
- characters. The general syntax rule is shown below:%@NL@%
- %@NL@%
- %@CR:MQP25202@%%@4@%{%@AI@%Character%@AE@% | %@AI@%String%@AE@%} + {%@AI@%Character%@AE@% | %@AI@%String%@AE@%}...%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP25203@%%@4@%For example%@EH@%%@NL@%
- %@NL@%
- %@AS@% 'dog' + 'house'; { creates the word "doghouse" }%@NL@%
- %@NL@%
- %@CR:MQP25204@%%@4@%The (%@AB@%+%@AE@%) operator works identically to the %@AB@%Concat%@AE@% function. String and%@EH@%
- character concatenation cannot build a string longer than 255 characters.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP30000@%%@1@%%@AB@%Chapter 3 Procedures and Functions%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQP30001@%%@4@%Procedures and functions allow you to write well-organized Pascal programs,%@EH@%
- in which discrete tasks are done in separate, logically contained modules.
- Once you understand procedures and functions, you are well on your way to
- becoming a true Pascal programmer.%@NL@%
- %@NL@%
- %@CR:MQP30002@%%@4@%This chapter begins by discussing procedures, which are simpler and more%@EH@%
- commonly used than functions. The discussion covers many topics, such as
- argument passing, that are common to both procedures and functions. The
- chapter ends with an explanation of functions, nested procedures, and
- recursion.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP31000@%%@2@%%@AB@%3.1 Overview%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP31001@%%@4@%Procedures and functions let you program using a "divide and conquer"%@EH@%
- approach. Instead of trying to solve every aspect of a large problem at
- once, you divide it into several small problems and solve each one
- separately. This strategy allows you to write clear, reliable programs that
- perform different tasks in distinct, logically contained modules. In Pascal,
- these modules are called procedures or functions.%@NL@%
- %@NL@%
- %@CR:MQP31002@%%@4@%Dividing a program into task-based modules offers several advantages:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP31003@% ■ Makes programs easier to write and read. All of the statements related%@NL@%
- to a task are located in one place.%@NL@%
- %@NL@%
- ■ Prevents unexpected side effects because you can use private ("local")%@NL@%
- variables that are not visible to the main program or other sections.%@NL@%
- %@NL@%
- ■ Eliminates unnecessary repetition of code for frequently performed%@NL@%
- tasks.%@NL@%
- %@NL@%
- ■ Simplifies debugging. Once you have debugged a procedure or function,%@NL@%
- you can use it with confidence in many different situations.%@NL@%
- %@NL@%
- %@CR:MQP31004@%%@4@%The distinction between procedures and functions can be summarized in a few%@EH@%
- words. A procedure performs a specific task; a function performs a specific
- task and also returns a value. We will return to this topic in Section 3.3%@BO: 1927a@%,
- "Functions."%@NL@%
- %@NL@%
- %@CR:MQP31005@%%@4@%If you are familiar with Microsoft QuickBASIC, you will notice many%@EH@%
- similarities in Pascal. A Pascal procedure resembles a QuickBASIC %@AB@%SUB%@AE@%
- procedure, and a Pascal function is like a QuickBASIC %@AB@%FUNCTION%@AE@% procedure. If
- you know the C language, you will notice that a C function combines the
- qualities of Pascal procedures and functions; a C function can return a
- value, or return nothing.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP32000@%%@2@%%@AB@%3.2 Procedures%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP32001@%%@4@%Procedures and functions are very similar──so similar, in fact, that%@EH@%
- everything explained in this section applies to functions as well as
- procedures. To avoid repeating the phrase "procedures and functions" with
- every sentence, this section refers only to procedures. You should read it
- with the understanding that these ideas also apply to functions. Section
- 3.3%@BO: 1927a@%, "Functions," explains how functions differ from procedures.%@NL@%
- %@NL@%
- %@CR:MQP32002@%%@4@%A "procedure" is a collection of declarations and statements that performs a%@EH@%
- certain task. You have already seen a few of the QuickPascal standard
- procedures, such as %@AB@%Writeln%@AE@%, which writes a line. This section explains
- procedures using several programs. The first example, CENTER.PAS, contains a
- procedure that centers a line on the screen:%@NL@%
- %@NL@%
- %@AS@% PROGRAM center;%@NL@%
- %@NL@%
- %@AS@% { CENTER.PAS: Demonstrate simple procedure }%@NL@%
- %@NL@%
- %@AS@% USES%@NL@%
- %@AS@% Crt;%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% row : Byte;%@NL@%
- %@AS@% title : STRING;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE center_line( message : STRING; line : Byte );%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% GotoXY( 40 - Length( message ) DIV 2, line );%@NL@%
- %@AS@% Writeln( message );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% row := 2;%@NL@%
- %@AS@% title := 'Each line of text is centered.';%@NL@%
- %@AS@% ClrScr;%@NL@%
- %@AS@% center_line( title, row );%@NL@%
- %@AS@% center_line( '--------', row+1 );%@NL@%
- %@AS@% center_line( 'Microsoft QuickPascal!', row+2 );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP32003@%%@4@%The CENTER.PAS program displays these lines on the screen:%@EH@%%@NL@%
- %@NL@%
- %@AS@% Each line of text is centered.%@NL@%
- %@AS@% --------%@NL@%
- %@AS@% Microsoft QuickPascal!%@NL@%
- %@NL@%
- %@CR:MQP32004@%%@4@%The rest of this section refers frequently to the CENTER.PAS example.%@EH@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP32100@%%@3@%%@AB@%3.2.1 Calling Procedures%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP32101@%%@4@%The CENTER.PAS program uses a procedure named %@AS@%center_line%@AE@% to center a line.%@EH@%
- You "call," or execute, a procedure by stating its name and by supplying any
- "arguments," or data items that it might require. The %@AS@%center_line%@AE@% procedure
- expects you to supply two arguments: a piece of text to print, and the
- screen line on which to print it. To print the message%@NL@%
- %@NL@%
- %@AS@%Vite!%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP32102@%%@4@%on the second screen line, you would call %@AS@%center_line%@AE@% with this statement:%@EH@%%@NL@%
- %@NL@%
- %@AS@% center_line( 'Vite!', 2 );%@NL@%
- %@NL@%
- %@CR:MQP32103@%%@4@%You list the arguments in parentheses after the procedure name, placing a%@EH@%
- comma between each two arguments. Here, the first argument is the string
- %@AS@%Vite!%@AE@% and the second is the number %@AS@%2%@AE@%. Later in this chapter, you will learn
- how a procedure handles the arguments it receives.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP32200@%%@3@%%@AB@%3.2.2 Declaring Procedures%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP32201@%%@4@%A procedure "declaration" contains the complete code for the procedure. Here%@EH@%
- is the procedure declaration for %@AS@%center_line%@AE@%:%@NL@%
- %@NL@%
- %@AS@% PROCEDURE center_line( message : STRING; line : Byte );%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% GotoXY( 40 - Length( message ) DIV 2, line );%@NL@%
- %@AS@% Write( message );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQP32202@%%@4@%A procedure declaration has two parts, called the "head" and the "body." A%@EH@%
- procedure head consists of the %@AB@%PROCEDURE%@AE@% keyword, followed by the
- procedure's name and a list of its arguments in parentheses. It ends with a
- semicolon. Here is the head of the %@AS@%center_line%@AE@% procedure:%@NL@%
- %@NL@%
- %@AS@% PROCEDURE center_line( message : STRING; line : Byte );%@NL@%
- %@NL@%
- %@CR:MQP32203@%%@4@%The list of arguments states the name and type of each argument. This%@EH@%
- example states that %@AS@%center_line%@AE@% requires two arguments, one each of the data
- types %@AB@%STRING%@AE@% and %@AB@%BYTE%@AE@%. The first argument is named %@AS@%message,%@AE@% and the second
- argument is named %@AS@%line%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQP32204@%%@4@%The procedure body is a statement block that contains the procedure's%@EH@%
- executable statements. Like other blocks, the procedure body is enclosed in
- %@AB@%BEGIN%@AE@% and %@AB@%END%@AE@%, and it ends with a semicolon. Here is the body of the
- %@AS@%center_line%@AE@% procedure:%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% GotoXY( 40 - Length( message ) DIV 2, line );%@NL@%
- %@AS@% Write( message );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQP32205@%%@4@%The body of the %@AS@%center_line%@AE@% procedure contains two statements, each of which%@EH@%
- calls a standard Pascal procedure. The first calls the %@AB@%GotoXY%@AE@% procedure and
- the second calls %@AB@%Write%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQP32210@%%@4@%%@AB@%Forward Declarations%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP32211@%%@4@%Pascal requires that you declare an entity before using it. Before using a%@EH@%
- variable, for instance, you must declare its name and type. The same rule
- applies to a procedure. Before calling a procedure, you must declare it as
- explained in the previous section.%@NL@%
- %@NL@%
- %@CR:MQP32212@%%@4@%In simple programs, such as CENTER.PAS, it's easy to satisfy the "declare%@EH@%
- before calling" rule. Simply place all of your procedure declarations before
- the main program body. In CENTER.PAS, the %@AS@%center_line%@AE@% procedure declaration
- appears before the main program.%@NL@%
- %@NL@%
- %@CR:MQP32213@%%@4@%Occasionally, however, you may need to call a procedure before it has been%@EH@%
- declared. This can be done by providing a "forward declaration" of the
- procedure prior to the procedure call.%@NL@%
- %@NL@%
- %@CR:MQP32214@%%@4@%A forward declaration is identical to a procedure head, except that it%@EH@%
- contains both the keyword %@AB@%FORWARD%@AE@% and a semicolon after the argument list.
- For instance, the %@AS@%center_line%@AE@% procedure head looks like this%@NL@%
- %@NL@%
- %@AS@% PROCEDURE center_line( message : STRING; line : Byte );%@NL@%
- %@NL@%
- %@CR:MQP32215@%%@4@%and its forward declaration looks like this%@EH@%%@NL@%
- %@NL@%
- %@AS@% PROCEDURE center_line( message : STRING; line : Byte );%@NL@%
- %@AS@% FORWARD;%@NL@%
- %@NL@%
- %@CR:MQP32216@%%@4@%The forward declaration must appear before the first reference to the%@EH@%
- procedure. Most programmers put forward references at or very near the
- beginning of the program.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP32300@%%@3@%%@AB@%3.2.3 Declaring Local Variables%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP32301@%%@4@%In addition to statements, the procedure body can contain variable%@EH@%
- declarations. Variables declared in a procedure are said to be "local,"
- meaning they can be seen only inside the procedure. Because their visibility
- is limited, local variables are less likely to be changed accidentally than
- global variables.%@NL@%
- %@NL@%
- %@CR:MQP32302@%%@4@%The LOCAL.PAS program demonstrates local variables. It prompts you to enter%@EH@%
- a number and then displays the factorial of that number. (A factorial is the
- product of all the integers from 1 to a number. For instance, the factorial
- of 4 is 24, the product of 1 *) 2 * 3 * 4.)%@NL@%
- %@NL@%
- %@AS@% PROGRAM local_variables;%@NL@%
- %@NL@%
- %@AS@% { LOCAL.PAS: Demonstrate local variables. }%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% num : Byte;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE factor( value : Byte );%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% factorial : Real;%@NL@%
- %@AS@% count : Byte;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% factorial := 1.0;%@NL@%
- %@AS@% FOR count := 1 TO value DO%@NL@%
- %@AS@% factorial := factorial * count;%@NL@%
- %@AS@% Write( 'Factorial of ', value, ' is ' );%@NL@%
- %@AS@% Writeln( factorial );%@NL@%
- %@AS@% END; { procedure factor }%@NL@%
- %@NL@%
- %@AS@% BEGIN%@AE@% { main program }%@NL@%
- %@AS@% Write( 'Enter a number smaller than 34: ' );%@NL@%
- %@AS@% Readln( num );%@NL@%
- %@AS@% Factor( num );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP32303@%%@4@%Here is typical output from LOCAL.PAS:%@EH@%%@NL@%
- %@NL@%
- %@AS@%Enter a number smaller than 34: 5%@AE@%%@NL@%
- %@AS@%Factorial of 5 is 1.20000000000000E+0002%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP32304@%%@4@%The %@AS@%factor%@AE@% procedure in LOCAL.PAS appears below. It declares two local%@EH@%
- variables named %@AS@%factorial%@AE@% and %@AS@%count%@AE@%:%@NL@%
- %@NL@%
- %@AS@% PROCEDURE factor( value : Byte );%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% factorial : Real;%@NL@%
- %@AS@% count : Byte;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% factorial := 1.0;%@NL@%
- %@AS@% FOR count := 1 TO value DO%@NL@%
- %@AS@% factorial := factorial * count;%@NL@%
- %@AS@% Write( 'Factorial of ', value,' is ' );%@NL@%
- %@AS@% Writeln( factorial );%@NL@%
- %@AS@% END; { procedure factor }%@NL@%
- %@NL@%
- %@CR:MQP32305@%%@4@%Notice where local variables are declared: between the procedure's head and%@EH@%
- the %@AB@%BEGIN%@AE@% keyword.%@NL@%
- %@NL@%
- %@CR:MQP32310@%%@4@%%@AB@%Variable Scope%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP32311@%%@4@%Unlike global variables, which are declared outside any procedure and are%@EH@%
- therefore visible everywhere in the program, local variables are declared
- inside a procedure and are hidden from the rest of the program. If you refer
- to a local variable outside the "scope," or range, where it is visible,
- QuickPascal issues an error message:%@NL@%
- %@NL@%
- %@AS@%Error P0032: Unknown identifier%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP32312@%%@4@%The same message appears if you refer to a variable that has never been%@EH@%
- declared. In both cases, it means the variable is not visible──and cannot be
- used──in the place where the reference appears.%@NL@%
- %@NL@%
- %@CR:MQP32313@%%@4@%The ability to limit a variable's visibility makes it easier to write%@EH@%
- reliable programs. If a variable is local, it can't be changed accidentally
- by some other part of the program. Such haphazard side effects are common in
- older interpreted BASIC programs, in which all variables are global.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP32400@%%@3@%%@AB@%3.2.4 Passing Arguments%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP32401@%%@4@%The %@AS@%Factor%@AE@% procedure in LOCAL.PAS has another local variable that hasn't%@EH@%
- been mentioned yet. In addition to %@AS@%factorial%@AE@% and %@AS@%count%@AE@%, which it declares,
- the procedure uses a third variable named %@AS@%value%@AE@%:%@NL@%
- %@NL@%
- %@AS@% PROCEDURE Factor( value: Byte );%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% factorial : Real;%@NL@%
- %@AS@% count : Byte;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% factorial := 1.0;%@NL@%
- %@AS@% FOR count := 1 TO value DO%@NL@%
- %@AS@% factorial := factorial * count;%@NL@%
- %@AS@% Write( 'Factorial of ', value,' is ' )%@NL@%
- %@AS@% Writeln( factorial );%@NL@%
- %@AS@% END; { procedure factor }%@NL@%
- %@NL@%
- %@CR:MQP32402@%%@4@%The %@AS@%value%@AE@% argument, in the procedure head, is "passed" when you call the%@EH@%
- %@AS@%factor%@AE@% procedure. The argument comes from a number you type in at the
- keyboard. The main procedure in LOCAL.PAS stores your input in a variable
- named %@AS@%num%@AE@%:%@NL@%
- %@NL@%
- %@AS@% Writeln( 'Enter a number smaller than 34: ' );%@NL@%
- %@AS@% Readln( num );%@NL@%
- %@NL@%
- %@CR:MQP32403@%%@4@%The main program passes the value of %@AS@%num%@AE@% as an argument when it calls the%@EH@%
- %@AS@%factor%@AE@% procedure:%@NL@%
- %@NL@%
- %@AS@% factor( num );%@NL@%
- %@NL@%
- %@CR:MQP32404@%%@4@%When you list an argument in the procedure head, it becomes a local variable%@EH@%
- in the procedure. Thus, the head of the %@AS@%factor%@AE@% procedure%@NL@%
- %@NL@%
- %@AS@% PROCEDURE Factor( value : Byte );%@NL@%
- %@NL@%
- %@CR:MQP32405@%%@4@%creates a local variable named %@AS@%value%@AE@%. Inside the %@AS@%factor%@AE@% procedure, %@AS@%value%@AE@%%@EH@%
- can be treated like any other local variable.%@NL@%
- %@NL@%
- %@CR:MQP32410@%%@4@%%@AB@%3.2.4.1 Passing by Value%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP32411@%%@4@%The type of argument passing in LOCAL.PAS is called "passing by value"%@EH@%
- because the procedure receives %@AI@%the value of%@AE@% the original variable, not the
- variable itself. The BYVALUE.PAS program demonstrates this idea, which has
- important consequences for managing variables:%@NL@%
- %@NL@%
- %@AS@% PROGRAM byvalue;%@NL@%
- %@NL@%
- %@AS@% { BYVALUE.PAS: Demonstrate passing by value. }%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% global_var : Integer;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE proc( local_var : Integer );%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'local_var = ', local_var );%@NL@%
- %@AS@% local_var := 333;%@NL@%
- %@AS@% Writeln( 'local_var = ', local_var );%@NL@%
- %@AS@% END; { procedure proc }%@NL@%
- %@NL@%
- %@AS@% BEGIN { main program }%@NL@%
- %@AS@% global_var := 5;%@NL@%
- %@AS@% proc( global_var );%@NL@%
- %@AS@% Writeln( 'global_var = ', global_var );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP32412@%%@4@%Here is the output from BYVALUE.PAS:%@EH@%%@NL@%
- %@NL@%
- %@AS@%local_var = 5%@AE@%%@NL@%
- %@AS@%local_var = 333%@AE@%%@NL@%
- %@AS@%global_var = 5%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP32413@%%@4@%The program declares a global variable named %@AS@%global_var%@AE@% and assigns the%@EH@%
- value %@AS@%5%@AE@% to %@AS@%global_var%@AE@%. The %@AS@%proc%@AE@% procedure expects you to pass one argument,
- which it names %@AS@%local_var%@AE@%. The procedure prints the value of %@AS@%local_var%@AE@%
- (initially, %@AS@%5%@AE@%), then changes its value to %@AS@%333%@AE@% and prints it again. After
- control returns to the main program, BYVALUE.PAS prints the value of
- %@AS@%global_var%@AE@%, which remains at %@AS@%5%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQP32414@%%@4@%The %@AS@%proc%@AE@% procedure alters the value of %@AS@%local_var%@AE@%. But this change has no%@EH@%
- effect on the original variable,%@AS@%global_var%@AE@%, which is not affected by
- anything that happens in %@AS@%proc%@AE@%. The same is true even if both variables have
- the same name (if you name both of them %@AS@%my_val%@AE@%, for instance).%@NL@%
- %@NL@%
- %@CR:MQP32415@%%@4@%Passing an argument by value creates a local copy of the variable in the%@EH@%
- procedure. Because the procedure receives only a local copy, it can give the
- argument any name, and change its value, without affecting variables
- outside the procedure.%@NL@%
- %@NL@%
- %@CR:MQP32420@%%@4@%%@AB@%3.2.4.2 Passing by Reference%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP32421@%%@4@%Sometimes, you may want a procedure to change the value of an argument. For%@EH@%
- instance, say you need a procedure that swaps two variables. If you pass the
- variables by value, their values change inside the swap procedure, but
- remain unchanged in the rest of the program. You need a way to tell the
- procedure to change the original variables, not its local copies of them.%@NL@%
- %@NL@%
- %@CR:MQP32422@%%@4@%Pascal offers a second passing method, called "passing by reference," for%@EH@%
- just such cases. The BYREF.PAS program demonstrates this method:%@NL@%
- %@NL@%
- %@AS@% PROGRAM byref;%@NL@%
- %@NL@%
- %@AS@% { BYREF.PAS: Demonstrate passing by reference. }%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% var1, var2 : Integer;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE swap_vars(VAR var1 : Integer; VAR var2 : Integer);%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% temp : Integer;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% temp := var1;%@NL@%
- %@AS@% var1 := var2;%@NL@%
- %@AS@% var2 := temp;%@NL@%
- %@AS@% END; { procedure swap_vars }%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% var1 := 55;%@NL@%
- %@AS@% var2 := 99;%@NL@%
- %@AS@% Writeln( 'var1 = ', var1, ' var2 = ', var2 );%@NL@%
- %@AS@% swap_vars( var1, var2 );%@NL@%
- %@AS@% Writeln( 'var1 = ', var1, ' var2 = ', var2 );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP32423@%%@4@%Here is the output from BYREF.PAS:%@EH@%%@NL@%
- %@NL@%
- %@AS@%var1 = 55 var2 = 99%@AE@%%@NL@%
- %@AS@%var1 = 99 var2 = 55%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP32424@%%@4@%The program declares two global variables named %@AS@%var1%@AE@% and %@AS@%var2%@AE@%, assigning%@EH@%
- them the values %@AS@%55%@AE@% and %@AS@%99%@AE@%, respectively. It prints their values, calls the
- %@AS@%swap_vars%@AE@% procedure, then prints their values again. The output proves that
- %@AS@%swap_vars%@AE@% changes the original variables.%@NL@%
- %@NL@%
- %@CR:MQP32425@%%@4@%The important difference between this program and the previous example%@EH@%
- appears in the %@AS@%swap_vars%@AE@% procedure head:%@NL@%
- %@NL@%
- %@AS@% PROCEDURE swap_vars(VAR var1 : Integer; VAR var2: Integer);%@NL@%
- %@NL@%
- %@CR:MQP32426@%%@4@%Notice the %@AB@%VAR%@AE@% keyword in front of each name in the argument list. It tells%@EH@%
- the %@AS@%swap_vars%@AE@% procedure to treat the argument as a variable (located
- elsewhere) rather than as a value. Instead of creating a local copy of the
- passed value, the procedure acts upon the variable itself.%@NL@%
- %@NL@%
- %@CR:MQP32427@%%@4@%The %@AS@%swap_vars%@AE@% procedure head happens to use the same names for these%@EH@%
- arguments (%@AS@%var1%@AE@% and %@AS@%var2%@AE@%) in its argument list. But the result would be the
- same if %@AS@%swap_vars%@AE@% used different names. Because the arguments are declared
- with %@AB@%VAR%@AE@%, their names in %@AS@%swap_vars%@AE@% are synonyms for the original variables.%@NL@%
- %@NL@%
- %@CR:MQP32428@%%@4@%You can underscore this point by making a simple change to the previous%@EH@%
- example, BYVALUE.PAS. Load the program and add %@AB@%VAR%@AE@% to the %@AS@%proc%@AE@% procedure
- head:%@NL@%
- %@NL@%
- %@AS@% PROCEDURE proc( VAR local_var : Integer );%@NL@%
- %@NL@%
- %@CR:MQP32429@%%@4@%After you make this change, the %@AS@%proc%@AE@% procedure changes the global variable%@EH@%
- %@AS@%global_var%@AE@%, giving this output:%@NL@%
- %@NL@%
- %@AS@%local_var = 5%@AE@%%@NL@%
- %@AS@%local_var = 333%@AE@%%@NL@%
- %@AS@%global_var = 333%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP3242A@%%@4@%In the original BYVALUE.PAS program, the global variable %@AS@%global_var%@AE@%%@EH@%
- retained the value %@AS@%5%@AE@% even though %@AS@%proc%@AE@% changed the value of %@AS@%local_var%@AE@%.
- Passing %@AS@%global_var%@AE@% by reference gives %@AS@%proc%@AE@% the ability to modify %@AS@%global_var%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQP3242B@%%@4@%When you pass an argument by reference, you must pass a variable, not a%@EH@%
- value. That is, the argument must be a variable name,%@NL@%
- %@NL@%
- %@AS@% swap_vars( global_1, global_2 ); { correct }%@NL@%
- %@NL@%
- %@CR:MQP3242C@%%@4@%not a constant,%@EH@%%@NL@%
- %@NL@%
- %@AS@% swap_vars( 55, 99 ); { error! }%@NL@%
- %@NL@%
- %@CR:MQP3242D@%%@4@%or an expression:%@EH@%%@NL@%
- %@NL@%
- %@AS@% swap_vars( 5 * 11, 93 + 6 ); { error! }%@NL@%
- %@NL@%
- %@CR:MQP3242E@%%@4@%It's best to pass arguments by reference only when you want the procedure to%@EH@%
- change the argument. Unnecessary passing by reference creates the same
- problems as the overuse of global variables.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP33000@%%@2@%%@AB@%3.3 Functions%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP33001@%%@4@%A function is a procedure that returns a value. Like most languages, Pascal%@EH@%
- has many standard functions, such as %@AB@%Sqrt%@AE@%, which returns a square root.%@NL@%
- %@NL@%
- %@CR:MQP33002@%%@4@%You can think of a function as a special kind of procedure. All of the%@EH@%
- concepts explained in Section 3.2%@BO: 145ab@%, "Procedures," also apply to functions.
- Rather than restate everything that procedures and functions share in
- common, this section explains the features that make functions different
- from procedures.%@NL@%
- %@NL@%
- %@CR:MQP33003@%%@4@%The FUNCT.PAS program contains a simple function:%@EH@%%@NL@%
- %@NL@%
- %@AS@% PROGRAM FUNCT;%@NL@%
- %@NL@%
- %@AS@% { FUNCT.PAS: Demonstrate function basics. }%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% num, expo, powr : Real;%@NL@%
- %@NL@%
- %@AS@% FUNCTION power( base, exponent : Real ) : Real;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% IF (base > 0) THEN%@NL@%
- %@AS@% Power := Exp( exponent * Ln( base ) )%@NL@%
- %@AS@% ELSE%@NL@%
- %@AS@% Power := -1.0;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Write( 'Enter a number: ' );%@NL@%
- %@AS@% Readln( num );%@NL@%
- %@AS@% Write( 'Enter an exponent: ' );%@NL@%
- %@AS@% Readln( expo );%@NL@%
- %@AS@% powr := Power( num, expo );%@NL@%
- %@AS@% Writeln( num, ' ^ ', expo, ' = ', powr );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP33004@%%@4@%The FUNCT.PAS program prompts you to enter two numbers, a base and an%@EH@%
- exponent. Then it calls the %@AS@%power%@AE@% function to raise the base to the
- exponent. Typical output appears below:%@NL@%
- %@NL@%
- %@AS@%Enter a number: 2%@AE@%%@NL@%
- %@AS@%Enter an exponent: 8%@AE@%%@NL@%
- %@NL@%
- %@AS@%2.00000000000000E+0000 ^ 8.00000000000000E+0000 = 2.56000000000000E+0002%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP33005@%%@4@%FUNCT.PAS raises %@AS@%2%@AE@% to the eighth power, giving a result of %@AS@%256%@AE@%.%@EH@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP33100@%%@3@%%@AB@%3.3.1 Calling Functions%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP33101@%%@4@%Function calls are identical to procedure calls. You state the function's%@EH@%
- name, listing in parentheses any arguments that the function requires. The
- only difference is in where the call can appear. A procedure call can stand
- alone as a statement, but a function call, because it returns a value, must
- appear in an assignment or expression.%@NL@%
- %@NL@%
- %@CR:MQP33102@%%@4@%The following statement from FUNCT.PAS calls the %@AS@%power%@AE@% function, assigning%@EH@%
- its return value to the variable %@AS@%powr%@AE@%:%@NL@%
- %@NL@%
- %@AS@% powr := power( num, expo );%@NL@%
- %@NL@%
- %@CR:MQP33103@%%@4@%Notice the similarity to a procedure call. The %@AS@%power%@AE@% function takes two%@EH@%
- arguments, which are listed in parentheses after the function name.%@NL@%
- %@NL@%
- %@CR:MQP33104@%%@4@%The previous example uses the function call in an assignment. Function calls%@EH@%
- can also appear in expressions:%@NL@%
- %@NL@%
- %@AS@% dazzle := 12 * surprise( 730, 88 ) / 2;%@NL@%
- %@NL@%
- %@CR:MQP33105@%%@4@%Here, the %@AS@%surprise%@AE@% function appears as part of the expression to the right%@EH@%
- of the assignment symbol.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP33200@%%@3@%%@AB@%3.3.2 Returning Values from Functions%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP33201@%%@4@%A function returns a value by assigning the value to its own name. In the%@EH@%
- %@AS@%power%@AE@% function, for instance, this statement causes the function to return
- the value %@AS@%-1.0%@AE@%:%@NL@%
- %@NL@%
- %@AS@% power := -1.0;%@NL@%
- %@NL@%
- %@CR:MQP33202@%%@4@%The return value must match the type declared in the function head. Since%@EH@%
- the %@AS@%power%@AE@% function returns a value of type %@AB@%Real%@AE@%, the above statement uses
- the value %@AS@%-1.0%@AE@% (with a decimal point).%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP33300@%%@3@%%@AB@%3.3.3 Declaring Functions%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP33301@%%@4@%Function declarations are identical to procedure declarations except that%@EH@%
- you substitute %@AB@%FUNCTION%@AE@% for %@AB@%PROCEDURE%@AE@% and declare the function's return type
- after the argument list. Below is the function head from FUNCT.PAS:%@NL@%
- %@NL@%
- %@AS@% FUNCTION power( base, exponent : Real ) : Real;%@NL@%
- %@NL@%
- %@CR:MQP33302@%%@4@%Following the argument list, separated by a colon, is the identifier %@AB@%Real%@AE@%,%@EH@%
- which indicates that the %@AS@%power%@AE@% function returns a value of type %@AB@%Real.%@AE@% If
- %@AS@%power%@AE@% returned an integer value, you would replace the %@AB@%Real%@AE@% with%@AB@%Integer%@AE@%, and
- so on.%@NL@%
- %@NL@%
- %@CR:MQP33303@%%@4@%Again, except for the differences noted in this section, functions are%@EH@%
- identical to procedures. They can handle arguments and local variables
- exactly as described in Section 3.2%@BO: 145ab@%, "Procedures."%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP34000@%%@2@%%@AB@%3.4 Nested Procedures%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP34001@%%@4@%In addition to local variables, a procedure can declare other procedures.%@EH@%
- You can "hide" one procedure declaration inside another. Like a local
- variable, the hidden procedure is visible only in the procedure where it is
- declared. This feature, which is unique to Pascal, allows you to limit the
- visibility of a procedure (and that procedure's local variables) in the same
- way you limit the visibility of local variables. Nesting applies to both
- procedures and functions.%@NL@%
- %@NL@%
- %@CR:MQP34002@%%@4@%The HIDEPROC.PAS program demonstrates procedure nesting:%@EH@%%@NL@%
- %@NL@%
- %@AS@% PROGRAM hideproc;%@NL@%
- %@NL@%
- %@AS@% { HIDEPROC.PAS: Demonstrate procedure nesting. }%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% globl : Integer;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE proc( p_parm : Integer );%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% p_locl: Integer;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE hidden( hidn_parm : Integer );%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% hidn_locl: Integer;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'hidden can see: globl, p_parm, '+%@NL@%
- %@AS@% 'p_locl, hidn_parm, hidn_locl' );%@NL@%
- %@AS@% END; { hidden procedure }%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'Proc can see: globl, p_parm, p_locl' );%@NL@%
- %@AS@% hidden( 44 ); { Pass argument to hidden }%@NL@%
- %@AS@% END; { proc }%@NL@%
- %@NL@%
- %@AS@% BEGIN { main program }%@NL@%
- %@AS@% Writeln( 'Main program can see: globl' );%@NL@%
- %@AS@% proc( 99 ); { Pass argument to proc }%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP34003@%%@4@%HIDEPROC.PAS produces this output:%@EH@%%@NL@%
- %@NL@%
- %@AS@%Main program can see: globl%@AE@%%@NL@%
- %@AS@%Proc can see: globl, p_parm, p_locl%@AE@%%@NL@%
- %@AS@%Hidden can see: globl, p_parm, p_locl, hidn_parm, hidn_locl%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP34004@%%@4@%The program has two procedures named %@AS@%proc%@AE@% and %@AS@%hidden%@AE@%. Because the %@AS@%hidden%@AE@%%@EH@%
- procedure declaration appears in the %@AS@%proc%@AE@% declaration, %@AS@%hidden%@AE@% is visible
- only inside %@AS@%proc%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQP34005@%%@4@%The program's output shows how nesting affects variable visibility. At the%@EH@%
- deepest level in HIDEPROC.PAS──inside %@AS@%hidden%@AE@%──all of the program's variables
- are visible. The %@AS@%hidden%@AE@% procedure can see its own local variables, plus the
- variables local to the %@AS@%proc%@AE@% procedure, plus all of the global variables. At
- the next level──inside %@AS@%proc%@AE@%──visibility is more restricted. The %@AS@%proc%@AE@%
- procedure can see its own local variables and the global variables, but not
- the variables local to %@AS@%hidden%@AE@%. The main program has the most restricted
- visibility. It can see only global variables.%@NL@%
- %@NL@%
- %@CR:MQP34006@%%@4@%Nesting also affects the visibility of a procedure itself. The %@AS@%hidden%@AE@%%@EH@%
- procedure can be called only from the %@AS@%proc%@AE@% procedure, where it is declared.
- If you call %@AS@%hidden%@AE@% from the main program, QuickPascal issues an error, just
- as it would if the main program referred to one of the local variables in
- %@AS@%proc%@AE@%.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP35000@%%@2@%%@AB@%3.5 Recursion%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP35001@%%@4@%"Recursion" is the ability of a procedure or function to call itself. The%@EH@%
- primary use of recursion is in solving certain mathematical problems that
- require repetitive operations.%@NL@%
- %@NL@%
- %@CR:MQP35002@%%@4@%The RECURSE.PAS program demonstrates recursion. It is a revision of the%@EH@%
- LOCAL.PAS program that demonstrated local variables. Like its predecessor,
- RECURSE.PAS computes a factorial. But instead of a loop, it uses a recursive
- function named %@AS@%factor%@AE@%:%@NL@%
- %@NL@%
- %@AS@% PROGRAM recurse;%@NL@%
- %@NL@%
- %@AS@% { RECURSE.PAS: Demonstrate recursion. }%@NL@%
- %@NL@%
- %@AS@% USES%@NL@%
- %@AS@% Crt;%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% num : Byte;%@NL@%
- %@AS@% result : Real;%@NL@%
- %@NL@%
- %@AS@% FUNCTION factor( value : Byte ) : Real;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% IF (value > 1) THEN%@NL@%
- %@AS@% factor := value * factor( value - 1 )%@NL@%
- %@AS@% ELSE%@NL@%
- %@AS@% factor := 1.0;%@NL@%
- %@AS@% END; { factor }%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Write( 'Enter a number smaller than 34: ' );%@NL@%
- %@AS@% Readln( num );%@NL@%
- %@AS@% result := factor( num );%@NL@%
- %@AS@% Write( 'Factorial of ', num, ' is ' );%@NL@%
- %@AS@% Writeln( result );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP35003@%%@4@%The output from RECURSE.PAS and LOCAL.PAS is identical:%@EH@%%@NL@%
- %@NL@%
- %@AS@%Enter a number smaller than 34: 5%@AE@%%@NL@%
- %@AS@%Factorial of 5 is 1.20000000000000E+0002%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP35004@%%@4@%The only difference between normal functions and recursive functions is that%@EH@%
- a recursive function contains a statement that calls itself. Here is the
- recursive statement in RECURSE.PAS:%@NL@%
- %@NL@%
- %@AS@% Factor := value * factor( value - 1 )%@NL@%
- %@NL@%
- %@CR:MQP35005@%%@4@%The expression on the right side of the assignment operator contains a call%@EH@%
- to the %@AS@%factor%@AE@% function. The first call to %@AS@%factor%@AE@% can trigger a second call,
- which can trigger a third call, and so on.%@NL@%
- %@NL@%
- %@CR:MQP35006@%%@4@%The %@AB@%IF%@AE@% statement at the beginning of the %@AS@%factor%@AE@% function prevents the%@EH@%
- function from calling itself endlessly. Every recursive procedure and
- function must include such an exit mechanism.%@NL@%
- %@NL@%
- %@CR:MQP35007@%%@4@%Most recursive procedures and functions exploit the fact that each%@EH@%
- invocation of a procedure or function creates a new set of local variables.
- Recursion can be very efficient in terms of programming time. You may be
- able to solve a complex math problem with only a few lines of code. But
- deeply recursive procedures can also be memory inefficient, consuming huge
- amounts of memory to store local variables.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP40000@%%@1@%%@AB@%Chapter 4 Controlling Program Flow%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQP40001@%%@4@%Like other high-level languages, Pascal offers a wide variety of ways to%@EH@%
- control a program's flow of execution. This chapter discusses looping
- statements, which perform repetitive actions, and decision-making
- statements, which transfer control based on logical tests. Before examining
- those statements in detail, this chapter briefly summarizes the operators
- used in logical tests.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP41000@%%@2@%%@AB@%4.1 Relational and Boolean Operators%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP41001@%%@4@%All of the looping and branching statements in Pascal depend on the outcome%@EH@%
- of a Boolean (true or false) test. Such tests use relational and Boolean
- operators, which look familiar to anyone who knows BASIC or C.%@NL@%
- %@NL@%
- %@CR:MQP41002@%%@4@%Even if you have never seen a line of Pascal code, you may be able to guess%@EH@%
- that the statement%@NL@%
- %@NL@%
- %@AS@% IF my_val = 20 THEN Writeln( 'my_val equals 20' );%@NL@%
- %@NL@%
- %@CR:MQP41003@%%@4@%prints the message%@EH@%%@NL@%
- %@NL@%
- %@AS@%my_val equals 20%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP41004@%%@4@%if the value of the variable %@AS@%my_val%@AE@% equals %@AS@%20%@AE@%. (The Pascal %@AB@%IF%@AE@% statement, as%@EH@%
- you'll read later in this chapter, works very much like %@AB@%IF%@AE@% in BASIC and C.)%@NL@%
- %@NL@%
- %@CR:MQP41005@%%@4@%The example uses the equality operator (%@AB@%=%@AE@%) to compare the variable %@AS@%my_val%@AE@% to%@EH@%
- the constant %@AS@%20%@AE@%. It produces a %@AB@%True%@AE@% result when %@AS@%my_val%@AE@% equals %@AS@%20%@AE@%, and a
- %@AB@%False%@AE@% result in every other case.%@NL@%
- %@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@AI@%NOTE%@AE@%%@NL@%
- %@AB@%True%@AE@% and %@AB@%False%@AE@% are symbolic values in Pascal. Although they are%@NL@%
- represented by actual numbers internally, you don't need to worry about%@NL@%
- what those numbers are.%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQP41006@%%@4@%Relational operators, including the equality operator, compare two values%@EH@%
- and produce a %@AB@%True%@AE@% or %@AB@%False%@AE@% result. Table 4.1 lists all of the Pascal
- relational operators.%@NL@%
- %@NL@%
- %@CR:MQP4T100@%%@4@%%@AB@%Table 4.1 Relational Operators%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Operator Description%@AE@%%@NL@%
- %@NL@%
- %@AB@%=%@AE@% Equal%@NL@%
- %@NL@%
- %@AB@%<>%@AE@% Not equal%@NL@%
- %@NL@%
- %@AB@%<%@AE@% Less than%@NL@%
- %@NL@%
- %@AB@%>%@AE@% Greater than%@NL@%
- %@NL@%
- %@AB@%<=%@AE@% Less than or equal%@NL@%
- %@NL@%
- %@AB@%>=%@AE@% Greater than or equal%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP41007@%%@4@%A second group of operators allows you to perform Boolean logical%@EH@%
- operations. They are listed in Table 4.2.%@NL@%
- %@NL@%
- %@CR:MQP4T200@%%@4@%%@AB@%Table 4.2 Boolean Operators%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Operator Description%@AE@%%@NL@%
- %@NL@%
- %@AB@%NOT%@AE@% Negation%@NL@%
- %@NL@%
- %@AB@%AND%@AE@% Logical %@AB@%AND%@AE@%%@NL@%
- %@NL@%
- %@AB@%OR%@AE@% Logical %@AB@%OR%@AE@%%@NL@%
- %@NL@%
- %@AB@%XOR%@AE@% Exclusive %@AB@%OR%@AE@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP41008@%%@4@%Boolean operators (except for %@AB@%NOT%@AE@%) can act on one or two values, allowing%@EH@%
- more complex logical tests. For instance, the statement%@NL@%
- %@NL@%
- %@AS@% IF ((my_val > 3) AND (my_val < 20)) THEN Writeln( 'Wahoo!');%@NL@%
- %@NL@%
- %@CR:MQP41009@%%@4@%tests two conditions instead of one. It prints the message%@EH@%%@NL@%
- %@NL@%
- %@AS@% Wahoo!%@NL@%
- %@NL@%
- %@CR:MQP4100A@%%@4@%if the value of %@AS@%my_val%@AE@% is greater than %@AS@%3%@AE@% and less than %@AS@%20%@AE@%.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP4100B@%%@4@%Pascal provides many more operators, but these are the important ones for%@EH@%
- controlling program flow. The QP Advisor contains information about all of
- the QuickPascal operators.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP42000@%%@2@%%@AB@%4.2 Looping Statements%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP42001@%%@4@%A loop performs one of the most basic computer operations: repeating an%@EH@%
- action. This section discusses the Pascal looping statements: %@AB@%WHILE%@AE@%, %@AB@%REPEAT%@AE@%,
- and %@AB@%FOR%@AE@%.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP42100@%%@3@%%@AB@%4.2.1 WHILE Loops%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP42101@%%@4@%A %@AB@%WHILE%@AE@% loop is the simplest kind of loop. It repeats 0 or more times, as%@EH@%
- long as a given condition remains true. The QWHILE.PAS program contains a
- simple %@AB@%WHILE%@AE@% loop.%@NL@%
- %@NL@%
- %@AS@% PROGRAM qwhile;%@NL@%
- %@NL@%
- %@AS@% { QWHILE.PAS: Demonstrate WHILE loop. }%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% count : Integer;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@NL@%
- %@AS@% count := 0;%@NL@%
- %@NL@%
- %@AS@% WHILE count < 10 DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'count = ', count );%@NL@%
- %@AS@% count := count + 2;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP42102@%%@4@%Here is the output from QWHILE.PAS:%@EH@%%@NL@%
- %@NL@%
- %@AS@%count = 0%@AE@%%@NL@%
- %@AS@%count = 2%@AE@%%@NL@%
- %@AS@%count = 4%@AE@%%@NL@%
- %@AS@%count = 6%@AE@%%@NL@%
- %@AS@%count = 8%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP42103@%%@4@%A %@AB@%WHILE%@AE@% loop begins with the %@AB@%WHILE%@AE@% keyword followed by a condition. The loop%@EH@%
- repeats as long as the condition remains true. In QWHILE.PAS, the condition
- is%@NL@%
- %@NL@%
- %@AS@% count < 10%@NL@%
- %@NL@%
- %@CR:MQP42104@%%@4@%so the loop continues as long as the value of the variable %@AS@%count%@AE@% is less%@EH@%
- than %@AS@%10%@AE@%. After the condition is the %@AB@%DO%@AE@% keyword followed by a "loop body,"
- which can be a single statement or a statement block. In QWHILE.PAS, the
- loop body is a statement block:%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'count = ', count );%@NL@%
- %@AS@% count := count + 2;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQP42105@%%@4@%You should enclose the body of a %@AB@%WHILE%@AE@% loop with %@AB@%BEGIN%@AE@% and %@AB@%END%@AE@%, even if the%@EH@%
- loop is only one statement. This convention prevents any confusion about
- where the loop body ends.%@NL@%
- %@NL@%
- %@CR:MQP42106@%%@4@%It's important to know that a %@AB@%WHILE%@AE@% loop tests its condition %@AI@%before%@AE@% it%@EH@%
- executes the loop body. Unlike some other kinds of loops, it's possible for
- a %@AB@%WHILE%@AE@% loop to skip everything in its loop body. If the test condition is
- false when a %@AB@%WHILE%@AE@% loop begins, the loop body does not execute at all. For
- instance, if %@AS@%count%@AE@% has the value %@AS@%10%@AE@% when the above loop begins, QWHILE.PAS
- doesn't print anything.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP42200@%%@3@%%@AB@%4.2.2 REPEAT Loops%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP42201@%%@4@%A %@AB@%REPEAT%@AE@% loop is an inverted %@AB@%WHILE%@AE@% loop. It tests the condition %@AI@%after%@AE@% it%@EH@%
- executes the loop body, and the loop repeats %@AI@%until%@AE@% the test condition
- becomes true.%@NL@%
- %@NL@%
- %@CR:MQP42202@%%@4@%The QREPEAT.PAS program performs the same task as QWHILE.PAS, but it uses a%@EH@%
- %@AB@%REPEAT%@AE@% loop instead of a %@AB@%WHILE%@AE@% loop.%@NL@%
- %@NL@%
- %@AS@% PROGRAM qrepeat;%@NL@%
- %@NL@%
- %@AS@% { QREPEAT.PAS: Demonstrate REPEAT loop. }%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% count : Integer;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@NL@%
- %@AS@% count := 0;%@NL@%
- %@NL@%
- %@AS@% REPEAT%@NL@%
- %@AS@% Writeln( 'count = ', count );%@NL@%
- %@AS@% count := count + 2;%@NL@%
- %@AS@% UNTIL ( count > 8 );%@NL@%
- %@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP42203@%%@4@%The output from QREPEAT.PAS and QWHILE.PAS is identical:%@EH@%%@NL@%
- %@NL@%
- %@AS@%count = 0%@AE@%%@NL@%
- %@AS@%count = 2%@AE@%%@NL@%
- %@AS@%count = 4%@AE@%%@NL@%
- %@AS@%count = 6%@AE@%%@NL@%
- %@AS@%count = 8%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP42204@%%@4@%The %@AB@%REPEAT%@AE@% loop in QREPEAT.PAS contains the same loop body as the %@AB@%WHILE%@AE@% loop%@EH@%
- in QWHILE.PAS:%@NL@%
- %@NL@%
- %@AS@% REPEAT%@NL@%
- %@AS@% Writeln( 'count = ', count );%@NL@%
- %@AS@% count := count + 2;%@NL@%
- %@AS@% UNTIL ( count > 8 );%@NL@%
- %@NL@%
- %@CR:MQP42205@%%@4@%You don't need to enclose the loop body of a %@AB@%REPEAT%@AE@% loop with the %@AB@%BEGIN%@AE@% and%@EH@%
- %@AB@%END%@AE@% keywords (although adding them does no harm). Since the loop body is
- already enclosed between two keywords (%@AB@%REPEAT%@AE@% and %@AB@%UNTIL%@AE@%), there can be no
- confusion about where the block begins and ends.%@NL@%
- %@NL@%
- %@CR:MQP42206@%%@4@%Remember that a %@AB@%REPEAT%@AE@% loop always executes the loop body at least once. If%@EH@%
- %@AS@%count%@AE@% has the value %@AS@%10%@AE@% when the loop begins, QREPEAT.PAS prints%@NL@%
- %@NL@%
- %@AS@% count = 10%@NL@%
- %@NL@%
- %@CR:MQP42207@%%@4@%even though %@AS@%10%@AE@% is clearly greater than %@AS@%8%@AE@%, the cutoff value in the test%@EH@%
- condition. The value of %@AS@%count%@AE@% is not tested until after the loop body has
- executed.%@NL@%
- %@NL@%
- %@CR:MQP42208@%%@4@%Notice that %@AB@%WHILE%@AE@% and %@AB@%REPEAT%@AE@% loops use opposite logical tests. A %@AB@%WHILE%@AE@% loop%@EH@%
- continues %@AI@%as long as%@AE@% the test condition is true, but a %@AB@%REPEAT%@AE@% loop continues
- %@AI@%until%@AE@% the test condition becomes true (or, to put it differently, as long as
- the test condition is false). To illustrate, the %@AB@%WHILE%@AE@% loop in QWHILE.PAS
- continues as long as %@AS@%count%@AE@% is less than %@AS@%10%@AE@%:%@NL@%
- %@NL@%
- %@AS@% count < 10%@NL@%
- %@NL@%
- %@CR:MQP42209@%%@4@%However, the %@AB@%REPEAT%@AE@% loop in QREPEAT.PAS continues until %@AS@%count%@AE@% becomes%@EH@%
- greater than %@AS@%8%@AE@%:%@NL@%
- %@NL@%
- %@AS@% count > 8%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP42300@%%@3@%%@AB@%4.2.3 FOR Loops%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP42301@%%@4@%%@AB@%WHILE%@AE@% and %@AB@%REPEAT%@AE@% loops are ideal for cases in which you cannot predict how%@EH@%
- many repetitions are needed. A program that gets keyboard input, for
- instance, might use %@AB@%REPEAT%@AE@% to repeat an action until you press a certain
- key. Sometimes, however, you know in advance exactly how many repetitions
- are required.%@NL@%
- %@NL@%
- %@CR:MQP42302@%%@4@%The %@AB@%FOR%@AE@% loop repeats a statement, or statement block, a set number of times.%@EH@%
- The QFOR.PAS program contains a simple %@AB@%FOR%@AE@% loop:%@NL@%
- %@NL@%
- %@AS@% PROGRAM qfor;%@NL@%
- %@NL@%
- %@AS@% { QFOR.PAS: Demonstrate FOR loop. }%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% count : Integer;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@NL@%
- %@AS@% FOR count := 0 TO 10 DO%@NL@%
- %@AS@% Writeln( 'count = ', count );%@NL@%
- %@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP42303@%%@4@%QFOR.PAS produces this output:%@EH@%%@NL@%
- %@NL@%
- %@AS@%count = 0%@AE@%%@NL@%
- %@AS@%count = 1%@AE@%%@NL@%
- %@AS@%count = 2%@AE@%%@NL@%
- %@AS@%count = 3%@AE@%%@NL@%
- %@AS@%count = 4%@AE@%%@NL@%
- %@AS@%count = 5%@AE@%%@NL@%
- %@AS@%count = 6%@AE@%%@NL@%
- %@AS@%count = 7%@AE@%%@NL@%
- %@AS@%count = 8%@AE@%%@NL@%
- %@AS@%count = 9%@AE@%%@NL@%
- %@AS@%count = 10%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP42304@%%@4@%The %@AB@%FOR%@AE@% loop in QFOR.PAS counts from %@AS@%0%@AE@% to %@AS@%10%@AE@% in increments of 1:%@EH@%%@NL@%
- %@NL@%
- %@AS@% FOR count := 0 TO 10 DO%@NL@%
- %@AS@% Writeln( 'count = ', count );%@NL@%
- %@NL@%
- %@CR:MQP42305@%%@4@%In this example the control variable %@AS@%count%@AE@% is first set to %@AS@%0%@AE@%. Each%@EH@%
- repetition executes the loop body once and adds 1 to %@AS@%count%@AE@% until %@AS@%count%@AE@%
- reaches %@AS@%10%@AE@%, the terminating value.%@NL@%
- %@NL@%
- %@CR:MQP42306@%%@4@%%@AB@%FOR%@AE@% loops can count down as well as up. The %@AB@%TO%@AE@% keyword makes the loop count%@EH@%
- up in increments of 1, and %@AB@%DOWNTO%@AE@% has the opposite effect. If you substitute
- this loop in QFOR.PAS, the loop counts down from %@AS@%10%@AE@% to%@AS@%0%@AE@% in increments of 1:%@NL@%
- %@NL@%
- %@AS@% FOR count := 10 DOWNTO 0 DO%@NL@%
- %@AS@% Writeln( 'count = ', count );%@NL@%
- %@NL@%
- %@CR:MQP42307@%%@4@%The loop body in QFOR.PAS happens to be a single statement. If the loop body%@EH@%
- is a statement block, you must enclose the block with %@AB@%BEGIN%@AE@% and %@AB@%END%@AE@%
- statements:%@NL@%
- %@NL@%
- %@AS@% FOR count := 0 TO 10 DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'count = ', count );%@NL@%
- %@AS@% Writeln( 'Another statement' );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP43000@%%@2@%%@AB@%4.3 Decision-Making Statements%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP43001@%%@4@%Decision-making statements allow your program to perform different actions%@EH@%
- based on the outcome of a logical test. This section examines the Pascal
- decision-making statements: %@AB@%IF%@AE@% and %@AB@%CASE%@AE@%.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP43100@%%@3@%%@AB@%4.3.1 IF Statements%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP43101@%%@4@%An %@AB@%IF%@AE@% statement consists of the %@AB@%IF%@AE@% keyword followed by a test expression and%@EH@%
- the %@AB@%THEN%@AE@% keyword. After %@AB@%THEN%@AE@% is a statement or statement block. The
- statement is executed if the test expression is true, or skipped if it is
- false.%@NL@%
- %@NL@%
- %@CR:MQP43102@%%@4@%The QIF.PAS program contains a simple %@AB@%IF%@AE@% statement:%@EH@%%@NL@%
- %@NL@%
- %@AS@% PROGRAM qif;%@NL@%
- %@NL@%
- %@AS@% { QIF.PAS: Demonstrate IF statement. }%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% my_val : Integer;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@NL@%
- %@AS@% my_val := 3;%@NL@%
- %@NL@%
- %@AS@% IF (my_val = 3) THEN Writeln( 'my_val equals 3' );%@NL@%
- %@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP43103@%%@4@%Here is the %@AB@%IF%@AE@% statement from QIF.PAS:%@EH@%%@NL@%
- %@NL@%
- %@AS@% IF (my_val = 3) THEN Writeln( 'my_val equals 3' );%@NL@%
- %@NL@%
- %@CR:MQP43104@%%@4@%In this statement the test condition%@EH@%%@NL@%
- %@NL@%
- %@AS@% (my_val = 3)%@NL@%
- %@NL@%
- %@CR:MQP43105@%%@4@%compares the variable %@AS@%my_val%@AE@% to the constant %@AS@%3%@AE@%. Since the comparison is%@EH@%
- true (%@AS@%my_val%@AE@% does equal %@AS@%3%@AE@%), QIF.PAS prints:%@NL@%
- %@NL@%
- %@AS@% my_val equals 3%@NL@%
- %@NL@%
- %@CR:MQP43106@%%@4@%The statement following %@AB@%THEN%@AE@% can be a single statement or a statement block.%@EH@%
- A block must be enclosed with %@AB@%BEGIN%@AE@% and %@AB@%END%@AE@% statements:%@NL@%
- %@NL@%
- %@AS@% IF (my_val = 3) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'my_val equals 3' );%@NL@%
- %@AS@% Writeln( 'Another statement' );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP43200@%%@3@%%@AB@%4.3.2 ELSE Clauses%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP43201@%%@4@%The %@AB@%ELSE%@AE@% keyword allows an %@AB@%IF%@AE@% statement to perform more complex branching.%@EH@%
- The QELSE.PAS program adds an %@AB@%ELSE%@AE@% clause to QIF.PAS:%@NL@%
- %@NL@%
- %@AS@% PROGRAM qelse;%@NL@%
- %@NL@%
- %@AS@% { QELSE.PAS: Demonstrate ELSE clause. }%@NL@%
- %@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% my_val : Integer;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@NL@%
- %@AS@% my_val := 555;%@NL@%
- %@NL@%
- %@AS@% IF (my_val = 3) THEN%@NL@%
- %@AS@% Writeln( 'my_val equals 3' )%@NL@%
- %@AS@% ELSE%@NL@%
- %@AS@% Writeln( 'my_val does not equal 3' )%@NL@%
- %@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP43202@%%@4@%The QELSE.PAS program contains the following %@AB@%IF...ELSE%@AE@% statement:%@EH@%%@NL@%
- %@NL@%
- %@AS@% IF (my_val = 3) THEN%@NL@%
- %@AS@% Writeln( 'my_val equals 3' )%@NL@%
- %@AS@% ELSE%@NL@%
- %@AS@% Writeln( 'my_val does not equal 3' );%@NL@%
- %@NL@%
- %@CR:MQP43203@%%@4@%The %@AB@%ELSE%@AE@% clause allows the %@AB@%IF%@AE@% statement to take two alternate actions. The%@EH@%
- %@AB@%IF%@AE@% statement prints%@NL@%
- %@NL@%
- %@AS@% my_val equals 3%@NL@%
- %@NL@%
- %@CR:MQP43204@%%@4@%if %@AS@%my_val%@AE@% equals %@AS@%3%@AE@%, and it prints%@EH@%%@NL@%
- %@NL@%
- %@AS@% my_val does not equal 3%@NL@%
- %@NL@%
- %@CR:MQP43205@%%@4@%in all other cases. Note that a semicolon does not precede the %@AB@%ELSE%@AE@%, because%@EH@%
- %@AB@%ELSE%@AE@% is considered part of the %@AB@%IF%@AE@% statement.%@NL@%
- %@NL@%
- %@CR:MQP43206@%%@4@%You can nest and combine %@AB@%IF%@AE@% statements and %@AB@%ELSE%@AE@% clauses as needed. Each %@AB@%ELSE%@AE@%%@EH@%
- is associated with the closest preceding %@AB@%IF%@AE@% that does not have an %@AB@%ELSE%@AE@%
- already. Consider this example:%@NL@%
- %@NL@%
- %@AS@% IF (my_val > 9) THEN%@NL@%
- %@AS@% IF (my_val = 10) THEN%@NL@%
- %@AS@% Writeln( 'Ten' )%@NL@%
- %@AS@% ELSE%@NL@%
- %@AS@% Writeln( 'Greater than nine, but not ten ')%@NL@%
- %@AS@% ELSE%@NL@%
- %@AS@% Writeln( 'Less than ten' );%@NL@%
- %@NL@%
- %@CR:MQP43207@%%@4@%The example can take three different actions. If %@AS@%my_val%@AE@% is greater then %@AS@%9%@AE@%%@EH@%
- and equal to %@AS@%10%@AE@%, it prints %@AS@%Ten%@AE@%. If %@AS@%my_val%@AE@% is greater then %@AS@%9%@AE@% but not equal to
- %@AS@%10%@AE@%, it prints %@AS@%Greater than nine, but not ten%@AE@%. If %@AS@%my_val%@AE@% is less than or
- equal to %@AS@%9%@AE@%, it prints %@AS@%Less than ten%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQP43208@%%@4@%Use a %@AB@%BEGIN%@AE@%...%@AB@%END%@AE@% block to enclose the nested %@AB@%IF%@AE@% statement when the %@AB@%ELSE%@AE@%%@EH@%
- applies to the surrounding %@AB@%IF%@AE@%, as shown below:%@NL@%
- %@NL@%
- %@AS@% IF (my_val > 9) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% IF (my_val = 10) THEN%@NL@%
- %@AS@% Writeln( 'Ten' );%@NL@%
- %@AS@% END%@NL@%
- %@AS@% ELSE%@NL@%
- %@AS@% Writeln( 'Less than ten ');%@NL@%
- %@NL@%
- %@CR:MQP43209@%%@4@%This example prints %@AS@%Ten%@AE@% if %@AS@%my_val%@AE@% equals %@AS@%10%@AE@%, and %@AS@%Less than ten%@AE@% otherwise.%@EH@%
- Without the %@AB@%BEGIN%@AE@%...%@AB@%END%@AE@% block, the %@AB@%ELSE%@AE@% clause would apply to the %@AS@%IF (my_val%@AE@%
- %@AS@%= 10)%@AE@% condition, and not to %@AS@%IF (my_val%@AE@%%@AS@%> 9)%@AE@%.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP43300@%%@3@%%@AB@%4.3.3 CASE Statements%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP43301@%%@4@%As the previous example demonstrates, complex %@AB@%IF...ELSE%@AE@% statements can be%@EH@%
- difficult to read. If all of the branches test the same value (as in the
- previous example), the %@AB@%CASE%@AE@% statement provides a cleaner solution.%@NL@%
- %@NL@%
- %@CR:MQP43302@%%@4@%The Pascal %@AB@%CASE%@AE@% statement is similar to %@AB@%SELECT CASE%@AE@% in BASIC or the %@AB@%switch%@AE@%%@EH@%
- statement in C. It can branch to several different alternatives based on the
- value of a single ordinal expression test. The QCASE.PAS program contains a
- simple %@AB@%CASE%@AE@% statement:%@NL@%
- %@NL@%
- %@AS@% PROGRAM qcase;%@NL@%
- %@NL@%
- %@AS@% { QCASE.PAS: Demonstrate CASE statement. }%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% my_val : Integer;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@NL@%
- %@AS@% my_val := 33;%@NL@%
- %@NL@%
- %@AS@% CASE my_val OF%@NL@%
- %@AS@% 10 : Writeln( 'Ten' );%@NL@%
- %@AS@% 20 : Writeln( 'Twenty' )%@NL@%
- %@AS@% ELSE%@NL@%
- %@AS@% Writeln( 'Not ten or twenty' );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP43303@%%@4@%A %@AB@%CASE%@AE@% statement begins with the %@AB@%CASE%@AE@% keyword, followed by an ordinal%@EH@%
- expression and the %@AB@%OF%@AE@% keyword. The %@AB@%CASE%@AE@% statement in QCASE.PAS tests the
- value of %@AS@%my_val%@AE@%:%@NL@%
- %@NL@%
- %@AS@% CASE my_val OF%@NL@%
- %@NL@%
- %@CR:MQP43304@%%@4@%Next comes a list of alternatives, each labeled with a constant followed by%@EH@%
- a colon (a "case constant"):%@NL@%
- %@NL@%
- %@AS@% 10 : Writeln( 'Ten' );%@NL@%
- %@AS@% 20 : Writeln( 'Twenty' );%@NL@%
- %@NL@%
- %@CR:MQP43305@%%@4@%The alternatives to execute can be single statements or statement blocks.%@EH@%
- Each case constant in the list acts as a target. When %@AS@%my_val%@AE@% equals %@AS@%10%@AE@%,
- QCASE.PAS executes the statement after the case constant%@NL@%
- %@NL@%
- %@AS@% 10:%@NL@%
- %@NL@%
- %@CR:MQP43306@%%@4@%When %@AS@%my_val%@AE@% equals %@AS@%20%@AE@%, control is transferred to the case constant%@EH@%%@NL@%
- %@NL@%
- %@AS@% 20:%@NL@%
- %@NL@%
- %@CR:MQP43307@%%@4@%When %@AS@%my_val%@AE@% doesn't match any case constant, QCASE.PAS executes the%@EH@%
- statement following %@AB@%ELSE%@AE@%:%@NL@%
- %@NL@%
- %@AS@% ELSE%@NL@%
- %@AS@% Writeln( 'Not ten or twenty' );%@NL@%
- %@NL@%
- %@CR:MQP43308@%%@4@%The %@AB@%ELSE%@AE@% clause is optional. If you omit it, and the value of the expression%@EH@%
- does not match any of the %@AB@%CASE%@AE@% constants, none of the alternatives are
- executed. Instead, execution proceeds with the first statement following the
- %@AB@%CASE%@AE@% statements.%@NL@%
- %@NL@%
- %@CR:MQP43309@%%@4@%The %@AB@%CASE%@AE@% statement can use as many case constants as needed. The case%@EH@%
- constant can be a single constant (as shown above), a group, or a range of
- constants:%@NL@%
- %@NL@%
- %@AS@% CASE my_val OF%@NL@%
- %@AS@% 1600,2000 : Writeln( 'Leap century' );%@NL@%
- %@AS@% 1601..1999: Writeln( 'Non-leap century' );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQP4330A@%%@4@%The first case constant includes two values: %@AS@%1600%@AE@% and %@AS@%2000%@AE@%. The second%@EH@%
- includes a range of 399 values: %@AS@%1601%@AE@% through %@AS@%1999%@AE@%.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP50000@%%@1@%%@AB@%Chapter 5 User-Defined Data Types%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQP50001@%%@4@%Instead of limiting a program to using only predefined data types,%@EH@%
- QuickPascal allows you to create your own custom data types that are
- relevant to the program at hand.%@NL@%
- %@NL@%
- %@CR:MQP50002@%%@4@%An ordinal data type is a collection of values where each value (except the%@EH@%
- first) has a unique value that precedes it and (except for the last) a
- unique value that follows it. Examples of ordinal data types are %@AB@%Boolean%@AE@%,
- %@AB@%Char%@AE@%, %@AB@%Integer%@AE@%, and %@AB@%LongInt%@AE@%. With QuickPascal, you can create your own
- ordinal types through the use of enumerated types and subrange types.%@NL@%
- %@NL@%
- %@CR:MQP50003@%%@4@%An enumerated data type has a series of unique, ordinal values defined in%@EH@%
- it. You can think of it in terms of an %@AB@%Integer%@AE@%, but instead of a range of
- numbers, you designate a range of your own values. A subrange data type is
- created by specifying the first and last elements of an existing ordinal
- type. The type may be one of the standard Pascal ordinal types, or an
- enumerated type of your own creation.%@NL@%
- %@NL@%
- %@CR:MQP50004@%%@4@%In addition to enumerated and subrange types, you can also create a set%@EH@%
- type. A set holds up to 255 unique values from an existing ordinal type.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP51000@%%@2@%%@AB@%5.1 Enumerated Data Types%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP51001@%%@4@%Enumerated data types consist of an ordered list of unique identifiers. The%@EH@%
- identifiers can be anything from cars to days of the week. An enumerated
- data type is defined simply by listing the identifiers that make up the
- type.%@NL@%
- %@NL@%
- %@CR:MQP51002@%%@4@%The syntax for an enumerated type is%@EH@%%@NL@%
- %@NL@%
- %@AB@%TYPE%@AE@% %@AI@%ListName%@AE@% = (%@AI@%Identifier%@AE@% «, %@AI@%Identifier%@AE@%...»)%@NL@%
- %@NL@%
- %@CR:MQP51003@%%@4@%QuickPascal assigns numbers to the identifiers in the list. The first list%@EH@%
- element is assigned 0, the second is 1, and so on, up to a maximum of 65,535
- values. This is the QuickPascal internal representation. You normally refer
- to a value by its name.%@NL@%
- %@NL@%
- %@CR:MQP51004@%%@4@%An example of an enumerated data type is%@EH@%%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% japanese_cars = ( honda, isuzu, nissan, toyota );%@NL@%
- %@NL@%
- %@CR:MQP51005@%%@4@%The use of the values assigned to elements in enumerated lists is shown in%@EH@%
- this statement:%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% rental_car : japanese_cars;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% rental_car := nissan;%@NL@%
- %@NL@%
- %@CR:MQP51006@%%@4@%This puts %@AS@%nissan%@AE@%, with a value of 2, into the variable %@AS@%rental_car%@AE@%.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP51007@%%@4@%There may be cases where you want the first element of a list to have a%@EH@%
- non-zero value. You can accomplish this by declaring a fake identifier as
- the first element:%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% place = (null, first, second, third, fourth);%@NL@%
- %@NL@%
- %@CR:MQP51008@%%@4@%This provides a more natural numeric ordering for the list elements.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP51009@%%@4@%QuickPascal provides two procedures and five functions to manipulate%@EH@%
- enumerated data types. The predefined routines are %@AB@%First%@AE@%, %@AB@%Last%@AE@%, %@AB@%Succ%@AE@%, %@AB@%Pred%@AE@%,
- %@AB@%Inc%@AE@%, %@AB@%Dec%@AE@%, and %@AB@%Ord%@AE@%.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP51100@%%@3@%%@AB@%5.1.1 The First Function%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP51101@%%@4@%The %@AB@%First%@AE@% function returns the first element of any ordinal type. The%@EH@%
- function is passed an ordinal type, and returns a value of the same type.%@NL@%
- %@NL@%
- %@CR:MQP51102@%%@4@%The following example shows you how to use %@AB@%First%@AE@%:%@EH@%%@NL@%
- %@NL@%
- %@AS@% PROGRAM enums;%@NL@%
- %@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% my_type = -5..5;%@NL@%
- %@AS@% greek = (alpha, beta, gamma, delta, epsilon);%@NL@%
- %@AS@% subgreek = gamma..epsilon;%@NL@%
- %@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'Type ':20, 'First(Type)':20, 'Last(Type)':20);%@NL@%
- %@AS@% Writeln;%@NL@%
- %@AS@% Writeln( 'Integer':20, First( Integer ):20, Last( Integer ):20 );%@NL@%
- %@AS@% Writeln( 'LongInt':20, First( LongInt ):20, Last( LongInt ):20 );%@NL@%
- %@AS@% Writeln( 'ShortInt':20, First( ShortInt ):20, Last( ShortInt ):20 );%@NL@%
- %@AS@% Writeln( 'Word':20, First( Word ):20, Last( Word ):20 );%@NL@%
- %@AS@% Writeln( 'Char(ord)':20, Ord( First( Char ) ):20,%@NL@%
- %@AS@% Ord( Last( Char ) ):20 );%@NL@%
- %@AS@% Writeln( 'Boolean':20, First( Boolean ):20, Last( Boolean ):20 );%@NL@%
- %@AS@% Writeln( 'my_type':20, First( my_type ):20, Last( my_type ):20 );%@NL@%
- %@AS@% Writeln( 'greek(ord)':20, Ord( First( greek ) ):20,%@NL@%
- %@AS@% Ord( Last( greek ) ):20 );%@NL@%
- %@AS@% Writeln( 'subgreek(ord)':20, Ord( First( subgreek ) ):20,%@NL@%
- %@AS@% Ord( Last( subgreek ) ):20 );%@NL@%
- %@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP51200@%%@3@%%@AB@%5.1.2 The Last Function%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP51201@%%@4@%The %@AB@%Last%@AE@% function returns the last element of any ordinal type. The function%@EH@%
- is passed an ordinal type, and returns a value of the same type.%@NL@%
- %@NL@%
- %@CR:MQP51202@%%@4@%The previous example shows how to use %@AB@%Last%@AE@%.%@EH@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP51300@%%@3@%%@AB@%5.1.3 The Succ Function%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP51301@%%@4@%The %@AB@%Succ%@AE@% function returns the successor, or following element, of an%@EH@%
- enumerated value.%@NL@%
- %@NL@%
- %@AB@%Sample Function Call Ordinal Type Result%@AE@%%@NL@%
- %@NL@%
- %@AS@%Succ(second)%@AE@% %@AS@%place%@AE@% %@AS@%third%@AE@%%@NL@%
- %@NL@%
- %@AS@%Succ(isuzu)%@AE@% %@AS@%japanese_cars%@AE@% %@AS@%nissan%@AE@%%@NL@%
- %@NL@%
- %@AS@%Succ(15)%@AE@% %@AS@%Integer%@AE@% %@AS@%16%@AE@%%@NL@%
- %@NL@%
- %@AS@%Succ('a')%@AE@% %@AS@%Char%@AE@% %@AS@%'b'%@AE@%%@NL@%
- %@NL@%
- %@AS@%Succ(False)%@AE@% %@AS@%Boolean%@AE@% %@AS@%True%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP51302@%%@4@%Both standard and user-defined ordinal types can be used with this function.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP51303@%%@4@%If range checking %@AB@%{$R+}%@AE@% is set, a run-time error occurs if you try to assign%@EH@%
- an element beyond the last in the list. You can avoid this problem by using
- the %@AB@%Last%@AE@% function to check if the element is last in the list.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP51400@%%@3@%%@AB@%5.1.4 The Pred Function%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP51401@%%@4@%The %@AB@%Pred%@AE@% function returns the predecessor, or preceding element, of an%@EH@%
- enumerated value.%@NL@%
- %@NL@%
- %@AB@%Sample Function Call Ordinal Type Result%@AE@%%@NL@%
- %@NL@%
- %@AS@%Pred(isuzu)%@AE@% %@AS@%japanese_cars%@AE@% %@AS@%honda%@AE@%%@NL@%
- %@NL@%
- %@AS@%Pred(second)%@AE@% %@AS@%place%@AE@% %@AS@%first%@AE@%%@NL@%
- %@NL@%
- %@AS@%Pred(12)%@AE@% %@AS@%Integer%@AE@% %@AS@%11%@AE@%%@NL@%
- %@NL@%
- %@AS@%Pred('b')%@AE@% %@AS@%Char%@AE@% %@AS@%'a'%@AE@%%@NL@%
- %@NL@%
- %@AS@%Pred(True)%@AE@% %@AS@%Boolean%@AE@% %@AS@%False%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP51402@%%@4@%Both standard and user-defined enumerated data types can be used with this%@EH@%
- function.%@NL@%
- %@NL@%
- %@CR:MQP51403@%%@4@%If range checking %@AB@%{$R+}%@AE@% is set, a run-time error occurs if you try to assign%@EH@%
- an element preceding the first in the list. You can avoid an error by using
- the %@AB@%First%@AE@% function to check if the element is first in the list.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP51500@%%@3@%%@AB@%5.1.5 The Inc Procedure%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP51501@%%@4@%The %@AB@%Inc%@AE@% procedure provides a shorthand form of the %@AB@%Succ%@AE@% function. Upon%@EH@%
- calling the procedure, the variable it is passed is incremented by the
- number of elements specified.%@NL@%
- %@NL@%
- %@CR:MQP51502@%%@4@%For example, instead of using %@AB@%Succ%@AE@% as follows:%@EH@%%@NL@%
- %@NL@%
- %@AS@% status := Succ( status );%@NL@%
- %@AS@% status := Succ( status );%@NL@%
- %@NL@%
- %@CR:MQP51503@%%@4@%the %@AB@%Inc%@AE@% procedure could be used as%@EH@%%@NL@%
- %@NL@%
- %@AS@% Inc( status, 2 );%@NL@%
- %@NL@%
- %@CR:MQP51504@%%@4@%If no increment parameter is specified, the variable is incremented by one:%@EH@%%@NL@%
- %@NL@%
- %@AS@% Inc( status );%@NL@%
- %@NL@%
- %@CR:MQP51505@%%@4@%The %@AB@%Last%@AE@% function should be used to avoid unpredictable results when%@EH@%
- incrementing elements.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP51600@%%@3@%%@AB@%5.1.6 The Dec Procedure%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP51601@%%@4@%The %@AB@%Dec%@AE@% procedure is an alternative to the %@AB@%Pred%@AE@% function. Upon calling the%@EH@%
- procedure, the variable it is passed is decremented by the number of
- elements specified.%@NL@%
- %@NL@%
- %@CR:MQP51602@%%@4@%For example, instead of using %@AB@%Pred%@AE@% as follows:%@EH@%%@NL@%
- %@NL@%
- %@AS@% status := Pred( status );%@NL@%
- %@AS@% status := Pred( status );%@NL@%
- %@NL@%
- %@CR:MQP51603@%%@4@%the %@AB@%Dec%@AE@% procedure could be used as%@EH@%%@NL@%
- %@NL@%
- %@AS@% Dec( status, 2 );%@NL@%
- %@NL@%
- %@CR:MQP51604@%%@4@%If no decrement parameter is specified, the variable is decremented by one:%@EH@%%@NL@%
- %@NL@%
- %@AS@% Dec( status );%@NL@%
- %@NL@%
- %@CR:MQP51605@%%@4@%The %@AB@%First%@AE@% function should be used to avoid unpredictable results when%@EH@%
- decrementing elements.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP51700@%%@3@%%@AB@%5.1.7 The Ord Function%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP51701@%%@4@%The %@AB@%Ord%@AE@% function returns the ordinal number of an enumerated element. Since%@EH@%
- each enumerated element is unique, you need not mention the enumerated data
- type that the element belongs to. Ordinal values start at zero.%@NL@%
- %@NL@%
- %@AB@%Sample Function Call Ordinal Type Result%@AE@%%@NL@%
- %@NL@%
- %@AS@%Ord(first)%@AE@% %@AS@%place%@AE@% %@AS@%1%@AE@%%@NL@%
- %@NL@%
- %@AS@%Ord(toyota)%@AE@% %@AS@%japanese_cars%@AE@% %@AS@%3%@AE@%%@NL@%
- %@NL@%
- %@AS@%Ord('a')%@AE@% %@AS@%Char%@AE@% %@AS@%97%@AE@%%@NL@%
- %@NL@%
- %@AS@%Ord(False)%@AE@% %@AS@%Boolean%@AE@% %@AS@%0%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP51702@%%@4@%The %@AB@%Ord%@AE@% function accepts both enumeration constants and variables. Both%@EH@%
- standard and user-defined enumerated data types can be used with the
- function.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP52000@%%@2@%%@AB@%5.2 Subrange Types%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP52001@%%@4@%Sometimes, only a few of the elements of an existing data type are needed.%@EH@%
- Instead of declaring a new data type, Pascal allows you to define a subrange
- of either a standard or enumerated data type.%@NL@%
- %@NL@%
- %@CR:MQP52002@%%@4@%For example, in a grading program, the variable %@AS@%test_score%@AE@% records grades%@EH@%
- between 0 and 100. Instead of creating a new data type for the variable, an
- %@AB@%Integer%@AE@% subrange is declared with a minimum value of 0 and a maximum value
- of 100.%@NL@%
- %@NL@%
- %@CR:MQP52003@%%@4@%You can define subranges of the following ordinal types:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP52004@% ■ Integers%@NL@%
- %@NL@%
- ■ Characters%@NL@%
- %@NL@%
- ■ Enumerations%@NL@%
- %@NL@%
- %@CR:MQP52005@%%@4@%To declare a subrange type, identify the %@AI@%SubrangeName%@AE@% and define the first%@EH@%
- and last value in the range, connected with two dots, as shown in the syntax
- below:%@NL@%
- %@NL@%
- %@AI@%SubrangeName%@AE@% %@AB@%=%@AE@% %@AI@%FirstValue..LastValue%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP52006@%%@4@%The %@AI@%FirstValue%@AE@% and %@AI@%LastValue%@AE@% must be constants of the same type, with the %@EH@%
- %@AI@%FirstValue%@AE@% as a predecessor of the %@AI@%LastValue%@AE@%. That is,%@NL@%
- %@NL@%
- %@CR:MQP52007@%%@AI@%Ord%@AE@%( %@AB@%FirstValue%@AE@% ) %@AI@%<= Ord%@AE@%( %@AB@%LastValue%@AE@%)%@NL@%
- %@NL@%
- %@CR:MQP52008@%%@4@%Subrange types serve two useful purposes:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP52009@% 1. If the range of a type needs to be changed, only one change in the%@NL@%
- declaration is necessary.%@NL@%
- %@NL@%
- 2. QuickPascal automatically checks the range assigned to variables of the%@NL@%
- subrange type, with the following limitations:%@NL@%
- %@NL@%
- ■ Range checking must be turned on with the compiler directive%@NL@%
- %@AB@%{$R+}%@AE@%. This can be done at the beginning of the program, or%@NL@%
- turned on (%@AB@%{$R+}%@AE@%) and off (%@AB@%{$R-}%@AE@%) around a statement where a%@NL@%
- subrange variable is used. When range checking is on, QuickPascal%@NL@%
- generates a run-time error if a value outside of the subrange is%@NL@%
- assigned to a variable of the subrange type. See Appendix B%@BO: 857d9@%,%@NL@%
- "Compiler Directives," for more information.%@NL@%
- %@NL@%
- ■ QuickPascal does range checking only in direct assignment%@NL@%
- statements. It does not check for out-of-range values in%@NL@%
- loop-control variables or %@AB@%Read%@AE@%/%@AB@%Write%@AE@% statements.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP52100@%%@3@%%@AB@%5.2.1 Integer Subranges%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP52101@%%@4@%Integer subranges define a range of valid integer values. Some examples of%@EH@%
- simple integer subranges include%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% screen_columns = 1..80;%@NL@%
- %@AS@% die_faces = 1..6; { values on dice faces }%@NL@%
- %@AS@% days = 1..31; { max. 31 in a month }%@NL@%
- %@AS@% months = 1..12; { 12 months/year }%@NL@%
- %@AS@% years = 1900..2099; { the years DOS knows }%@NL@%
- %@AS@% seconds = 0..59;%@NL@%
- %@AS@% minutes = 0..59;%@NL@%
- %@AS@% hours = 0..23;%@NL@%
- %@NL@%
- %@CR:MQP52102@%%@4@%Constant identifiers can define the subranges. Examples include%@EH@%%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% max_col = 80;%@NL@%
- %@AS@% max_row = 25; { or 43 for EGA screen }%@NL@%
- %@AS@% max_days_per_month = 31;%@NL@%
- %@AS@% months_per_year = 12;%@NL@%
- %@AS@% min_year = 1900;%@NL@%
- %@AS@% max_year = 2099;%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% screen_columns = 1..max_col;%@NL@%
- %@AS@% screen_rows = 1..max_row;%@NL@%
- %@AS@% days = 1..max_days_per_month;%@NL@%
- %@AS@% months = 1..months_per_year;%@NL@%
- %@AS@% years = min_year..max_year;%@NL@%
- %@NL@%
- %@CR:MQP52103@%%@4@%Adding constants enhances readability and simplifies the subrange limits.%@EH@%
- For example, if you are developing a program that employs EGA video, you
- need to display 43 lines per screen. Variables of the %@AS@%screen_rows%@AE@% type
- should fall within the 1..43 range. All that is required is to change the
- constant %@AS@%max_row%@AE@% to %@AS@%43%@AE@% at one location.%@NL@%
- %@NL@%
- %@CR:MQP52104@%%@4@%QuickPascal permits expressions in defining ranges. The following are%@EH@%
- examples of declarations that include constant expressions:%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% sec_per_minute = 60;%@NL@%
- %@AS@% minute_per_hour = 60;%@NL@%
- %@AS@% hour_per_day = 24;%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% seconds = 0..sec_per_minute - 1;%@NL@%
- %@AS@% minutes = 0..minute_per_hour - 1;%@NL@%
- %@AS@% hours = 0..hour_per_day - 1;%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP52200@%%@3@%%@AB@%5.2.2 Character Subranges%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP52201@%%@4@%Character subranges define a range of acceptable %@AB@%Char%@AE@% values. Examples%@EH@%
- include%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% up_case_char = 'A'..'Z';%@NL@%
- %@AS@% lo_case_char = 'a'..'z';%@NL@%
- %@AS@% digit_char = '0'..'9';%@NL@%
- %@AS@% ctrl_char = #0..#31;%@NL@%
- %@AS@% { range of characters after 'Z' and before 'a' }%@NL@%
- %@AS@% between_Z_a = Succ('Z') .. Pred('a');%@NL@%
- %@NL@%
- %@CR:MQP52202@%%@4@%Any range of ASCII characters can be defined in a subrange. Note the use of%@EH@%
- the %@AB@%Succ%@AE@% and %@AB@%Pred%@AE@% functions in the last example to define the six ASCII
- characters between 'Z' and 'a'. (See the ASCII character chart in Appendix
- A%@BO: 829c0@%.)%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP52300@%%@3@%%@AB@%5.2.3 Enumerated Subranges%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP52301@%%@4@%Enumerated subranges limit the range of permissible enumerated values. An%@EH@%
- example is%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% vehicles = (volkswagen, honda, toyota, corvette,%@NL@%
- %@AS@% porsche, ferrari, suburban, blazer,%@NL@%
- %@AS@% bronco);%@NL@%
- %@NL@%
- %@AS@% economy_cars = volkswagen..toyota;%@NL@%
- %@AS@% sports_cars = corvette..ferrari;%@NL@%
- %@NL@%
- %@CR:MQP52302@%%@4@%The type %@AS@%economy_cars%@AE@% is a subrange with legal values of %@AS@%volkswagen%@AE@%, %@AS@%honda%@AE@%,%@EH@%
- and %@AS@%toyota%@AE@%. Similarly, the %@AS@%sports_cars%@AE@% type has only the enumerated
- %@AS@%corvette%@AE@%, %@AS@%porsche%@AE@%, and %@AS@%ferrari%@AE@% values.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP53000@%%@2@%%@AB@%5.3 Sets%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP53001@%%@4@%Sets are structured, user-defined data types. In mathematics, a set is an%@EH@%
- unordered collection of elements. The concept of a set is the same in
- QuickPascal. A set holds only unique values. For example, if A, B, and C
- were contained in a set, and you added B to it, the set would still only
- contain A, B, and C, not A, B, B, and C. Sets are useful for holding a
- collection of attributes or determining if an element is a member of a
- particular group.%@NL@%
- %@NL@%
- %@CR:MQP53002@%%@4@%The syntax for declaring a set is%@EH@%%@NL@%
- %@NL@%
- %@AI@%SetName%@AE@% %@AB@%= SET OF%@AE@% %@AI@%OrdinalType%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP53003@%%@4@%The argument %@AI@%OrdinalType%@AE@% is an ordered range of values. The members of the%@EH@%
- %@AI@%OrdinalType%@AE@% must be all of the same type, and can be single elements or a
- subrange. The %@AI@%OrdinalType%@AE@% cannot have more than 256 possible values. This
- limits sets to the predefined %@AB@%Boolean%@AE@%, %@AB@%Char%@AE@%, and %@AB@%Byte%@AE@% types, and restricts
- the use of %@AB@%Word%@AE@%, %@AB@%Integer%@AE@%, and %@AB@%LongInt%@AE@% types.%@NL@%
- %@NL@%
- %@CR:MQP53004@%%@4@%As an example, a program might declare a set of uppercase letters and vowels%@EH@%
- to be%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% vowels = ['A', 'E', 'I', 'O', 'U'];%@NL@%
- %@AS@% upper_case = SET OF 'A'..'Z' = ['A'..'Z'];%@NL@%
- %@NL@%
- %@CR:MQP53005@%%@4@%Once you have declared a set, the operator %@AB@%IN%@AE@% can be used to test for the%@EH@%
- presence or absence of a specified element. For example, in these statements%@NL@%
- %@NL@%
- %@AS@% IF ch IN upper_case THEN...%@NL@%
- %@AS@% IF ch IN vowels THEN...%@NL@%
- %@NL@%
- %@CR:MQP53006@%%@4@%%@AB@%IN%@AE@% returns a true result if %@AS@%ch%@AE@% is a member of the set, and false if it is%@EH@%
- not.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP53100@%%@3@%%@AB@%5.3.1 Declaring Set Types%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP53101@%%@4@%Sets can be declared with a variety of types. Included are%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP53102@% ■ Predefined ordinal types of %@AB@%Boolean%@AE@%, %@AB@%Char%@AE@%, and %@AB@%Byte%@AE@%%@NL@%
- %@NL@%
- %@AS@%TYPE%@AE@%%@NL@%
- %@AS@%boolean_set = SET OF Boolean;%@AE@%%@NL@%
- %@AS@%char_set = SET OF Char;%@AE@%%@NL@%
- %@AS@%byte_set = SET OF Byte;%@AE@%%@NL@%
- %@NL@%
- ■ Subranges of predefined types (either directly as the first set or%@NL@%
- indirectly as the last)%@NL@%
- %@NL@%
- %@AS@%TYPE%@AE@%%@NL@%
- %@AS@%bits = 1..7;%@AE@%%@NL@%
- %@AS@%byte_bits = SET OF bits;%@AE@%%@NL@%
- %@AS@%up_case = SET OF 'A'..'Z';%@AE@%%@NL@%
- %@AS@%lo_case = SET OF 'a'..'z';%@AE@%%@NL@%
- %@NL@%
- ■ Enumerated types%@NL@%
- %@NL@%
- %@AS@%TYPE%@AE@%%@NL@%
- %@AS@%transportation = (bicycle, motorcycle, car, truck,%@AE@%%@NL@%
- %@AS@%bus);%@AE@%%@NL@%
- %@AS@%four_wheels = car..bus;%@AE@%%@NL@%
- %@AS@%trans_set = SET OF transportation;%@AE@%%@NL@%
- %@AS@%four_wheel_set = SET OF four_wheels;%@AE@%%@NL@%
- %@NL@%
- ■ Variables%@NL@%
- %@NL@%
- %@AS@%VAR%@AE@%%@NL@%
- %@AS@%fast_trans : four_wheels;%@AE@%%@NL@%
- %@AS@%lower_letters : lo_case;%@AE@%%@NL@%
- %@AS@%num1, num2 : byte_bits;%@AE@%%@NL@%
- %@NL@%
- ■ Constants and typed constants%@NL@%
- %@NL@%
- %@AS@%CONST%@AE@%%@NL@%
- %@AS@%math_op : SET OF Char = ['=', '-', '^(*)', '/'];%@AE@%%@NL@%
- %@AS@%vowels : SET OF Char = ['A','E','I','O','U'];%@AE@%%@NL@%
- %@AS@%up_chars : SET OF Char = ['A'..'Z'];%@AE@%%@NL@%
- %@AS@%lo_chars : SET OF Char = ['a'..'z'];%@AE@%%@NL@%
- %@AS@%cheap_trans : SET OF transportation =%@AE@%%@NL@%
- %@AS@%[bicycle, motorcycle, bus];%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP53103@%%@4@%Character set constants are useful in representing fixed sets of characters%@EH@%
- used in menu selections. For example, if you have a menu with the following
- selections:%@NL@%
- %@NL@%
- %@AS@%Add Change Delete Print View Store Recall%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP53104@%%@4@%where the capital letters are "hot" keys used to quickly select a menu%@EH@%
- option, the corresponding typed constant would look like this:%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% menu_char : SET OF Char = ['A','C','D','P','V','S','R'];%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP53200@%%@3@%%@AB@%5.3.2 Assigning Set Elements to Variables%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP53201@%%@4@%To assign set elements to a set variable, use the square brackets:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP53202@%%@AI@%SetVariable%@AE@% %@AB@%:= [%@AE@%%@AI@%SetElements%@AE@%%@AB@%]%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP53203@%%@4@%If there are no set elements present, the set variable is assigned an empty%@EH@%
- set %@AB@%(%@AE@%%@AI@%SetVariable%@AE@%%@AB@%: = [])%@AE@%. Set variables may be initialized in this way.%@NL@%
- %@NL@%
- %@CR:MQP53204@%%@4@%A set may be constructed from a list of single elements, a subrange, or a%@EH@%
- combination of both. Examples of assigning set elements to variables are%@NL@%
- %@NL@%
- %@AS@% set1 := [1, 3, 5, 7, 9];{ single elements }%@NL@%
- %@AS@% set2 := [0..7]; { subrange }%@NL@%
- %@AS@% set3 := [0..7, 14, 15, 16]; { subrange & single elements }%@NL@%
- %@AS@% char_list := ['A'..'Z','a'..'z','0'..'9']; { subranges }%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP53300@%%@3@%%@AB@%5.3.3 Set Operators%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP53301@%%@4@%Although individual elements of a set cannot be directly accessed, a variety%@EH@%
- of operators is available to test membership and manipulate the set as a
- whole.%@NL@%
- %@NL@%
- %@CR:MQP53302@%%@4@%These operators offer powerful and flexible methods of creating new sets%@EH@%
- with elements from existing sets. Set operators supported by QuickPascal
- include%@NL@%
- %@NL@%
- %@CR:MQP53303@% ■ Relational operators%@NL@%
- %@NL@%
- ■ %@AB@%IN%@AE@% operator%@NL@%
- %@NL@%
- ■ Set-union operator%@NL@%
- %@NL@%
- ■ Set-difference operator%@NL@%
- %@NL@%
- ■ Set-intersection operator%@NL@%
- %@NL@%
- %@CR:MQP53310@%%@4@%%@AB@%5.3.3.1 Relational Operators%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP53311@%%@4@%A variety of relational operators is available to test set membership. Based%@EH@%
- on the condition of an expression, the operator will return %@AB@%True%@AE@% or %@AB@%False%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQP53312@%%@4@%Table 5.1 lists the relational operators that work on sets, with %@AS@%A%@AE@% and %@AS@%B%@AE@% as%@EH@%
- example sets.%@NL@%
- %@NL@%
- %@CR:MQP5T100@%%@4@%%@AB@%Table 5.1 Relational Operators%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Expression Returns True if%@AE@%%@NL@%
- %@NL@%
- %@AS@%A = B%@AE@% %@AS@%A%@AE@% and %@AS@%B%@AE@% are identical.%@NL@%
- %@NL@%
- %@AS@%A <> B%@AE@% At least one element in %@AS@%A%@AE@% is%@NL@%
- not in %@AS@%B%@AE@%, or at least one element%@NL@%
- in %@AS@%B%@AE@% is not in A.%@NL@%
- %@NL@%
- %@AS@%A <= B%@AE@% All elements in %@AS@%A%@AE@% are in %@AS@%B%@AE@%.%@NL@%
- %@NL@%
- %@AS@%A >= B%@AE@% All elements in %@AS@%B%@AE@% are in %@AS@%A%@AE@%.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP53320@%%@4@%%@AB@%5.3.3.2 IN Operator%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP53321@%%@4@%As previously discussed, the %@AB@%IN%@AE@% operator tests for set membership. This%@EH@%
- operator returns a Boolean result indicating whether a value is a member of
- the set. The tested value must be the same or of a compatible type with the
- tested set's base type. The syntax is%@NL@%
- %@NL@%
- %@AI@%Value%@AE@% %@AB@%IN%@AE@% %@AI@%Set%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP53322@%%@4@%For example,%@EH@%%@NL@%
- %@NL@%
- %@AS@% ch IN vowels%@NL@%
- %@AS@% 'i' IN consonants%@NL@%
- %@AS@% operator IN ['+', '-', '/', '*']%@NL@%
- %@NL@%
- %@CR:MQP53323@%%@4@%Figure 5.1%@BO: 279a5@% displays the action of set operators on sets %@AS@%A%@AE@% and %@AS@%B%@AE@%. The shaded%@EH@%
- area represents the result of the operations on the sets.%@NL@%
- %@NL@%
- %@CR:MQP5f000@%%@4@%%@AB@%Figure 5.1 Set Operators%@AE@%%@EH@%%@NL@%
- %@NL@%
- │ A + B │ A - B │ A * B │%@NL@%
- │ (Union) │ (Difference) │ (Intersection) │%@NL@%
- ────────┼──────────────────────┼───────────────────────┼───────────────────────┤%@NL@%
- │┌───────────┐ │ ┌───────────┐ │ ┌───────────┐ │%@NL@%
- A and B ││▒A▒▒▒▒▒▒▒▒▒│ ┌──────┐│ │▒A▒▒▒▒▒▒▒▒▒│ ┌──────┐│ │ A │ ┌──────┐│%@NL@%
- are ││▒▒▒▒▒▒▒▒▒▒▒│ │▒▒▒▒B▒││ │▒▒▒▒▒▒▒▒▒▒▒│ │ B ││ │ │ │ B ││%@NL@%
- disjoint││▒▒▒▒▒▒▒▒▒▒▒│ │▒▒▒▒▒▒││ │▒▒▒▒▒▒▒▒▒▒▒│ │ ││ │ │ │ ││%@NL@%
- sets. ││▒▒▒▒▒▒▒▒▒▒▒│ └──────┘│ │▒▒▒▒▒▒▒▒▒▒▒│ └──────┘│ │ │ └──────┘│%@NL@%
- │└───────────┘ │ └───────────┘ │ └───────────┘ │%@NL@%
- ────────┼──────────────────────┼───────────────────────┼───────────────────────┤%@NL@%
- │ ┌───────────┐ │ ┌───────────┐ │ ┌───────────┐ │%@NL@%
- A │ │▒A▒▒▒▒▒▒┌──┼───┐ │ │▒A▒▒▒▒▒▒┌──┼───┐ │ │ A ┌──┼───┐ │%@NL@%
- inter- │ │▒▒▒▒▒▒▒▒│▒▒│▒B▒│ │ │▒▒▒▒▒▒▒▒│ │ B │ │ │ │▒▒│ B │ │%@NL@%
- sects │ │▒▒▒▒▒▒▒▒│▒▒│▒▒▒│ │ │▒▒▒▒▒▒▒▒│ │ │ │ │ │▒▒│ │ │%@NL@%
- B │ │▒▒▒▒▒▒▒▒└──┼───┘ │ │▒▒▒▒▒▒▒▒└──┼───┘ │ │ └──┼───┘ │%@NL@%
- │ └───────────┘ │ └───────────┘ │ └───────────┘ │%@NL@%
- ────────┼──────────────────────┼───────────────────────┼───────────────────────┤%@NL@%
- │ ┌───────────┐ │ ┌───────────┐ │ ┌───────────┐ │%@NL@%
- B is a │ │▒A▒┌──────┐│ │ │▒A▒┌──────┐│ │ │ A ┌──────┐│ │%@NL@%
- subset │ │▒▒▒│▒▒▒▒B▒││ │ │▒▒▒│ B ││ │ │ │▒▒▒▒B▒││ │%@NL@%
- of A │ │▒▒▒│▒▒▒▒▒▒││ │ │▒▒▒│ ││ │ │ │▒▒▒▒▒▒││ │%@NL@%
- │ │▒▒▒└──────┘│ │ │▒▒▒└──────┘│ │ │ └──────┘│ │%@NL@%
- │ └───────────┘ │ └───────────┘ │ └───────────┘ │%@NL@%
- ────────┴──────────────────────┴───────────────────────┴───────────────────────┘%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP53330@%%@4@%%@AB@%5.3.3.3 Set-Union Operator%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP53331@%%@4@%The set-union operator (+) merges two sets into a third set. If either set%@EH@%
- is a subset of the other, combining the two sets results in a set that is
- the same as the larger set. In the example below, two sets with unique
- members are merged, resulting in a larger set:%@NL@%
- %@NL@%
- %@AS@% set1 := ['A'..'Z'];%@NL@%
- %@AS@% set2 := ['a'..'z'];%@NL@%
- %@AS@% set3 := set1 + set2;%@NL@%
- %@AS@% set3 := ['A'..'Z','a'..'z']; { same as previous assignment }%@NL@%
- %@NL@%
- %@CR:MQP53332@%%@4@%In the next example, the two character sets have overlapping members. The%@EH@%
- united set consists of %@AS@%['A'..'Z']%@AE@% with any overlapping members represented
- only once.%@NL@%
- %@NL@%
- %@AS@% set1 := ['A'..'L'];%@NL@%
- %@AS@% set2 := ['H'..'Z'];%@NL@%
- %@AS@% set3 := set1 + set2;%@NL@%
- %@AS@% set3 := ['A'..'Z'];{ equivalent to previous assignment }%@NL@%
- %@NL@%
- %@CR:MQP53333@%%@4@%The third example shows a set being united with a subset. This results in%@EH@%
- %@AS@%set3%@AE@% and %@AS@%set1%@AE@% having the same members.%@NL@%
- %@NL@%
- %@AS@% set1 := ['A'..'L'];%@NL@%
- %@AS@% set2 := ['F'..'J'];%@NL@%
- %@AS@% set3 := set1 + set2;%@NL@%
- %@AS@% set3 := ['A'..'L']; { equivalent to previous assignment }%@NL@%
- %@NL@%
- %@CR:MQP53334@%%@4@%The union operator is also important for adding to the membership of a set.%@EH@%
- In the following example, a character set is initialized and then a %@AB@%FOR%@AE@% loop
- is used to add the characters %@AS@%A,B,C,D,E,F,...,%@AE@%:%@NL@%
- %@NL@%
- %@AS@% set1 := []; { initialize }%@NL@%
- %@AS@% FOR ch := 'A' TO 'Z' DO%@NL@%
- %@AS@% set1 := set1 + [ch];%@NL@%
- %@NL@%
- %@CR:MQP53335@%%@4@%Note the presence of the set brackets around the %@AS@%ch%@AE@% variable. They are%@EH@%
- required in order to make %@AS@%[ch]%@AE@% a single-element set.%@NL@%
- %@NL@%
- %@CR:MQP53336@%%@4@%Refer to Figure 5.1%@BO: 279a5@% for an illustration of the union operator.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP53340@%%@4@%%@AB@%5.3.3.4 Set-Difference Operator%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP53341@%%@4@%The set-difference operator (%@AB@%-)%@AE@% creates a set that contains all of the%@EH@%
- members of the first set that do not appear in the second set. For example,
- in the statement%@NL@%
- %@NL@%
- %@AS@% set3 := set1 - set2;%@NL@%
- %@NL@%
- %@CR:MQP53342@%%@4@%%@AS@%set3%@AE@% will contain all of the elements in %@AS@%set1%@AE@% that are not in %@AS@%set2%@AE@%.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP53343@%%@4@%If %@AS@%set1%@AE@% and %@AS@%set2%@AE@% have the same members, then %@AS@%set3%@AE@% becomes an empty set. If%@EH@%
- %@AS@%set2%@AE@% is a subset of %@AS@%set1%@AE@%, then %@AS@%set3%@AE@% comprises of the members of %@AS@%set1%@AE@% that
- are not common to %@AS@%set2%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQP53344@%%@4@%In the following example, the difference between two sets with unique%@EH@%
- members is assigned to a third set. The resulting set has the same members
- as %@AS@%set1%@AE@% since the operand sets have nothing in common:%@NL@%
- %@NL@%
- %@AS@% set1 := ['A'..'Z'];%@NL@%
- %@AS@% set2 := ['a'..'z'];%@NL@%
- %@AS@% set3 := set1 - set2;%@NL@%
- %@AS@% set3 := ['A'..'Z']; { equivalent to previous assignment }%@NL@%
- %@NL@%
- %@CR:MQP53345@%%@4@%In the next example, the two character sets have overlapping members. The%@EH@%
- resulting set is made up of %@AS@%['A'..'G']%@AE@%:%@NL@%
- %@NL@%
- %@AS@% set1 := ['A'..'L'];%@NL@%
- %@AS@% set2 := ['H'..'Z'];%@NL@%
- %@AS@% set3 := set1 - set2;%@NL@%
- %@AS@% set3 := ['A'..'G']; { equivalent to previous assignment }%@NL@%
- %@NL@%
- %@CR:MQP53346@%%@4@%The next example shows the difference of a set with its subset. The result%@EH@%
- is that %@AS@%set3%@AE@% contains %@AS@%['A'..'E']%@AE@%, the members of the first set not found in
- the second one.%@NL@%
- %@NL@%
- %@AS@% set1 := ['A'..'L'];%@NL@%
- %@AS@% set2 := ['F'..'J'];%@NL@%
- %@AS@% set3 := set1 - set2;%@NL@%
- %@AS@% set3 := ['A'..'E', 'K', 'L']; { equivalent to previous assignment }%@NL@%
- %@NL@%
- %@CR:MQP53347@%%@4@%The difference operator can also be used to strip single members from set%@EH@%
- variables. The last example for the union operator can be rewritten to use
- the difference operator in the following way. The character set is
- initialized to %@AS@%['A'..'Z']%@AE@% and a %@AB@%FOR%@AE@% loop is used to eliminate the %@AS@%A, B, D,%@AE@%
- %@AS@%F, H,%@AE@% characters and so on.%@NL@%
- %@NL@%
- %@AS@% oddeven := 0;%@NL@%
- %@AS@% set1 := ['A'..'Z']; { initialize }%@NL@%
- %@AS@% FOR ch := 'B' TO 'Z' DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% IF (NOT Odd( Oddeven )) THEN%@NL@%
- %@AS@% set1 := set1 - [ch];%@NL@%
- %@AS@% Inc( Oddeven );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQP53348@%%@4@%Refer to Figure 5.1%@BO: 279a5@% for an illustration of the difference operator.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP53350@%%@4@%%@AB@%5.3.3.5 Set-Intersection Operator%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP53351@%%@4@%The set-intersection operator (%@AB@%*%@AE@%) is used to extract all of the elements%@EH@%
- that are in two similarly typed sets. For example, with%@NL@%
- %@NL@%
- %@AS@% set3 := set1 * set2;%@NL@%
- %@NL@%
- %@CR:MQP53352@%%@4@%%@AS@%set3%@AE@% will contain all of the elements that are in both %@AS@%set1%@AE@% and %@AS@%set2%@AE@%.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP53353@%%@4@%In the next example, the two character sets have overlapping members. The%@EH@%
- intersection set is %@AS@%['H'..'L']%@AE@%:%@NL@%
- %@NL@%
- %@AS@% set1 := ['A'..'L'];%@NL@%
- %@AS@% set2 := ['H'..'Z'];%@NL@%
- %@AS@% set3 := set1 * set2;%@NL@%
- %@AS@% set3 := ['H'..'L'];%@NL@%
- %@NL@%
- %@CR:MQP53354@%%@4@%The intersection of a set with its subset returns the members of the subset.%@EH@%
- The next example shows such an operation. The result is that %@AS@%set3%@AE@% and %@AS@%set2%@AE@%
- have the same members:%@NL@%
- %@NL@%
- %@AS@% set1 := ['A'..'L'];%@NL@%
- %@AS@% set2 := ['F'..'J'];%@NL@%
- %@AS@% set3 := set1 * set2;%@NL@%
- %@AS@% set3 := ['F'..'J'];%@NL@%
- %@NL@%
- %@CR:MQP53355@%%@4@%In the following example, two sets with unique members are intersected. The%@EH@%
- resulting set is empty, since the operand sets have nothing in common:%@NL@%
- %@NL@%
- %@AS@% set1 := ['A'..'Z'];%@NL@%
- %@AS@% set2 := ['a'..'z'];%@NL@%
- %@AS@% set3 := set1 * set2;%@NL@%
- %@AS@% set3 := [];%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP60000@%%@1@%%@AB@%Chapter 6 Arrays and Records%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQP60001@%%@4@%This chapter presents data types that hold organized collections of data in%@EH@%
- a definite order.%@NL@%
- %@NL@%
- %@CR:MQP60002@%%@4@%An "array" is a collection of data items of the same type. Programs use%@EH@%
- arrays in situations where a standard data format is repeated many times.
- For example, numbers representing the Gross National Product for all the
- years from 1900 to 1980 might be placed in an array.%@NL@%
- %@NL@%
- %@CR:MQP60003@%%@4@%A "record" is a collection of data items having different types. Programs%@EH@%
- use records in situations where a variety of data have a close association.
- For example, all of the information on a given employee──name, salary, and
- security clearance──might be placed in a single record.%@NL@%
- %@NL@%
- %@CR:MQP60004@%%@4@%Finally, this chapter presents the "variant record" type, which is an%@EH@%
- extension of the record type. A variant record allows you to use different
- data formats to access the same area of memory, enabling you to create a
- record that holds different kinds of information at different times.%@NL@%
- %@NL@%
- %@CR:MQP60005@%%@4@%Each of the major sections in this chapter introduces a data type, shows how%@EH@%
- to declare it, then shows how to access its components.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP61000@%%@2@%%@AB@%6.1 Arrays%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP61001@%%@4@%An array is a collection of elements that share the same data type and a%@EH@%
- common variable name. You access an element in the array by specifying the
- position of the element. An integer or ordinal value indicates the position
- and is called an "index."%@NL@%
- %@NL@%
- %@CR:MQP61002@%%@4@%Pascal lets you declare arrays of any type. You can even declare arrays of%@EH@%
- arrays, which are, in essence, two-dimensional arrays. You can declare
- arrays with any number of dimensions. Multidimensional arrays have many
- applications and appear often in Pascal programs. For example, a program
- that requires a grid will use a two-dimensional array, and a program that
- maps three-dimensional space will use a three-dimensional array. The
- simplest arrays are one-dimensional. They consist of a linear sequence of
- elements.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP61100@%%@3@%%@AB@%6.1.1 Declaring Arrays%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP61101@%%@4@%In many languages (such as C), arrays must always start at a particular%@EH@%
- index number (such as 0 or 1). In Pascal, however, you can define the bounds
- of an array with almost any ordinal type:%@NL@%
- %@NL@%
- %@AB@%ARRAY [%@AE@%%@AI@%IndexType%@AE@%%@AB@%] OF %@AE@%%@AI@%ElementType%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP61102@%%@4@%To declare a multidimensional array, you declare an index type for each%@EH@%
- dimension:%@NL@%
- %@NL@%
- %@AB@%ARRAY [%@AE@%%@AI@%IndexType%@AE@%%@AB@%, %@AE@%%@AI@%IndexType%@AE@%%@AB@% ...] OF %@AE@%%@AI@%type%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP61103@%%@4@%%@AI@%IndexType%@AE@% can be any ordinal type except %@AB@%LongInt%@AE@% or subranges of %@AB@%LongInt%@AE@%.%@EH@%
- Most often, programs use subranges in array declarations. The lower and
- upper bounds of the subrange give the lowest and highest index, and also
- determine the size of the array. For example:%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% income_per_year = ARRAY[1977..1989] OF LongInt;%@NL@%
- %@AS@% class_size = ARRAY[1..12] OF Integer;%@NL@%
- %@AS@% grid = ARRAY[-5..5, -10..10] OF Real;%@NL@%
- %@NL@%
- %@CR:MQP61104@%%@4@%As you can see, even negative numbers can serve as array bounds. Because%@EH@%
- Pascal is so structured, you can use many different integer subranges and
- enumerated types to index arrays. For example:%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% pay = LongInt;%@NL@%
- %@AS@% rank = (private, sergeant, lt, captain, major, general);%@NL@%
- %@AS@% officers = lt..general ;%@NL@%
- %@AS@% letters = 'A'..'Z';%@NL@%
- %@AS@% my_arr = ARRAY[1..10] OF Real;%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% low_pay : ARRAY[private .. sergeant] OF pay;%@NL@%
- %@AS@% high_pay : ARRAY[officers] OF pay;%@NL@%
- %@AS@% ascii_code : ARRAY[letters] OF Word;%@NL@%
- %@AS@% big_arr : ARRAY[letters] OF my_arr;%@NL@%
- %@NL@%
- %@CR:MQP61105@%%@4@%The last example above, %@AS@%big_arr%@AE@%, is really a two-dimensional array and is%@EH@%
- equivalent to the following declaration, which specifies the ranges of the
- two dimensions explicitly:%@NL@%
- %@NL@%
- %@AS@% big_arr : ARRAY[letters, 1..10] OF Real;%@NL@%
- %@NL@%
- %@CR:MQP61106@%%@4@%Bear in mind the difference between the index type of an array and the%@EH@%
- element type. The item in brackets defines the index type of the array and
- is significant in the following ways:%@NL@%
- %@NL@%
- %@CR:MQP61107@% ■ The index type determines the range and meaning of indexes. The next%@NL@%
- section describes how you use indexes to access elements.%@NL@%
- %@NL@%
- ■ The index type determines the number of elements in the array. For%@NL@%
- example, an array with subrange %@AS@%1..500%@AE@% has 500 elements. An array with%@NL@%
- subrange %@AS@%101..103%@AE@% has three elements.%@NL@%
- %@NL@%
- %@CR:MQP61108@%%@4@%The elements are declared by the data type at the end of the array%@EH@%
- declaration. As mentioned above, you can use any data type, including any of
- the advanced data types mentioned later in this book. Each element of the
- array has this element type.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP61200@%%@3@%%@AB@%6.1.2 Accessing Array Elements%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP61201@%%@4@%To refer to an element of an array, use the syntax%@EH@%%@NL@%
- %@NL@%
- %@AI@%Name%@AE@%%@AB@% [ %@AE@%%@AI@%Index%@AE@%%@AB@% ]%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP61202@%%@4@%in which %@AI@%Name%@AE@% is the name of the array variable, and %@AI@%Index%@AE@% has the index%@EH@%
- type used to declare the array. If the index type is a subrange, %@AI@%Index%@AE@% must
- fall into the specified range or the program produces errors. Consider the
- following declarations:%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% trio : ARRAY[1..3] OF Word;%@NL@%
- %@AS@% income : ARRAY[1980..1983] OF LongInt;%@NL@%
- %@NL@%
- %@CR:MQP61203@%%@4@%In the example above, the elements of %@AS@%trio%@AE@% are referred to as%@EH@%%@NL@%
- %@NL@%
- %@AS@% trio[1]%@NL@%
- %@AS@% trio[2]%@NL@%
- %@AS@% trio[3]%@NL@%
- %@NL@%
- %@CR:MQP61204@%%@4@%The elements of %@AS@%income%@AE@% are referred to as%@EH@%%@NL@%
- %@NL@%
- %@AS@% income[1980]%@NL@%
- %@AS@% income[1981]%@NL@%
- %@AS@% income[1982]%@NL@%
- %@AS@% income[1983]%@NL@%
- %@NL@%
- %@CR:MQP61205@%%@4@%Each of the elements above has the data type declared for the array──%@AB@%Word%@AE@% in%@EH@%
- the case of %@AS@%trio%@AE@% and %@AB@%LongInt%@AE@% in the case of %@AS@%income%@AE@%. You can refer to an
- element in any context that is valid for a simple variable of the same type.
- You can alter an element, pass it to a procedure, or assign its value to
- another variable. The following statements are all valid:%@NL@%
- %@NL@%
- %@AS@% trio[1] := 50;%@NL@%
- %@AS@% trio[2] := trio[1] DIV 2;%@NL@%
- %@AS@% Writeln( ' Result is : ', trio[1] + trio[2] );%@NL@%
- %@NL@%
- %@CR:MQP61206@%%@4@%The array index can be a variable as well as a constant. In fact, the power%@EH@%
- of arrays in programming comes largely from the use of variable indexes. The
- following code uses a loop variable to efficiently initialize a large array
- of random numbers:%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% i : Integer;%@NL@%
- %@AS@% big_arr : ARRAY[1..1000] OF Word;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% FOR i := 1 TO 1000 DO%@NL@%
- %@AS@% big_arr[i] := Random(100);%@NL@%
- %@NL@%
- %@CR:MQP61207@%%@4@%To refer to an element of a multidimensional array, use the syntax%@EH@%%@NL@%
- %@NL@%
- %@AI@%Name%@AE@%%@AB@% [%@AE@%%@AI@%Index%@AE@%%@AB@%, %@AE@%%@AI@%Index%@AE@% ... %@AB@%]%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP61208@%%@4@%in which each %@AI@%Index%@AE@% is of the type and range of the corresponding index in%@EH@%
- the array declaration. For example, the following code uses a nested loop to
- efficiently initialize a two-dimensional array of random numbers:%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% i, j : Integer;%@NL@%
- %@AS@% results : ARRAY[1..max_row, 1..max_col] OF Word;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% FOR i := 1 TO max_row DO%@NL@%
- %@AS@% FOR j := 1 TO max_col DO%@NL@%
- %@AS@% results[i, j] := Random(100);%@NL@%
- %@NL@%
- %@CR:MQP61209@%%@4@%The %@AB@%{$R+}%@AE@% directive causes the program to check for out-of-bound indexes at%@EH@%
- run time. Use the %@AB@%{$R+}%@AE@% directive during program development, but you may
- want to turn the directive off (%@AB@%{$R-}%@AE@%) once you finish writing and
- debugging. This lets the program run faster.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP61300@%%@3@%%@AB@%6.1.3 Declaring Constant Arrays%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP61301@%%@4@%To declare a constant array, first define the array type, then declare the%@EH@%
- array and the initial values in a %@AB@%CONST%@AE@% statement. As shown in the examples
- below, follow the array type with an equal sign (%@AB@%=%@AE@%) and a list of initial
- values enclosed in parentheses. Separate elements with commas.
- Multidimensional arrays require additional levels of parentheses. For
- example, in a two-dimensional array, place parentheses around the values for
- each row.%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% max_row = 5;%@NL@%
- %@AS@% grid_size = 2;%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% small_int_arr = ARRAY[1..max_row] OF Integer;%@NL@%
- %@AS@% hex_digit_arr = ARRAY[1..16] OF Char;%@NL@%
- %@NL@%
- %@AS@% grid_xy = 1..grid_size;%@NL@%
- %@AS@% char_grid_type = ARRAY[grid_xy, grid_xy] OF Char;%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% topic_index : small_int_arr = ( 11, 12, 13, 14, 15 );%@NL@%
- %@AS@% hex : hex_digit_arr =%@NL@%
- %@AS@% ( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',%@NL@%
- %@AS@% 'A', 'B', 'C', 'D', 'E', 'F' );%@NL@%
- %@AS@% default_state : char_grid_type =%@NL@%
- %@AS@% ( ( 'a', 'j' ), ( 'W', 'T' ) );%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP61400@%%@3@%%@AB@%6.1.4 Passing Arrays as Parameters%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP61401@%%@4@%This section describes how to pass an entire array to a procedure or%@EH@%
- function. Note that there is no restriction on how you pass individual
- elements, which can be passed just like simple variables of the same type.%@NL@%
- %@NL@%
- %@CR:MQP61402@%%@4@%To pass an array as a parameter, first define the array as an independent%@EH@%
- type. Then declare the function to take a parameter of this predefined type,
- and pass a value of this same type to the function. This requirement is
- necessary for Pascal to ensure that the array is passed correctly.%@NL@%
- %@NL@%
- %@CR:MQP61403@%%@4@%The following code illustrates how to successfully pass an array:%@EH@%%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% res_arr = ARRAY[1..20] OF Integer;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% results : res_arr; { results is a res_arr type variable }%@NL@%
- %@NL@%
- %@AS@% { =====init_arr===== }%@NL@%
- %@AS@% { init_arr accepts a variable with res_arr type and initializes it }%@NL@%
- %@AS@% PROCEDURE init_arr( VAR new_arr : res_arr );%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% { call init_arr, passing it the results variable%@NL@%
- %@AI@%which has type res_arr%@AE@%%@NL@%
- }%@NL@%
- %@AS@% init_arr( results );%@NL@%
- %@NL@%
- %@CR:MQP61404@%%@4@%You don't need to predefine a string type in order to pass a string.%@EH@%
- However, if the Var-String Checking option (in the dialog box for Compiler
- directives in the Options menu) is in effect (the default), the length of
- the string you pass must match exactly the length of the string the
- procedure expects. For example, if procedure %@AS@%print_str%@AE@% is declared as%@NL@%
- %@NL@%
- %@AS@% PROCEDURE print_str ( data_str : STRING[20] );%@NL@%
- %@NL@%
- %@CR:MQP61405@%%@4@%then you can only pass strings of type %@AS@%STRING[20]%@AE@%.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP61406@%%@4@%If Var-String Checking is turned off, then you can pass strings to%@EH@%
- parameters without regard to length. You can also pass variables of type
- %@AB@%STRING%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQP61407@%%@4@%Like all variables, arrays can be passed by value or by reference. When you%@EH@%
- pass an array by value, the entire array is copied to the stack. This can
- cause you to run out of stack memory quickly if you work with large arrays.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP61500@%%@3@%%@AB@%6.1.5 Using the Debugger with Arrays%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP61501@%%@4@%When you want to display an array during debugging, you can specify three%@EH@%
- different kinds of Watch expressions:%@NL@%
- %@NL@%
- %@CR:MQP61502@% 1. The entire array. You can watch all the elements of an array simply by%@NL@%
- specifying the array's name. The Watch window displays array elements%@NL@%
- as a list of comma-delimited items enclosed in parentheses. You may%@NL@%
- need to scroll through the Watch window to see all of the elements.%@NL@%
- %@NL@%
- 2. Specific array elements. You can watch individual elements of an array%@NL@%
- by specifying either a constant or variable as an index. If you use a%@NL@%
- variable, then QuickPascal displays a different element whenever the%@NL@%
- variable changes.%@NL@%
- %@NL@%
- 3. A subset of the array elements (a "subarray"). You can specify a%@NL@%
- subarray by using the following syntax:%@NL@%
- %@NL@%
- %@AI@%ArrayName%@AE@%%@AB@%[%@AE@%%@AI@% Index%@AE@%%@AB@%],%@AE@% %@AI@%Number%@AE@%%@NL@%
- %@NL@%
- For example, %@AS@%a[4],5%@AE@% permits you to view the subarray %@AS@%a[4]%@AE@% to %@AS@%a[9]%@AE@%. You%@NL@%
- can also use a variable as the index of the first item.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP62000@%%@2@%%@AB@%6.2 Records%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP62001@%%@4@%A record is a collection of variables that can have different types. Each%@EH@%
- variable within the record has a name to differentiate it from other
- variables in the record. This name is called a "field." To access an item in
- a record, you give both the record name and the field.%@NL@%
- %@NL@%
- %@CR:MQP62002@%%@4@%Records are common in practical applications. For example, consider a%@EH@%
- program that maintains airplane reservations. For each reservation, there
- are several relevant pieces of information: customer name, flight number,
- date, and time. You can combine all of this information into a single
- record.%@NL@%
- %@NL@%
- %@CR:MQP62003@%%@4@%Although you could keep track of the different data items in separate%@EH@%
- variables, placing them together in a single record makes programs easier to
- write and maintain. Furthermore, as you'll see in Chapter 10%@BO: 43fd9@%, "Binary
- Files," records are convenient units of data to read and write to disk.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP62100@%%@3@%%@AB@%6.2.1 Declaring Records%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP62101@%%@4@%Declare a record with the following syntax. The record can form part of a%@EH@%
- type definition or variable declaration.%@NL@%
- %@NL@%
- %@AB@%RECORD%@AE@%%@NL@%
- %@AI@%FieldDeclarations%@AE@%%@NL@%
- %@AB@%END%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP62102@%%@4@%In the syntax display above, %@AI@%FieldDeclarations%@AE@% is a variable declaration.%@EH@%
- The variable name determines the name of the %@AI@%Field%@AE@% (see examples). You must
- separate each field from the next with a semicolon.%@NL@%
- %@NL@%
- %@CR:MQP62103@%%@4@%The following lines show some simple record type definitions:%@EH@%%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% complex = RECORD%@NL@%
- %@AS@% x_real,%@NL@%
- %@AS@% y_imag : Real;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% mail_rec = RECORD%@NL@%
- %@AS@% name : STRING[20];%@NL@%
- %@AS@% street : STRING[25];%@NL@%
- %@AS@% city : STRING[5];%@NL@%
- %@AS@% state : STRING[2];%@NL@%
- %@AS@% zip : LongInt;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQP62104@%%@4@%Because of the highly structured nature of Pascal, each field can have any%@EH@%
- data type. A field can be an array or even another record. When a record
- appears as a field within another record, it is said to be "nested." For
- example, the type %@AS@%mail_list_rec%@AE@% shown below contains %@AS@%last_deleted_rec%@AE@%,
- which is another record, as one of its fields.%@NL@%
- %@NL@%
- %@AS@% mail_list_rec = RECORD%@NL@%
- %@AS@% num_recs : Word;%@NL@%
- %@AS@% last_update,%@NL@%
- %@AS@% last_mailing : STRING;%@NL@%
- %@AS@% last_deleted_rec : mail_rec;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQP62105@%%@4@%Arrays of records are common data types. For example, the following data%@EH@%
- structure creates a table of the grades of students in a math class:%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% table_rows = 1..30;%@NL@%
- %@AS@% stu_rec = RECORD%@NL@%
- %@AS@% name : STRING [20];%@NL@%
- %@AS@% test1_score,%@NL@%
- %@AS@% test2_score,%@NL@%
- %@AS@% test3_score : Word;%@NL@%
- %@AS@% grade_pt : REAL;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% table : ARRAY[table_rows] OF stu_rec;%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP62200@%%@3@%%@AB@%6.2.2 Accessing Record Fields%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP62201@%%@4@%To access an individual field of a record, you give both the name of the%@EH@%
- record variable and the name of the field:%@NL@%
- %@NL@%
- %@AI@%RecordName%@AE@%%@AB@%.%@AE@%%@AI@%FieldName%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP62202@%%@4@%The result is a data object of the type declared for the field. You can use%@EH@%
- the resulting item in any context that would be valid for an ordinary
- variable of the same type.%@NL@%
- %@NL@%
- %@CR:MQP62203@%%@4@%Consider the following record type:%@EH@%%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% mail_rec = RECORD%@NL@%
- %@AS@% name : STRING[20];%@NL@%
- %@AS@% street : STRING[25];%@NL@%
- %@AS@% city : STRING[5];%@NL@%
- %@AS@% state : STRING[2];%@NL@%
- %@AS@% zip : LongInt;%@NL@%
- %@AS@% END;%@NL@%
- %@AS@% mail_array = ARRAY [1..max_mailing] OF mail_rec;%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% my_mail : mail_rec;%@NL@%
- %@AS@% mailing : mail_array;%@NL@%
- %@NL@%
- %@CR:MQP62204@%%@4@%The following example assigns a string to the %@AS@%name%@AE@% field of the %@AS@%my_mail%@AE@%%@EH@%
- record variable declared above.%@NL@%
- %@NL@%
- %@AS@% my_mail.name := 'John Doe';%@NL@%
- %@NL@%
- %@CR:MQP62205@%%@4@%The expression %@AS@%my_mail.name%@AE@% is a string variable that can be assigned a%@EH@%
- value or passed to a function, just like any other string variable. For
- example, the following statement displays the name:%@NL@%
- %@NL@%
- %@AS@% Writeln( 'Addressee name is ', my_mail.name );%@NL@%
- %@NL@%
- %@CR:MQP62206@%%@4@%The syntax gets a little more complicated when you refer to an item within%@EH@%
- the array of records. For example, the following statement initializes the
- %@AS@%name%@AE@% field of the third array element:%@NL@%
- %@NL@%
- %@AS@% mailing[3].name := 'Hugo Bletch';%@NL@%
- %@NL@%
- %@CR:MQP62207@%%@4@%Consider how Pascal analyzes this expression. You can understand any complex%@EH@%
- expression by following similar logic:%@NL@%
- %@NL@%
- %@CR:MQP62208@% 1. The symbol %@AS@%mailing%@AE@% is declared as an array of records.%@NL@%
- %@NL@%
- 2. The expression %@AS@%mailing[3]%@AE@% is therefore an individual record.%@NL@%
- Specifically, it is the third record of the array.%@NL@%
- %@NL@%
- 3. The expression %@AS@%mailing[3].name%@AE@% refers to the %@AS@%name%@AE@% field in the third%@NL@%
- record of the array. The result is a variable of type %@AS@%STRING[20]%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQP62209@%%@4@%The data path to an object grows as you increase the levels of nesting. For%@EH@%
- example, consider the definition of the %@AS@%mail_rec%@AE@% type above plus the
- following additional statements:%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% MailArr = ARRAY[1..100] OF mail_rec;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% mailing_list : RECORD%@NL@%
- %@AS@% title : STRING;%@NL@%
- %@AS@% addresses : MailArr;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQP6220A@%%@4@%Given these declarations, you can access an individual name field as%@EH@%%@NL@%
- %@NL@%
- %@AS@% mailing_list.addresses[5].name%@NL@%
- %@NL@%
- %@CR:MQP6220B@%%@4@%The next section shows a technique for shortening the length of such%@EH@%
- expressions.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP62300@%%@3@%%@AB@%6.2.3 Using the WITH Statement to Access Fields%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP62301@%%@4@%While defining the full data path in a record makes your code more readable,%@EH@%
- it also increases the length of the identifiers. The QuickPascal %@AB@%WITH%@AE@%
- statement enables you to omit the name of a record variable from a block of
- statements. It has the following syntax:%@NL@%
- %@NL@%
- %@AB@%WITH %@AE@%%@AI@%RecordName%@AE@%%@AB@% DO %@AE@%%@AI@%Statement%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP62302@%%@4@%The %@AI@%Statement%@AE@% following %@AB@%DO%@AE@% can refer to fields in %@AI@%RecordName%@AE@% directly. For%@EH@%
- example, you can assign a string to the %@AS@%name%@AE@% field of record variable
- %@AS@%my_mail%@AE@% with the following statement:%@NL@%
- %@NL@%
- %@AS@% WITH my_mail DO%@NL@%
- %@AS@% name := 'John Doe';%@NL@%
- %@NL@%
- %@CR:MQP62303@%%@4@%To follow the %@AB@%DO%@AE@% keyword with more than one statement, use a %@AB@%BEGIN%@AE@%...%@AB@%END%@AE@%%@EH@%
- statement block.%@NL@%
- %@NL@%
- %@CR:MQP62304@%%@4@%In the case of nested records, the %@AB@%WITH%@AE@% statement may contain a record name%@EH@%
- modified by a field name. Always specify the outermost record first. For
- example, suppose %@AS@%name%@AE@% is a field of %@AS@%mail_rec%@AE@%, which in turn is a field of
- the record variable %@AS@%mail_list_rec%@AE@%. The following statement assigns a string
- to the %@AS@%name%@AE@% field:%@NL@%
- %@NL@%
- %@AS@% WITH mail_list_rec.mail_rec DO%@NL@%
- %@AS@% name := 'Hugo Bletch';%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP62400@%%@3@%%@AB@%6.2.4 Constant Records%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP62401@%%@4@%To declare a constant record, first define the record type, then declare the%@EH@%
- record and the initial value in a %@AB@%CONST%@AE@% statement. The initial value of a
- record consists of the following syntax:%@NL@%
- %@NL@%
- %@AB@%( %@AE@%%@AI@%FieldName%@AE@%%@AB@%: %@AE@%%@AI@%Constant%@AE@%%@AB@%;%@AE@% %@AI@%FieldName%@AE@% %@AB@%: %@AE@%%@AI@%Constant%@AE@% ... %@AB@%)%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP62402@%%@4@%The initial value for each field follows the rules for its type. For%@EH@%
- example, each row of an array initializer must be enclosed in parentheses.
- In the case of nested records, additional levels of parentheses and fields
- are required, as shown below.%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% complex = RECORD%@NL@%
- %@AS@% x_real,%@NL@%
- %@AS@% y_imag : Real;%@NL@%
- %@AS@% END;%@NL@%
- %@AS@% square_matrix = RECORD%@NL@%
- %@AS@% mat_size : Byte;%@NL@%
- %@AS@% imag : complex;%@NL@%
- %@AS@% determinant : Real;%@NL@%
- %@AS@% mat_x : ARRAY[1..3, 1..3] OF Real;%@NL@%
- %@AS@% END;%@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% origin : complex = ( x_real : 0.0; y_imag : 0.0 );%@NL@%
- %@AS@% def_mat : square_matrix = (%@NL@%
- %@AS@% mat_size : 3;%@NL@%
- %@AS@% imag : ( x_real : 1.0; y_imag : 1.0 );%@NL@%
- %@AS@% determinant : 0.0;%@NL@%
- %@AS@% mat_x :%@NL@%
- %@AS@% ( (1.0, 1.0, 1.0),%@NL@%
- %@AS@% (2.0, 2.0, 2.0),%@NL@%
- %@AS@% (3.0, 3.0, 3.0)%@NL@%
- %@AS@% )%@NL@%
- %@AS@% );%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP62500@%%@3@%%@AB@%6.2.5 Assigning Records to Record Variables%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP62501@%%@4@%Pascal supports the use of the assignment operator (%@AB@%:=%@AE@%) to assign the value%@EH@%
- of one record variable to another record. You can also assign one array to
- another if you declare the array type as a field within a record.%@NL@%
- %@NL@%
- %@CR:MQP62502@%%@4@%For example, if %@AS@%rec_a%@AE@% and %@AS@%rec_b%@AE@% are both arrays of the same type, you can%@EH@%
- use the following statement to assign one record to another:%@NL@%
- %@NL@%
- %@AS@% rec_a := rec_b;%@NL@%
- %@NL@%
- %@CR:MQP62503@%%@4@%As a further example, assume %@AS@%matrix1%@AE@% and %@AS@%matrix2%@AE@% are both records of the%@EH@%
- same type, and that this type contains an array field %@AS@%mat_x%@AE@%. You can use
- the following statement to assign one array field to another:%@NL@%
- %@NL@%
- %@AS@% matrix1.mat_x := matrix2.mat_x%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP62600@%%@3@%%@AB@%6.2.6 Using the Debugger with Records%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP62601@%%@4@%The Debug window displays the fields of a record as a list of data items%@EH@%
- enclosed in parentheses. Appending ",R" to the name of a watched record when
- it is put into the Debug window displays the names of the fields and their
- values. A colon separates the name of a field and its current value with
- this display format. You may need to scroll through the window to see all of
- the fields in the record.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP63000@%%@2@%%@AB@%6.3 Variant Records%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP63001@%%@4@%A variant record lets you provide a variety of data formats for the same%@EH@%
- area of memory. Whenever you refer to the variant record, you indicate which
- format to use. This capability is useful in the following situations:%@NL@%
- %@NL@%
- %@CR:MQP63002@% ■ You need flexibility within a general type of record. Suppose you want%@NL@%
- to create a record type to store data on each employee in a company.%@NL@%
- You'll want certain common fields, such as name, to apply to every%@NL@%
- employee. However, you may need to store different kinds of information%@NL@%
- on different kinds of employees.%@NL@%
- %@NL@%
- Variant records provide the needed flexibility. Instead of including%@NL@%
- all possible fields for all possible employees in every record (which%@NL@%
- would waste memory), you can create fields specific to each subgroup of%@NL@%
- employees.%@NL@%
- %@NL@%
- ■ You want to read data in one way and write it out in another way. While%@NL@%
- this situation is comparatively rare, it offers a perfect use for%@NL@%
- variant records. For example, you can simulate the behavior of%@NL@%
- microprocessors which permit the same register to be accessed either a%@NL@%
- byte at a time or a word at a time.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP63100@%%@3@%%@AB@%6.3.1 Declaring Variant Records%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP63101@%%@4@%The syntax for a variant record declaration is:%@EH@%%@NL@%
- %@NL@%
- %@AB@%RECORD%@AE@%%@NL@%
- %@AI@%FieldDeclarations%@AE@%%@NL@%
- %@AB@%CASE %@AE@%«%@AI@%Tag%@AE@%%@AB@%:%@AE@%»%@AI@%TagType%@AE@% %@AB@%OF%@AE@%%@NL@%
- %@AI@%CaseDeclarations%@AE@%%@NL@%
- %@AB@%END%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP63102@%%@4@%The %@AI@%FieldDeclarations%@AE@% make up the "fixed fields" of the record and are%@EH@%
- optional. The %@AI@%Tag%@AE@% is an optional field that you can use to indicate which of
- the cases (data formats) is active. Each %@AI@%CaseDeclaration%@AE@% has the following
- format:%@NL@%
- %@NL@%
- %@AI@%CaseLabel%@AE@%%@AB@%: (%@AE@%%@AI@%FieldDeclarations%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP63103@%%@4@%Separate each %@AI@%CaseDeclaration%@AE@% with a semicolon. The %@AI@%Tag%@AE@% and each %@AI@%CaseLabel%@AE@%%@EH@%
- must be of the %@AI@%TagType%@AE@%, which can be any valid ordinal type (such as an
- integer or user-defined type).%@NL@%
- %@NL@%
- %@CR:MQP63104@%%@4@%Each case declares a different series of fields. However, each case is%@EH@%
- overlaid in the same area of the record. Pascal allocates enough memory for
- the case that has the largest total size. This area is called the "variant
- portion" of the record. One case might use this area to store a string
- field. Another might use it to store floating-point fields.%@NL@%
- %@NL@%
- %@CR:MQP63105@%%@4@%The following example shows a variant record that models the registers of%@EH@%
- the 8086 processor:%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% regtype = (reg16, reg08);%@NL@%
- %@AS@% registers86 = RECORD%@NL@%
- %@AS@% CASE Integer OF%@NL@%
- %@AS@% 0 : ( ax, bx, cx, dx, si, di, bp, sp, flags : Word; );%@NL@%
- %@AS@% 1 : ( al, ah, bl, bh, cl, ch, dl, dh : Byte; );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQP63106@%%@4@%This type definition allows you to access the same data either as one 16-bit%@EH@%
- item, such as %@AS@%ax%@AE@%, or as two 8-bit items, such as %@AS@%al%@AE@% and %@AS@%ah%@AE@%.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP63200@%%@3@%%@AB@%6.3.2 Accessing Variant Record Fields%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP63201@%%@4@%You access all of the fields in the record the same way, regardless of%@EH@%
- whether they are fixed fields or defined within the variant portion of the
- record. (Consequently, the names of all fields in both the fixed and variant
- portions must be unique.) In addition, if a tag field is declared, you can
- set it to indicate which case is active.%@NL@%
- %@NL@%
- %@CR:MQP63202@%%@4@%For example (assuming the declaration of %@AS@%registers86%@AE@% at the end of the last%@EH@%
- section), the following statements load data into %@AS@%al%@AE@% and %@AS@%ah%@AE@%, and then
- display %@AS@%ax%@AE@%. Note that %@AS@%ax%@AE@% contains the same data as %@AS@%al%@AE@% and %@AS@%ah%@AE@% combined.%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% my_regs : registers86;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% my_regs.ah := $FF;%@NL@%
- %@AS@% my_regs.al := $10;%@NL@%
- %@AS@% Writeln ('AX now contains', my_regs.ax);%@NL@%
- %@NL@%
- %@CR:MQP63203@%%@4@%For another example, a simplified variant record scheme for the personnel%@EH@%
- system of a company might look like this:%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% clearance = (topsecret, secret, medium, low, known_spy);%@NL@%
- %@AS@% drink_type = ( martini, wine, champagne, teetotaler );%@NL@%
- %@AS@% games_type = ( tennis, squash, golf );%@NL@%
- %@AS@% title = ( secretary, engineer, exec );%@NL@%
- %@NL@%
- %@AS@% emp_rec = RECORD%@NL@%
- %@AS@% name : STRING[20];%@NL@%
- %@AS@% CASE job : title OF%@NL@%
- %@AS@% secretary : ( wpm, steno : Word );%@NL@%
- %@AS@% engineer : ( security : clearance; IQ : Byte );%@NL@%
- %@AS@% exec : ( beverage : drink_type;%@NL@%
- %@AS@% pastime : games_type;%@NL@%
- %@AS@% washroom_code : LongInt );%@NL@%
- %@AS@% END;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% new_emp : emp_rec;%@NL@%
- %@NL@%
- %@CR:MQP63204@%%@4@%The following code initializes the %@AS@%new_emp%@AE@% record variable for a recently%@EH@%
- hired engineer:%@NL@%
- %@NL@%
- %@AS@% new_emp.name := 'Jane Eyre';%@NL@%
- %@AS@% new_emp.job := engineer;%@NL@%
- %@AS@% new_emp.security := secret;%@NL@%
- %@AS@% new_emp.IQ := 120;%@NL@%
- %@NL@%
- %@CR:MQP63205@%%@4@%Now suppose that Jane Eyre is promoted into management. The old data%@EH@%
- relevant to engineers (security clearance and IQ) is no longer relevant to
- Jane in her new position. Fortunately, the variant record type lets you
- reuse this same area of memory to put in data relevant to managers.%@NL@%
- %@NL@%
- %@CR:MQP63206@%%@4@%First, the program makes Jane's promotion official:%@EH@%%@NL@%
- %@NL@%
- %@AS@% new_emp.job := exec;%@NL@%
- %@NL@%
- %@CR:MQP63207@%%@4@%The program then enters Jane's new data. To accommodate Jane's rise up the%@EH@%
- corporate ladder, the program records her favorite drink, favorite pastime,
- and key code for the executive washroom. This information is overwritten
- onto the engineer data, which is no longer needed.%@NL@%
- %@NL@%
- %@AS@% new_emp.beverage := martini;%@NL@%
- %@AS@% new_emp.pastime := tennis;%@NL@%
- %@AS@% new_emp.washroom_code := 12345007;%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP70000@%%@1@%%@AB@%Chapter 7 Units%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQP70001@%%@4@%Units extend the usefulness of QuickPascal by giving your programs access to%@EH@%
- additional declarations and procedures. A "unit" is defined as a related
- collection of such declarations and procedures. Referencing a unit's name at
- the beginning of a program gives you access to that unit's contents just as
- though they were a part of standard Pascal. QuickPascal comes with several
- predefined (or "standard") units, and you can also write your own.%@NL@%
- %@NL@%
- %@CR:MQP70002@%%@4@%This chapter explains both how to use QuickPascal standard units and how to%@EH@%
- create your own units.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP71000@%%@2@%%@AB@%7.1 Understanding Units%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP71001@%%@4@%If you've done much programming in another language, you're probably%@EH@%
- familiar with libraries. Libraries usually provide specialized routines not
- normally part of the language. Pascal units work on a similar concept but
- have a broader scope and application. They contain not only procedures and
- functions but also variables, constants, and type declarations. In addition,
- a unit can execute some code when the program starts and do anything a
- program can, like open files or get user input. These are important
- differences from libraries in another programming language.%@NL@%
- %@NL@%
- %@CR:MQP71002@%%@4@%Once you tell QuickPascal that your program uses a particular unit, you can%@EH@%
- access the procedures, functions, and declarations defined in that unit just
- as you would any standard procedure, function, or declaration.%@NL@%
- %@NL@%
- %@CR:MQP71003@%%@4@%Units effectively extend the portion of a program between the header and the%@EH@%
- main program body──the area where all the declarations appear. Instead of
- writing a tremendous number of declarations, procedures, and functions, you
- can use a unit and get the same results.%@NL@%
- %@NL@%
- %@CR:MQP71004@%%@4@%If you use some of your own procedures repeatedly, you can create a custom%@EH@%
- unit and make the procedures available to all your programs. And, rewriting
- large programs to use units removes some of the constraints of the 64K
- segment limit. Each unit gets its own segment, so creating just one unit
- doubles your programming space. Programs can use up to 81 units.%@NL@%
- %@NL@%
- %@CR:MQP71005@%%@4@%QuickPascal standard units broaden your programs' general capabilities; the%@EH@%
- custom units you write provide any specific functionality you need.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP72000@%%@2@%%@AB@%7.2 Using Units in a Program%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP72001@%%@4@%You access a unit by adding the %@AB@%USES%@AE@% statement and the unit's name under the%@EH@%
- %@AB@%PROGRAM%@AE@% declaration. For example, the lines%@NL@%
- %@NL@%
- %@AS@% USES%@NL@%
- %@AS@% Crt, Dos;%@NL@%
- %@NL@%
- %@CR:MQP72002@%%@4@%let you use any of the procedures defined in either the %@AS@%Crt%@AE@% or %@AS@%Dos%@AE@% units in%@EH@%
- your program, just as you would any local procedure. Any variables,
- constants, or types declared in the unit are available to your program. (If
- you write programs that need many variables or constants, declaring them in
- a custom unit can simplify your main program and make debugging easier.)%@NL@%
- %@NL@%
- %@CR:MQP72003@%%@4@%Here's a more complete example that shows a unit in context:%@EH@%%@NL@%
- %@NL@%
- %@AS@% PROGRAM lil_unit_test;%@NL@%
- %@AS@% USES%@NL@%
- %@AS@% Crt;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Write( 'Press any key to end' );%@NL@%
- %@AS@% REPEAT UNTIL KeyPressed;%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP72004@%%@4@%Once you put the unit in the %@AB@%USES%@AE@% list, you're free to use its contents just%@EH@%
- like any other Pascal procedures, functions, and declarations.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP73000@%%@2@%%@AB@%7.3 Standard QuickPascal Units%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP73001@%%@4@%QuickPascal comes with several standard units. They enhance your control%@EH@%
- over the screen and text, DOS routines, printer use, and graphics.
- QuickPascal automatically inserts one other standard unit, %@AB@%System%@AE@%, into
- every program you compile. It supplies all of the standard procedures and
- functions.%@NL@%
- %@NL@%
- %@CR:MQP73002@%%@4@%QuickPascal standard units include the following:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP73003@%%@AB@%Unit name Description%@AE@%%@NL@%
- %@NL@%
- %@AB@%Crt%@AE@% Handles keyboard input, screen/window%@NL@%
- management, color selection, and cursor control.%@NL@%
- %@NL@%
- %@AB@%Dos%@AE@% Manipulates DOS files and directories, and%@NL@%
- performs other DOS functions.%@NL@%
- %@NL@%
- %@AB@%Printer%@AE@% Gives programs access to a printer.%@NL@%
- %@NL@%
- %@AB@%MSGraph%@AE@% Creates graphics and displays text in different%@NL@%
- sizes and type styles.%@NL@%
- %@NL@%
- %@AB@%System%@AE@% Contains the run-time system including the%@NL@%
- QuickPascal standard procedures and functions.%@NL@%
- This unit is automatically used by all%@NL@%
- QuickPascal programs; you do not need to%@NL@%
- explicitly declare it.%@NL@%
- %@NL@%
- %@CR:MQP73004@%%@4@%If you consistently use procedures not available in the standard units,%@EH@%
- consider creating your own unit. Like a program, a custom unit can reference
- other units. Both types of units──standard and custom──add power and
- flexibility to your programs.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP74000@%%@2@%%@AB@%7.4 Creating Your Own Units%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP74001@%%@4@%QuickPascal standard units supply most of the procedures you commonly need.%@EH@%
- Yet you may need a special function repeatedly or want to initialize a large
- number of variables, constants, or data types. Or you may wish to share
- procedures with other programmers. In any case, a convenient solution is to
- write your own unit.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP74100@%%@3@%%@AB@%7.4.1 Writing a New Unit%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP74101@%%@4@%QuickPascal units look similar to other Pascal programs, with the following%@EH@%
- differences:%@NL@%
- %@NL@%
- %@CR:MQP74102@% ■ Units begin with a different keyword.%@NL@%
- %@NL@%
- ■ An %@AB@%INTERFACE%@AE@% section indicates what the program using the unit can%@NL@%
- access.%@NL@%
- %@NL@%
- ■ An %@AB@%IMPLEMENTATION%@AE@% section defines any procedures and functions in your%@NL@%
- unit.%@NL@%
- %@NL@%
- %@CR:MQP74110@%%@4@%%@AB@%Beginning a Unit%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP74111@%%@4@%Just as any program begins with the keyword %@AB@%PROGRAM%@AE@%, every unit begins with%@EH@%
- a %@AB@%UNIT%@AE@% keyword:%@NL@%
- %@NL@%
- %@AS@% UNIT new_unit;%@NL@%
- %@NL@%
- %@CR:MQP74112@%%@4@%The %@AB@%UNIT%@AE@% keyword tells QuickPascal to compile the file into a unit rather%@EH@%
- than an executable program. The compiled unit receives the same name as its
- source file, with the .QPU extension added. Unit source files usually keep
- the .PAS extension.%@NL@%
- %@NL@%
- %@CR:MQP74120@%%@4@%%@AB@%Interface Portion%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP74121@%%@4@%Everything in the next section, the %@AB@%INTERFACE%@AE@% portion of the unit, becomes%@EH@%
- "public" information to any programs that use the unit. It includes any
- units needed by this unit; the declarations of any public variables,
- constants, or data types; and the calling format for any procedures or
- functions (including declarations of all parameters). The actual code for
- the procedures and functions comes later.%@NL@%
- %@NL@%
- %@CR:MQP74122@%%@4@%Consider the following sample %@AB@%INTERFACE%@AE@% section:%@EH@%%@NL@%
- %@NL@%
- %@AS@% INTERFACE { Public information }%@NL@%
- %@NL@%
- %@AS@% USES%@NL@%
- %@AS@% Crt;%@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% days_per_year = 365;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE center_line( message : STRING );%@NL@%
- %@AS@% FUNCTION cube( num : Real ) : Real;%@NL@%
- %@NL@%
- %@CR:MQP74123@%%@4@%These lines tell QuickPascal that this unit uses the standard %@AB@%Crt%@AE@% unit,%@EH@%
- establishes the constant %@AS@%days_per_year%@AE@%, and makes one procedure
- (%@AS@%center_line%@AE@%) and one function (%@AS@%cube%@AE@%) publicly available.%@NL@%
- %@NL@%
- %@CR:MQP74130@%%@4@%%@AB@%Implementation Portion%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP74131@%%@4@%The second part of a unit, the %@AB@%IMPLEMENTATION%@AE@% portion, defines the%@EH@%
- procedures given in the %@AB@%INTERFACE%@AE@% portion and any data necessary to
- implement those procedures. This data may include any new definitions of
- variables, constants, types, labels, and support procedures (procedures that
- assist the primary procedures). The complete code for every %@AB@%PROCEDURE%@AE@% or
- %@AB@%FUNCTION%@AE@% declared in the %@AB@%INTERFACE%@AE@% section must appear in the %@AB@%IMPLEMENTATION%@AE@%
- section.%@NL@%
- %@NL@%
- %@CR:MQP74132@%%@4@%The following %@AB@%IMPLEMENTATION%@AE@% section includes both a new variable and a%@EH@%
- support function:%@NL@%
- %@NL@%
- %@AS@% IMPLEMENTATION%@NL@%
- %@AS@% { Private information available only to new_unit }%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% back : Word;%@NL@%
- %@NL@%
- %@AS@% FUNCTION cube( num : Real ) : Real;%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% temp : Real;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% temp := Sqr( num );%@NL@%
- %@AS@% cube := temp * num;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% FUNCTION calc_start( message : STRING ) : %@AS@%Integer;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% calc_start := (80 - Length( message )) DIV 2;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE center_line( message : STRING );%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% GotoXY( calc_start( message ), WhereY );%@NL@%
- %@AS@% Writeln( message );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% { Initialization part }%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'What background color would you like ?' );%@NL@%
- %@AS@% Write( '(0..7) :' );%@NL@%
- %@AS@% Readln( back );%@NL@%
- %@AS@% TextBackground( back );%@NL@%
- %@AS@% ClrScr;%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP74133@%%@4@%In QuickPascal, %@AB@%VAR%@AE@%, %@AB@%CONST%@AE@%, %@AB@%PROCEDURE%@AE@%, and %@AB@%FUNCTION%@AE@% declarations may come%@EH@%
- in any order. However, you must declare supporting procedures and
- functions──in this case the %@AS@%calc_start%@AE@% function, called by the %@AS@%center_line%@AE@%
- procedure──prior to calling them from within another procedure. Be sure to
- include the definition for every procedure listed in the %@AB@%INTERFACE%@AE@% portion
- of the program. Omitting any definition causes an %@AS@%Unsatisfied forward%@AE@%
- %@AS@%reference%@AE@% error.%@NL@%
- %@NL@%
- %@CR:MQP74134@%%@4@%Although the compiler does not require you to list each procedure's%@EH@%
- parameters (as it did in the %@AB@%INTERFACE%@AE@% portion), it is generally considered
- good programming practice to do so. Keep in mind that if you do repeat the
- parameters, they must exactly match the parameters listed in the %@AB@%INTERFACE%@AE@%
- portion.%@NL@%
- %@NL@%
- %@CR:MQP74140@%%@4@%%@AB@%Viewing the Entire Unit%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP74141@%%@4@%Together, the three previous examples form a complete unit. A program that%@EH@%
- uses %@AS@%new_unit%@AE@% gets access to the constant %@AS@%days_per_year%@AE@%, the procedure
- %@AS@%center_line%@AE@%, and the function %@AS@%cube%@AE@%. However, the program cannot access the
- %@AS@%calc_start%@AE@% function or the %@AS@%temp%@AE@% variable because they appear in the
- %@AB@%IMPLEMENTATION%@AE@% section; that section remains entirely "hidden" to the
- program using the unit.%@NL@%
- %@NL@%
- %@CR:MQP74142@%%@4@%When you finish writing a unit, save the source code with the unit's name%@EH@%
- and the .PAS extension. The next step, compiling the unit, is discussed in
- the following section.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP74200@%%@3@%%@AB@%7.4.2 Compiling a Unit%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP74201@%%@4@%You compile a unit in the same manner you compile a program. Choose the%@EH@%
- Compile File command on the Make menu. If your code contains errors that
- prevent the unit from compiling, QuickPascal displays an error message. When
- you remove the message, the cursor appears at the point QuickPascal detected
- the error. Correct the error and repeat the process until the unit compiles.%@NL@%
- %@NL@%
- %@CR:MQP74202@%%@4@%Alternately, you can compile the main program and a new unit in one step by%@EH@%
- choosing the Rebuild Main File command on the Make menu (or specify the /R
- option if you compile from the QPL command line). Again, if QuickPascal
- encounters any errors, the compilation halts and an error message appears.
- You must compile all of the custom units a program references before you can
- compile the main program.%@NL@%
- %@NL@%
- %@CR:MQP74203@%%@4@%Once your unit compiles properly, you can use it in any of your programs%@EH@%
- just as you would use any of the standard units. If you change a program
- that uses a custom unit, you need to recompile only that program (and not
- the unit). However, if you change the unit itself, you may need to recompile
- both the unit and the program. The Build Main File and Rebuild Main File
- commands on the Make menu simplify this task.%@NL@%
- %@NL@%
- %@CR:MQP74204@%%@4@%The Build Main File command recompiles all the source files that changed%@EH@%
- since the last Build Main File command was executed. Rebuild Main File
- recompiles the program and all of its associated custom units, regardless of
- whether anything changed. See the QP Advisor or "Compiling a Multiple-Module
- Program" in Chapter 3 of %@AI@%Up and Running%@AE@% for a step-by-step approach to
- compiling.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP74300@%%@3@%%@AB@%7.4.3 Tips for Programming with Units%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP74301@%%@4@%When you program with units, avoid using identifiers with the same name in%@EH@%
- different units and circular references between units.%@NL@%
- %@NL@%
- %@CR:MQP74310@%%@4@%%@AB@%Identifiers with the Same Name%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP74311@%%@4@%When two or more units contain identifiers (such as constant or procedure%@EH@%
- names) that share the same name, the identifier "belongs" to the unit most
- recently used. QuickPascal uses units in the order they appear in the %@AB@%USES%@AE@%
- statement.%@NL@%
- %@NL@%
- %@CR:MQP74312@%%@4@%To avoid any confusion, you can reference an identifier in a manner similar%@EH@%
- to referencing fields in records using this syntax:%@NL@%
- %@NL@%
- %@AI@%UnitName%@AE@%%@AB@%.%@AE@%%@AI@%Identifier%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP74313@%%@4@%For example, if you have a %@AS@%ClrScr%@AE@% procedure called SCRSTUFF.QPU, you can%@EH@%
- reference it in your code as %@AS@%ScrStuff.ClrScr%@AE@% in a unit, and the standard
- %@AB@%ClrScr%@AE@% can be referenced as %@AS@%Crt.ClrScr%@AE@%. Then the order of the units in the
- %@AB@%USES%@AE@% declaration becomes irrelevant.%@NL@%
- %@NL@%
- %@CR:MQP74320@%%@4@%%@AB@%Circular Referencing%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP74321@%%@4@%QuickPascal permits two units to reference each other. UNIT_A can use%@EH@%
- UNIT_B, and UNIT_B can use UNIT_A. However, QuickPascal does not support
- circular referencing between three or more units. QuickPascal won't compile
- a program in which UNIT_A uses UNIT_B which uses UNIT_C which uses UNIT_A
- (an A-B-C-A loop). Careful planning can avoid problems with circular
- referencing.%@NL@%
- %@NL@%
- %@CR:MQP74322@%%@4@%The order of the units listed after the %@AB@%USES%@AE@% declaration is not important%@EH@%
- unless their procedures have the same names, or the initialization code in
- one unit interferes with the initialization code in another unit.%@NL@%
- %@NL@%
- %@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@CR:MQPP2000@%%@1@%%@AB@%Part 2 Programming Topics%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPP2003@%%@4@%Part 2 of %@AI@%Pascal by Example%@AE@% assumes you either have read Part 1, "Pascal%@EH@%
- Basics," or already know Pascal's basic concepts. Part 2 covers more
- advanced programming concepts that give your programs additional
- flexibility. Topics include enhancing keyboard and screen control, saving
- and extracting data from files, and using pointers. The final chapter is
- devoted entirely to advanced topics that experienced programmers may find
- particularly interesting.%@NL@%
- %@NL@%
- %@CR:MQPP2004@%%@4@%While Part 1 was designed to be read sequentially, this part is much more%@EH@%
- topical. You may read the chapters in any order. If you're using %@AI@%Pascal by%@AE@%
- %@AI@%Example%@AE@% to learn Pascal, however, consider reading the chapter on text files
- before you try working with binary files.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP80000@%%@1@%%@AB@%Chapter 8 The Keyboard and Screen%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQP80001@%%@4@%Virtually all programs receive or send out information in some way, perhaps%@EH@%
- accepting it from the keyboard or a file, perhaps printing it to the screen
- or a printer. QuickPascal supports all of the input and output features of
- standard Pascal and includes a unit specifically designed to enhance your
- programs' appearance and ease of use.%@NL@%
- %@NL@%
- %@CR:MQP80002@%%@4@%This chapter contains two parts. The first covers the basics of Pascal input%@EH@%
- and output and how to format output. The second part introduces the %@AB@%Crt%@AE@% unit
- and how to use it to refine control of both the keyboard and the screen.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP81000@%%@2@%%@AB@%8.1 Basic Input and Output%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP81001@%%@4@%Pascal provides the %@AB@%Read%@AE@% and %@AB@%Readln%@AE@% procedures for input and the %@AB@%Write%@AE@% and%@EH@%
- %@AB@%Writeln%@AE@% procedures for output. These procedures can handle both single data
- items and lists of items separated by commas. All four use similar syntax:%@NL@%
- %@NL@%
- %@AB@%Read(%@AE@%«%@AI@%FileName%@AE@%%@AB@%,%@AE@% » %@AI@%InputVariable%@AE@%%@AB@%) %@AE@%«%@AB@%, %@AE@%%@AI@%InputVariable%@AE@%...»%@NL@%
- %@NL@%
- %@CR:MQP81002@%%@4@%and%@EH@%%@NL@%
- %@NL@%
- %@AB@%Write(%@AE@%«%@AI@%FileName%@AE@%%@AB@%,%@AE@% » %@AI@%OutputVariable%@AE@% «%@AB@%:%@AE@% %@AI@%Width%@AE@%«:%@AI@%Decimals%@AE@%»»%@NL@%
- «%@AB@%,%@AE@%%@AI@%OutputVariable%@AE@% « %@AB@%:%@AE@%%@AI@%Width%@AE@%«%@AB@%:%@AE@%%@AI@%Decimals%@AE@%»»»%@AB@%)%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP81003@%%@4@%where %@AI@%FileName%@AE@% optionally refers to a disk file or device (such as a printer%@EH@%
- or a modem), and %@AI@%Width%@AE@% and %@AI@%Decimals%@AE@% refer to formatting information. Without
- %@AI@%FileName%@AE@%, %@AB@%Read%@AE@% accepts data from the standard input device (usually the
- keyboard) and %@AB@%Write%@AE@% sends data to the standard output device (usually the
- screen).%@NL@%
- %@NL@%
- %@CR:MQP81004@%%@4@%If either %@AB@%Read%@AE@% or %@AB@%Write%@AE@% encounters an error, the program terminates with a%@EH@%
- run-time error message. You can include the %@AB@%{$I-}%@AE@% compiler directive in your
- program if you want your program to continue despite %@AB@%Read%@AE@% or %@AB@%Write%@AE@% run-time
- errors.%@NL@%
- %@NL@%
- %@CR:MQP81005@%%@4@%If you choose to use the %@AB@%{$I-}%@AE@% compiler directive, you need to call the%@EH@%
- function %@AB@%IOResult%@AE@% immediately after each input or output operation. The
- value returned by %@AB@%IOResult%@AE@% indicates whether an error occurred. QuickPascal
- ignores any input or output attempts after an error, unless you call
- %@AB@%IOResult%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQP81006@%%@4@%Sections 8.1.1%@BO: 36a44@% and 8.1.2%@BO: 37b4e@% cover the basic use of the %@AB@%Read%@AE@% and %@AB@%Write%@AE@%%@EH@%
- statements. Section 8.2%@BO: 3a5eb@% goes into the formatting details (of %@AI@%Width%@AE@% and
- %@AI@%Decimals%@AE@%). For further information on using %@AB@%Read%@AE@% and %@AB@%Write%@AE@% with data files
- and other devices (by using %@AI@%FileName%@AE@%), read Chapter 9%@BO: 3efa5@%, "Text Files," and
- Chapter 10, "Binary Files."%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP81100@%%@3@%%@AB@%8.1.1 Read and Readln Procedures%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP81101@%%@4@%The %@AB@%Read%@AE@% and %@AB@%Readln%@AE@% procedures place data into one or more "input%@EH@%
- variables." Most commonly, %@AB@%Read%@AE@% and %@AB@%Readln%@AE@% receive their input from the
- keyboard or a data file.%@NL@%
- %@NL@%
- %@CR:MQP81102@%%@4@%The input variables must belong to one of the predefined data types (except%@EH@%
- Boolean) or a subrange type you defined, and they must be of a type that can
- accept the kind of data you're trying to read. For example, an input
- variable of type %@AB@%Char%@AE@% cannot accept a %@AB@%Real%@AE@% value. See Chapter 2%@BO: bdde@%,
- "Programming Basics," for information on assigning data types.%@NL@%
- %@NL@%
- %@CR:MQP81103@%%@4@%%@AB@%Readln%@AE@% attempts to read data into the list of input variables. If the number%@EH@%
- of data items typed on a single line exceeds the number of variables, the
- additional data items are ignored. However, if %@AB@%Readln%@AE@% receives fewer data
- items than the number of input variables, it expects the additional data to
- appear on subsequent lines. For example, the %@AB@%Readln%@AE@% statement in the
- following excerpt expects three values:%@NL@%
- %@NL@%
- %@AS@% Writeln( 'For the investment what are: present value,' );%@NL@%
- %@AS@% Writeln( 'annual return, and number of years invested?' );%@NL@%
- %@AS@% Readln( present_value, rate_of_return, years_invested );%@NL@%
- %@NL@%
- %@CR:MQP81104@%%@4@%Suppose you run the program and in response to the prompt%@EH@%%@NL@%
- %@NL@%
- %@AS@%For the investment what are: present value,%@AE@%%@NL@%
- %@AS@%annual return, and number of years invested?%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP81105@%%@4@%you type%@EH@%%@NL@%
- %@NL@%
- %@AS@%3000.00 1.05%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP81106@%%@4@%and press ENTER. The program will then wait for you to enter the final%@EH@%
- value. You must remember to use spaces, tabs, or carriage returns to
- separate the values. Using commas causes a run-time error. If you're
- concerned about the possibility of such errors, you can either write the
- program with one %@AB@%Readln%@AE@% statement for each item entered, or read the data as
- a string of text and create a procedure to separate the string into numbers.%@NL@%
- %@NL@%
- %@CR:MQP81107@%%@4@%The %@AB@%Read%@AE@% procedure, in contrast, reads only enough data to fill its input%@EH@%
- variables. But subsequent %@AB@%Read%@AE@% or %@AB@%Readln%@AE@% procedures may get the remaining
- data.%@NL@%
- %@NL@%
- %@CR:MQP81108@%%@4@%Suppose you rewrote the example above as%@EH@%%@NL@%
- %@NL@%
- %@AS@% Writeln( 'For the investment what are: present value?' );%@NL@%
- %@AS@% Read( present_value )%@NL@%
- %@AS@% Writeln( 'the annual return?' );%@NL@%
- %@AS@% Read( rate_of_return );%@NL@%
- %@AS@% Writeln( 'and the number of years invested?' );%@NL@%
- %@AS@% Read( years_invested );%@NL@%
- %@NL@%
- %@CR:MQP81109@%%@4@%and ran the program with this response%@EH@%%@NL@%
- %@NL@%
- %@AS@%For the investment what are: present value?%@AE@%%@NL@%
- %@AS@%3000.00 12.8 37%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP8110A@%%@4@%The program would then accept %@AS@%3000.00%@AE@% as %@AS@%present_value%@AE@% and immediately print%@EH@%
- the two remaining prompts without stopping:%@NL@%
- %@NL@%
- %@AS@%the annual return?%@AE@%%@NL@%
- %@AS@%and the number of years invested?%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP8110B@%%@4@%and set %@AS@%rate_of_return%@AE@% and %@AS@%years_invested%@AE@% equal to %@AS@%12.8%@AE@% and %@AS@%37%@AE@%,%@EH@%
- respectively. Unless your program performs some type of error checking,
- using such a series of %@AB@%Read%@AE@% statements can potentially introduce errors.%@NL@%
- %@NL@%
- %@CR:MQP8110C@%%@4@%Like %@AB@%Readln%@AE@%, %@AB@%Read%@AE@% accepts all of the Pascal standard data types but inputs%@EH@%
- them differently. Character data is not delimited; %@AB@%Read%@AE@% assigns any kind of
- input to character variables, including carriage returns, spaces, and so on.
- Strings input with %@AB@%Read%@AE@% can include any combination of ASCII text except for
- a carriage return, which signifies the end of the string. For numeric data,
- %@AB@%Read%@AE@% ignores any leading blanks, begins with the first number or sign (+ or
- -), and continues until it reaches the next white-space character or
- carriage return.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP81200@%%@3@%%@AB@%8.1.2 Write and Writeln Procedures%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP81201@%%@4@%The %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% procedures enable you to send variables, constants,%@EH@%
- and strings to the screen, disk files, or other output devices. The
- variables or constants you use in %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% may be any of the Pascal
- standard data types or a subrange of any of these types.%@NL@%
- %@NL@%
- %@CR:MQP81202@%%@4@%%@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% differ only in that %@AB@%Writeln%@AE@% terminates the line after%@EH@%
- sending its data to the output device. Subsequent output appears on the next
- line.%@NL@%
- %@NL@%
- %@CR:MQP81203@%%@4@%You often use the %@AB@%Write%@AE@% statement to print prompts on the screen. %@AB@%Writeln%@AE@%%@EH@%
- displays full lines of text and is useful for leaving blank lines on the
- screen for aesthetic purposes.%@NL@%
- %@NL@%
- %@CR:MQP81204@%%@4@%%@AB@%Write%@AE@% is often used with %@AB@%Read%@AE@% for simple prompt-and-reply input:%@EH@%%@NL@%
- %@NL@%
- %@AS@% Write( 'Please enter two integers separated by a space: ' );%@NL@%
- %@AS@% Read( Int1, Int2 );%@NL@%
- %@NL@%
- %@CR:MQP81205@%%@4@%For complete lines of text and for blank lines, you might use %@AB@%Writeln%@AE@%:%@EH@%%@NL@%
- %@NL@%
- %@AS@% Writeln( 'The Very Model of a Modern Major General' );%@NL@%
- %@AS@% Writeln( '========================================' );%@NL@%
- %@AS@% Writeln;%@NL@%
- %@AS@% Writeln('By Shorty Bonaparte');%@NL@%
- %@NL@%
- %@CR:MQP81206@%%@4@%Note that the strings of text appear at the left edge of the screen.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP81207@%%@4@%By themselves, %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% do not provide much numerical formatting;%@EH@%
- they print numbers in a default format according to the type of variable.
- For example, the output from%@NL@%
- %@NL@%
- %@AS@% real_num := 3.1415;%@NL@%
- %@AS@% long_int := 1234567;%@NL@%
- %@AS@% Writeln( 'A real number prints out as ', real_num,'.' );%@NL@%
- %@AS@% Writeln( 'And a long integer prints as ', long_int,'.' );%@NL@%
- %@NL@%
- %@CR:MQP81208@%%@4@%looks like%@EH@%%@NL@%
- %@NL@%
- %@AS@%A real number prints out as 3.14150000000154E+0000.%@AE@%%@NL@%
- %@AS@%And a long integer prints as 1234567.%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP81209@%%@4@%The next section explains how to change these default formats.%@EH@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP81300@%%@3@%%@AB@%8.1.3 Formatted Output with Write and Writeln%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP81301@%%@4@%The default numerical output format for real numbers is scientific notation.%@EH@%
- For integers, the default output format is a sequence of digits. And, Pascal
- normally prints strings as left justified. But %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% do allow
- you to change the default formats.%@NL@%
- %@NL@%
- %@CR:MQP81302@%%@4@%Recall that the %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% statements follow the syntax:%@EH@%%@NL@%
- %@NL@%
- %@AB@%Write(%@AE@%«%@AI@%FileName%@AE@%%@AB@%,%@AE@% » %@AI@%OutputVariable%@AE@% «%@AB@%:%@AE@% %@AI@%Width%@AE@%«%@AB@%:%@AE@%%@AI@%Decimals%@AE@%»»%@NL@%
- «%@AB@%,%@AE@%%@AI@%OutputVariable%@AE@% « %@AB@%:%@AE@%%@AI@%Width%@AE@%«%@AB@%:%@AE@%%@AI@%Decimals%@AE@%»»»%@AB@%)%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP81303@%%@4@%The two optional fields %@AI@%Width%@AE@% and %@AI@%Decimals%@AE@% control formatting. The %@AI@%Width%@AE@%%@EH@%
- field sets the maximum number of spaces available for printing the variable
- called %@AI@%OutputVariable%@AE@% and indicates right or left justification by its sign
- (positive for right justification, negative for left).%@NL@%
- %@NL@%
- %@CR:MQP81304@%%@4@%Pascal formats text and integer data in a similar fashion. These statements%@EH@%
- print out the integer %@AS@%my_int%@AE@% and the string %@AS@%my_str%@AE@% in a space six columns
- wide and right justified:%@NL@%
- %@NL@%
- %@AS@% Writeln( my_int:6 );%@NL@%
- %@AS@% Writeln( my_str:6 );%@NL@%
- %@NL@%
- %@CR:MQP81305@%%@4@%If either %@AS@%my_int%@AE@% or %@AS@%my_str%@AE@% exceeds a width of six columns, QuickPascal%@EH@%
- prints the entire integer or string with the default format.%@NL@%
- %@NL@%
- %@CR:MQP81306@%%@4@%Variables of type %@AB@%Real%@AE@% can also specify %@AI@%Decimals%@AE@%, which indicates the number%@EH@%
- of digits to appear to the right of the decimal point. You cannot specify
- %@AI@%Decimals%@AE@% for integers or strings.%@NL@%
- %@NL@%
- %@CR:MQP81307@%%@4@%The %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% procedures do not truncate strings or any type of%@EH@%
- numerical data. If %@AI@%OutputVariable%@AE@% is wider than %@AI@%Width%@AE@%, %@AI@%Width%@AE@% is overridden
- and the entire %@AI@%OutputVar%@AE@% is printed. For floating-point types, %@AB@%Write%@AE@% and
- %@AB@%Writeln%@AE@% always print the number of decimal places specified by %@AI@%Decimals%@AE@%,
- even if it means overriding the %@AI@%Width%@AE@% specification.%@NL@%
- %@NL@%
- %@CR:MQP81308@%%@4@%The following line right justifies a real number%@AS@%realnum%@AE@% and displays it with%@EH@%
- four decimal places:%@NL@%
- %@NL@%
- %@AS@% Writeln( realnum:12:4 )%@NL@%
- %@NL@%
- %@CR:MQP81309@%%@4@%Provided %@AS@%realnum%@AE@% contains 12 or fewer digits, the last digit lies in column%@EH@%
- 12.%@NL@%
- %@NL@%
- %@CR:MQP8130A@%%@4@%This example%@EH@%%@NL@%
- %@NL@%
- %@AS@% int_var := 12345;%@NL@%
- %@AS@% str_var := 'This sentence is a string.';%@NL@%
- %@AS@% real_var := 9870.65434;%@NL@%
- %@NL@%
- %@AS@% Writeln( '1234567890123456789012345678901234567890 Ruler' );%@NL@%
- %@AS@% Writeln( ' 10 20 30 40' );%@NL@%
- %@AS@% Writeln( int_var : 8 );%@NL@%
- %@AS@% Writeln( int_var : 85 );%@NL@%
- %@AS@% Writeln( str_var : 35 );%@NL@%
- %@AS@% Writeln( str_var : -3 );%@NL@%
- %@AS@% Writeln( real_var : -2 : 6 );%@NL@%
- %@AS@% Writeln( real_var : 14 : 2 );%@NL@%
- %@NL@%
- %@CR:MQP8130B@%%@4@%produces the following output:%@EH@%%@NL@%
- %@NL@%
- %@AS@%1234567890123456789012345678901234567890 Ruler%@AE@%%@NL@%
- %@AS@%10 20 30 40%@AE@%%@NL@%
- %@AS@%12345%@AE@%%@NL@%
- %@AS@%12345%@AE@%%@NL@%
- %@AS@%This sentence is a string.%@AE@%%@NL@%
- %@AS@%This sentence is a string.%@AE@%%@NL@%
- %@AS@%9870.654340%@AE@%%@NL@%
- %@AS@%9870.65%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP8130C@%%@4@%Formatting needs vary from program to program. If you frequently format your%@EH@%
- data in a particular style, however, you may find it helpful to write a
- procedure that automatically follows that format.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP81400@%%@3@%%@AB@%8.1.4 DOS Redirection: Input and Output Files%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP81401@%%@4@%A process called "DOS redirection" allows you to specify both input and%@EH@%
- output files for QuickPascal programs. An input file contains responses to
- all of the questions asked by the program (provided they are input with %@AB@%Read%@AE@%
- or %@AB@%Readln%@AE@% statements). An output file receives all of the information
- written by %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% statements that usually go to the screen.%@NL@%
- %@NL@%
- %@CR:MQP81410@%%@4@%%@AB@%8.1.4.1 Standard Redirection%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP81411@%%@4@%Redirected programs run in a completely normal manner; they just accept%@EH@%
- their input from a file instead of the keyboard, and send their output to a
- file instead of the screen. You can run redirected programs only from the
- DOS command line. To use redirection from within the QuickPascal
- environment, you must first choose the DOS Shell command from the File menu.
- The general redirection syntax is%@NL@%
- %@NL@%
- %@AI@%ProgramName%@AE@% «%@AB@%<%@AE@%%@AI@%InputFile%@AE@%» %@AB@%>%@AE@%%@AI@%OutputFile%@AE@%»%@NL@%
- %@NL@%
- %@CR:MQP81412@%%@4@%You can include the %@AI@%InputFile%@AE@% only, the %@AI@%OutputFile%@AE@% only, or both. Both must%@EH@%
- be text files. If you run with just %@AI@%InputFile%@AE@%%@NL@%
- %@NL@%
- %@AI@%ProgramName%@AE@% %@AB@%<%@AE@%%@AI@%InputFile%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP81413@%%@4@%you still see the program's queries and other output on the screen. However,%@EH@%
- unless you specifically write your program to echo user input, you do not
- see the input data on the screen because it comes directly from the input
- file.%@NL@%
- %@NL@%
- %@CR:MQP81414@%%@4@%If you run %@AI@%ProgramName%@AE@% and include only the %@AI@%OutputFile%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AI@%ProgramName%@AE@% %@AB@%>%@AE@%%@AI@%OutputFile%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP81415@%%@4@%you need to know the order in which the program requires its input; all%@EH@%
- output, including prompts for input, go to %@AI@%OutputFile%@AE@%. DOS creates a new
- output file each time you run the program and specify %@AI@%OutputFile%@AE@%. If a file
- named %@AI@%OutputFile%@AE@% already exists, the old one is erased and a new one is
- created. But, if you add an additional > symbol%@NL@%
- %@NL@%
- %@AI@%ProgramName%@AE@% %@AB@%>>%@AE@%%@AI@%OutputFile%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP81416@%%@4@%DOS appends the new output to the end of the existing file named %@AI@%OutputFile%@AE@%.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP81417@%%@4@%For example, suppose you write a database program called%@AS@%ADDRESS.EXE%@AE@% that%@EH@%
- reads employee names and returns their mailing addresses. Using Quick Pascal
- or some other editor that saves text files, you can create a list of
- employee names and save it as %@AS@%NAME.TXT%@AE@%. Then if you enter%@NL@%
- %@NL@%
- %@AS@%ADDRESS <NAME.TXT%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP81418@%%@4@%you can print the list of employee addresses on the screen. Entering%@EH@%%@NL@%
- %@NL@%
- %@AS@%ADDRESS <NAME.TXT >ADD.TXT%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP81419@%%@4@%creates a new file called %@AS@%ADD.TXT%@AE@% that contains the employee addresses. And,%@EH@%
- if you write another input file called %@AS@%MORENAME.TXT%@AE@%, then the command%@NL@%
- %@NL@%
- %@AS@%ADDRESS <MORENAME.TXT >>ADD.TXT%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP8141A@%%@4@%adds the additional addresses to the end of the existing %@AS@%ADD.TXT%@AE@% file.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP81420@%%@4@%%@AB@%8.1.4.2 The Crt Unit and DOS Redirection%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP81421@%%@4@%The %@AB@%Crt%@AE@% unit overrides DOS redirection. Programs with %@AB@%Crt%@AE@% in their %@AB@%USES%@AE@%%@EH@%
- statements ignore input and output files.%@NL@%
- %@NL@%
- %@CR:MQP81422@%%@4@%If you want to run programs that use the %@AB@%Crt%@AE@% unit with input and output%@EH@%
- files, you must include the following lines in your program prior to the
- first input or output statement:%@NL@%
- %@NL@%
- %@AS@% Assign( Input, '' );%@NL@%
- %@AS@% Reset( Input );%@NL@%
- %@AS@% Assign( Output, '' );%@NL@%
- %@AS@% Rewrite( Output );%@NL@%
- %@NL@%
- %@CR:MQP81423@%%@4@%The %@AB@%Crt%@AE@% unit changes the names of the standard input and output sources; the%@EH@%
- four lines above reassign them to their original settings.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP82000@%%@2@%%@AB@%8.2 The Crt Unit%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP82001@%%@4@%If you have read Chapter 7%@BO: 31ac9@%, "Units," you're familiar with the concept of%@EH@%
- units. The %@AB@%Crt%@AE@% unit is a standard unit that provides data types and
- procedures for keyboard input, cursor control, screen control, and windows.
- This section describes some of the variables and all of the procedures
- provided in the %@AB@%Crt%@AE@% unit. You can obtain more information on each of these
- variables and procedures through the on-line help system.%@NL@%
- %@NL@%
- %@CR:MQP82002@%%@4@%If you plan to use the %@AB@%Crt%@AE@% and %@AB@%MSGraph%@AE@% units together, be sure you read%@EH@%
- Chapter 13%@BO: 5dac7@%, "Using Graphics." QuickPascal imposes some restrictions on
- programs that call both the %@AB@%Crt%@AE@% and the %@AB@%MSGraph%@AE@% units.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP82100@%%@3@%%@AB@%8.2.1 Using the Crt Unit%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP82101@%%@4@%Many of the complete sample programs presented in this manual use the %@AB@%Crt%@AE@%%@EH@%
- unit. To access its functions, procedures, variables, and constants in your
- own programs, add the statement %@AS@%USES Crt;%@AE@% immediately after your program
- declaration.%@NL@%
- %@NL@%
- %@CR:MQP82102@%%@4@%When you start a graphics program you need to tell QuickPascal how you want%@EH@%
- it to display text. You pass a particular constant to the %@AS@%TextMode%@AE@% procedure
- based on your desired text mode. The constants appear in Table 8.1.%@NL@%
- %@NL@%
- %@CR:MQP8T100@%%@4@%%@AB@%Table 8.1 Crt Text-Mode Constants%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Constant%@AE@%%@NL@%
- %@AB@%Identifier Value Display%@AE@%%@NL@%
- %@NL@%
- %@AB@%BW40%@AE@% 0 40 by 25 monochrome text screen%@NL@%
- %@NL@%
- %@AB@%BW80%@AE@% 2 80 by 25 monochrome text screen%@NL@%
- %@NL@%
- %@AB@%Mono%@AE@% 7 80 by 25 monochrome text screen%@NL@%
- %@NL@%
- %@AB@%CO40%@AE@% 1 40 by 25 color text screen%@NL@%
- %@NL@%
- %@AB@%CO80%@AE@% 3 80 by 25 color text screen%@NL@%
- %@NL@%
- %@AB@%Font8x8%@AE@% 256 EGA/VGA 43 lines%@NL@%
- %@NL@%
- %@CR:MQP82103@%%@4@%The %@AB@%Crt%@AE@% unit also establishes the color constants shown in Table 8.2%@BO: 3afb0@%. When%@EH@%
- you print text in different colors or create windows with different colored
- backgrounds, refer to the color by its value.%@NL@%
- %@NL@%
- %@CR:MQP8T200@%%@4@%%@AB@%Table 8.2 Crt Color Constants%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Color Value Color Value%@AE@%%@NL@%
- %@NL@%
- %@AB@%Black%@AE@% 0 %@AB@%LightBlue%@AE@% 9%@NL@%
- %@NL@%
- %@AB@%Blue%@AE@% 1 %@AB@%LightGreen%@AE@% 10%@NL@%
- %@NL@%
- %@AB@%Green%@AE@% 2 %@AB@%LightCyan%@AE@% 11%@NL@%
- %@NL@%
- %@AB@%Cyan%@AE@% 3 %@AB@%LightRed%@AE@% 12%@NL@%
- %@NL@%
- %@AB@%Red%@AE@% 4 %@AB@%LightMagenta%@AE@% 13%@NL@%
- %@NL@%
- %@AB@%Magenta%@AE@% 5 %@AB@%Yellow%@AE@% 14%@NL@%
- %@NL@%
- %@AB@%Brown%@AE@% 6 %@AB@%White%@AE@% 15%@NL@%
- %@NL@%
- %@AB@%LightGray%@AE@% 7 %@AB@%Blink%@AE@% 128%@NL@%
- %@NL@%
- %@AB@%DarkGray%@AE@% 8%@NL@%
- %@NL@%
- %@CR:MQP82104@%%@4@%In addition to the constants, the %@AB@%Crt%@AE@% unit exports the variables listed in%@EH@%
- Table 8.3%@BO: 3b42e@%. They let your programs access status and informational settings
- used by QuickPascal, such as the previous video mode or current text
- attributes.%@NL@%
- %@NL@%
- %@CR:MQP8T300@%%@4@%%@AB@%Table 8.3 Variables Provided by the Crt Unit%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Variable Data Type Purpose%@AE@%%@NL@%
- %@NL@%
- %@AB@%CheckBreak%@AE@% %@AB@%Boolean%@AE@% Indicates the state of CTRL+BREAK%@NL@%
- checking%@NL@%
- %@NL@%
- %@AB@%CheckEof%@AE@% %@AB@%Boolean%@AE@% Enables/disables checking for%@NL@%
- end-of-file character on keyboard input%@NL@%
- %@NL@%
- %@AB@%CheckSnow%@AE@% %@AB@%Boolean%@AE@% Enables/disables "snow checking" for the%@NL@%
- screen%@NL@%
- %@NL@%
- %@AB@%DirectVideo%@AE@% %@AB@%Boolean%@AE@% Enables/disables direct video%@NL@%
- output%@NL@%
- %@NL@%
- %@AB@%LastMode%@AE@% %@AB@%Word%@AE@% Saves previous video mode%@NL@%
- %@NL@%
- %@AB@%TextAttr%@AE@% %@AB@%Byte%@AE@% Contains the current text display%@NL@%
- attribute%@NL@%
- %@NL@%
- %@AB@%WindMin%@AE@% %@AB@%Word%@AE@% Saves the previous coordinates of the%@NL@%
- upper left corner of the active window%@NL@%
- %@NL@%
- %@AB@%WindMax%@AE@% %@AB@%Word%@AE@% Saves the previous coordinates of the%@NL@%
- lower right corner of the active window%@NL@%
- %@NL@%
- %@CR:MQP82105@%%@4@%The variable %@AB@%DirectVideo%@AE@% plays an important role in speeding up screen%@EH@%
- output. Setting %@AB@%DirectVideo%@AE@% to %@AB@%True%@AE@% sends the output of %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@%
- statements directly to your screen's memory. Unfortunately, this technique
- does not work on some computer configurations. Setting %@AB@%DirectVideo%@AE@% to %@AB@%False%@AE@%,
- on the other hand, employs your machine's Basic Input Output System (BIOS).
- BIOS always displays correctly but works at a slower speed; experiment to
- see which setting works better for your computer.%@NL@%
- %@NL@%
- %@CR:MQP82106@%%@4@%The %@AB@%WindMin%@AE@% and %@AB@%WindMax%@AE@% variables store the coordinates of the active%@EH@%
- window. Use the predefined %@AB@%Hi%@AE@% and %@AB@%Lo%@AE@% functions to read the high and low
- bytes that are packed in the %@AB@%WindMin%@AE@% or %@AB@%WindMax%@AE@% variables, as shown below:%@NL@%
- %@NL@%
- %@AS@% UpperLeftX := Lo(WindMin) + 1;%@NL@%
- %@AS@% UpperLeftY := Hi(WindMin) + 1;%@NL@%
- %@AS@% LowerRightX := Lo(WindMax) + 1;%@NL@%
- %@AS@% LowerRightY := Hi(WindMax) + 1;%@NL@%
- %@NL@%
- %@CR:MQP82107@%%@4@%Table 8.4%@BO: 3bfd0@% lists all of the %@AB@%Crt%@AE@% procedures and functions; by browsing%@EH@%
- through it you'll get a feel for the %@AB@%Crt%@AE@% unit. The "Purpose" column
- describes what each procedure does. On-line help gives a more complete
- explanation, and the sample programs show other uses of these procedures.%@NL@%
- %@NL@%
- %@CR:MQP8T400@%%@4@%%@AB@%Table 8.4 Procedures and Functions Provided by the Crt Unit%@AE@%%@EH@%%@NL@%
- %@TH: 75 2968 2 18 17 41 @%
- %@AB@%Procedure Purpose Example%@AE@%
-
- %@AB@%AssignCrt%@AE@% Associates a text-file %@AS@%AssignCrt(DataFile) ;%@AE@%
- variable with the
- screen
-
- %@AB@%ClrEol%@AE@% Clears to the end of %@AS@%ClrEol;%@AE@%
- the line
-
- %@AB@%ClrScr%@AE@% Clears the window and %@AS@%ClrScr;%@AE@%
- places the cursor at
- the upper left corner
-
- %@AB@%Delay%@AE@% Delays the program for %@AS@%Delay(1000){1 sec. };%@AE@%
- a specified number of
- milliseconds
-
- %@AB@%DelLine%@AE@% Removes the line at %@AS@%DelLine;%@AE@%
- the current cursor
- location
-
- %@AB@%GotoXY%@AE@% Moves the cursor to %@AS@%GotoXY( 40,25 );%@AE@%
- the specified window
- coordinates
-
- %@AB@%HighVideo%@AE@% Displays characters in %@AS@%HighVideo;%@AE@%
- high intensity
-
- %@AB@%InsLine%@AE@% Inserts an empty line %@AS@%InsLine;%@AE@%
- at the current cursor
- location
-
- %@AB@%KeyPressed%@AE@% Returns %@AB@%True%@AE@% if there %@AS@%WHILE KeyPressed DO ...%@AE@%
- is a character in the
- keyboard buffer
-
- %@AB@%LowVideo%@AE@% Displays characters in %@AS@%LowVideo;%@AE@%
- low intensity
-
- %@AB@%NormVideo%@AE@% Restores screen %@AS@%NormVideo;%@AE@%
- attri-butes to those
- in effect when the
- program started
-
- %@AB@%NoSound%@AE@% Turns the speaker off %@AS@%NoSound;%@AE@%
-
- %@AB@%ReadKey%@AE@% Reads the next %@AS@%akey := ReadKey;%@AE@%
- character from the
- keyboard buffer
- without showing it on
- the screen
-
- %@AB@%Sound%@AE@% Turns the speaker on %@AS@%Sound( frequency );%@AE@%
-
- %@AB@%TextBackground%@AE@% Selects the background %@AS@%TextBackground( Black );%@AE@%
- color for subsequent
- text display
-
- %@AB@%TextColor%@AE@% Selects the foreground %@AS@%TextColor( Red );%@AE@%
- color for subsequent
- text display
-
- %@AB@%TextMode%@AE@% Selects the display %@AS@%TextMode( BW80 );%@AE@%
- mode
-
- %@AB@%WhereX%@AE@% Returns the X coor- %@AS@%posx := WhereX;%@AE@%
- dinate of the cursor
- location
-
- %@AB@%WhereY%@AE@% Returns the Y coor- %@AS@%posy := WhereY;%@AE@%
- dinate of the cursor
- location
-
- %@AB@%Window%@AE@% Defines a new display %@AS@%Window( 2,2,40,10 );%@AE@%
- window
- %@TE: 75 2968 2 18 17 41 @%
- %@NL@%
- %@CR:MQP82200@%%@3@%%@AB@%8.2.2 Character Input%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP82201@%%@4@%You can read characters from the keyboard in a couple of different ways. In%@EH@%
- the case of the %@AB@%Read%@AE@% and %@AB@%Readln%@AE@% procedures, as each letter is typed in, it
- is put into the input variables and displayed on the screen. The %@AB@%Crt%@AE@%
- function %@AB@%ReadKey%@AE@% also reads input from the keyboard, but can read only one
- character at a time; it does not display the character on the screen.%@NL@%
- %@NL@%
- %@CR:MQP82202@%%@4@%Although you may want to do your primary data collection with %@AB@%Read%@AE@% and%@EH@%
- %@AB@%Readln%@AE@%, the %@AB@%ReadKey%@AE@% function lets you add finishing touches to your
- programs. For example, the following line pauses program execution until the
- user presses ENTER:%@NL@%
- %@NL@%
- %@AS@% REPEAT UNTIL ReadKey = Chr( 13 );%@NL@%
- %@NL@%
- %@CR:MQP82203@%%@4@%%@AB@%ReadKey%@AE@% also reads function keys, cursor-control keys, control keys, and%@EH@%
- alternate keys. These special keys send a sequence of characters. The first
- is a null character (that is, ASCII 0). The second character is an extended
- key code. (See Appendix A%@BO: 829c0@% for a table of extended key codes.)%@NL@%
- %@NL@%
- %@CR:MQP82204@%%@4@%The following excerpt illustrates a typical character processor for a%@EH@%
- keyboard-driven program. It checks for the special character code %@AS@%#0%@AE@% and the
- standard alphanumeric keys. If the first key is special, a second %@AB@%CASE%@AE@%
- statement identifies which key is pressed. Once the character processor
- determines the key pressed, it invokes the applicable procedure.%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% done : Boolean;%@NL@%
- %@AS@% ch, ch2 : Char;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% done := False;%@NL@%
- %@NL@%
- %@AS@% REPEAT%@NL@%
- %@AS@% ch:= ReadKey;%@NL@%
- %@AS@% CASE ch OF%@NL@%
- %@AS@% #0: BEGIN%@NL@%
- %@AS@% ch2:= ReadKey;%@NL@%
- %@AS@% CASE ch2 OF%@NL@%
- %@AS@% 59: { Got F1 key }%@NL@%
- %@AS@% DoF1; { F1 procedure }%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% END;{ CASE ch2 }%@NL@%
- %@AS@% END;{ #0 }%@NL@%
- %@AS@% '0'..'9',%@NL@%
- %@AS@% 'A'..'Z',%@NL@%
- %@AS@% 'a'..'z':%@NL@%
- %@AS@% DoAlphaDigit( ch ); { Procedure for normal keys }%@NL@%
- %@AS@% ELSE%@NL@%
- %@AS@% done :=True;%@NL@%
- %@AS@% END;%@NL@%
- %@AS@% UNTIL done;%@NL@%
- %@NL@%
- %@CR:MQP82205@%%@4@%The CRT1.PAS program in the QuickPascal Advisor demonstrates how to detect%@EH@%
- special keys using %@AB@%ReadKey%@AE@%. You can compile and run the program, which does
- the following:%@NL@%
- %@NL@%
- %@CR:MQP82206@% ■ Moves the %@AS@%'o'%@AE@% character on the screen when you press the UP, DOWN,%@NL@%
- LEFT, and RIGHT arrow keys.%@NL@%
- %@NL@%
- ■ Simulates a bouncing ball effect if you press the F2 function key.%@NL@%
- %@NL@%
- ■ Hides the cursor.%@NL@%
- %@NL@%
- ■ Exits when you press the F1 function key.%@NL@%
- %@NL@%
- %@CR:MQP82207@%%@4@%If you don't like the sound effects, set the constant %@AS@%music%@AE@% to %@AS@%false%@AE@%.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP82208@%%@4@%In the CRT1.PAS program, the %@AS@%IF%@AE@% statement%@EH@%%@NL@%
- %@NL@%
- %@AS@% IF c1 = #0%@NL@%
- %@NL@%
- %@CR:MQP82209@%%@4@%becomes true when you press a special key. In that case, %@AB@%ReadKey%@AE@% returns two%@EH@%
- characters, the first of which is always ASCII %@AS@%#0%@AE@%. The path taken through
- the %@AB@%WHILE%@AE@% loops depends on which key you press.%@NL@%
- %@NL@%
- %@CR:MQP8220A@%%@4@%The %@AS@%cursor_off%@AE@% procedure calls BIOS to turn off the cursor. The %@AB@%Crt%@AE@%%@EH@%
- procedures %@AB@%Sound%@AE@% and %@AB@%Delay%@AE@% are also used in this program. On-line help has
- more information about these two procedures.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP82300@%%@3@%%@AB@%8.2.3 Cursor and Screen Control%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP82301@%%@4@%The %@AB@%Crt%@AE@% unit provides several procedures for screen and cursor control.%@EH@%
- Their names reflect their actions: %@AB@%DelLine%@AE@%, %@AB@%HighVideo%@AE@%, %@AB@%GotoXY%@AE@%, and so on.
- For more information about a specific procedure, use the QuickPascal Advisor
- help.%@NL@%
- %@NL@%
- %@CR:MQP82302@%%@4@%This section refers you to two example programs in the QP Advisor. The%@EH@%
- program CRT2.PAS uses %@AB@%Crt%@AE@% procedures to insert and delete lines, change
- video intensity, and produce sound effects. The program requires very few
- code lines to accomplish these tasks.%@NL@%
- %@NL@%
- %@CR:MQP82303@%%@4@%The CRT3.PAS program uses the %@AB@%GotoXY%@AE@% function to control the cursor. Table%@EH@%
- 8.6%@BO: 3e005@% shows the %@AB@%GotoXY%@AE@% statements used to move the cursor relative to its
- current position, assuming the cursor is not at the edge of a window.%@NL@%
- %@NL@%
- %@CR:MQP8T600@%%@4@%%@AB@%Table 8.6 Statement Effects%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Example Description%@AE@%%@NL@%
- %@NL@%
- %@AS@%GotoXY( WhereX-1, WhereY )%@AE@% Moves one character to the left%@NL@%
- %@NL@%
- %@AS@%GotoXY( WhereX+1, WhereY )%@AE@% Moves one character to the right%@NL@%
- %@NL@%
- %@AS@%GotoXY( WhereX, WhereY-1 )%@AE@% Moves up one line%@NL@%
- %@NL@%
- %@AS@%GotoXY( WhereX, WhereY+1 )%@AE@% Moves down one line%@NL@%
- %@NL@%
- %@AS@%GotoXY( 1, WhereY )%@AE@% Moves to the beginning of the current line%@NL@%
- %@NL@%
- %@AS@%GotoXY(80, WhereY)%@AE@% Moves to the end of the current line%@NL@%
- %@NL@%
- %@CR:MQP82304@%%@4@%The CRT3.PAS program prompts you to type a character and then "bounces" that%@EH@%
- character around the screen. The character changes direction and beeps when
- it reaches the edge of the screen. The character's speed increases each time
- the character changes direction. When it reaches a maximum speed, the
- character slows back down to its original speed.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP82400@%%@3@%%@AB@%8.2.4 Using Windows%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP82401@%%@4@%The %@AB@%Crt%@AE@% unit provides easy control of text windows. The %@AB@%Window%@AE@% procedure%@EH@%
- allows you to define a new active area of the screen.%@NL@%
- %@NL@%
- %@CR:MQP82402@%%@4@%%@AB@%Window%@AE@% accepts row and column coordinates for the upper left and lower right%@EH@%
- corners of the new window. These coordinates must be integers of type %@AB@%Byte%@AE@%.
- The rows range from 1-25 (or 1-43 or 1-50, depending on the text mode) and
- the columns range from 1-80.%@NL@%
- %@NL@%
- %@CR:MQP82403@%%@4@%The %@AB@%Window%@AE@% procedure is analogous to choosing the size of a piece of paper%@EH@%
- to draw on; the coordinates you pass to the procedure tell QuickPascal how
- big to make the piece of paper. For example, the following statement defines
- the entire screen area:%@NL@%
- %@NL@%
- %@AS@% Window( 1, 1, 25, 80 );%@NL@%
- %@NL@%
- %@CR:MQP82404@%%@4@%Many applications use the top and bottom lines of the screen to display a%@EH@%
- menu or help text. To exclude these lines from the active screen area, use%@NL@%
- %@NL@%
- %@AS@% Window( 1, 2, 24, 80 );%@NL@%
- %@NL@%
- %@CR:MQP82405@%%@4@%If you write an application that draws a frame around the screen, you may%@EH@%
- want to use the following statement to reduce the active screen area:%@NL@%
- %@NL@%
- %@AS@% Window( 2, 2, 24, 79 );%@NL@%
- %@NL@%
- %@CR:MQP82406@%%@4@%When you create a new window, the upper left corner of the display area is%@EH@%
- (1, 1). Thus,%@AB@%GotoXY%@AE@%(1, 1) moves the cursor to the upper left corner of the
- active window, regardless of window size and location. %@AB@%GotoXY%@AE@% is analogous
- to setting your pen down at a specific place on the piece of paper. %@AB@%WhereX%@AE@%
- and %@AB@%WhereY%@AE@% return you to your current location.%@NL@%
- %@NL@%
- %@CR:MQP82407@%%@4@%Choose the foreground and background colors for the active window with the%@EH@%
- %@AB@%TextColor%@AE@% and %@AB@%TextBackground%@AE@% procedures. To continue the earlier comparison,
- %@AB@%TextColor%@AE@% lets you select your pen's color and %@AB@%TextBackground%@AE@% selects the
- color of the piece of paper. Note that after changing the background color,
- you must clear the screen to see the new color. Clearing the screen resets
- the cursor to (1, 1).%@NL@%
- %@NL@%
- %@CR:MQP82408@%%@4@%The program CRT4.PAS shows how these procedures work (although you need a%@EH@%
- color monitor to see the colors). It illustrates%@NL@%
- %@NL@%
- %@CR:MQP82409@% ■ Windows that move while keeping their size fixed%@NL@%
- %@NL@%
- ■ Windows that simultaneously move and change sizes%@NL@%
- %@NL@%
- ■ Screen and cursor control of text within a window%@NL@%
- %@NL@%
- %@CR:MQP8240A@%%@4@%CRT4.PAS gives you an idea of what you can do with windows. With a few%@EH@%
- similar lines of code, you can improve your screen's visual impact and add
- clarity and emphasis to your programs.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP90000@%%@1@%%@AB@%Chapter 9 Text Files%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQP90001@%%@4@%Text files store data as lines of ASCII characters. The lines do not have to%@EH@%
- be the same length. Each line terminates with an end-of-line character
- (carriage return). Any text editor or word processor that reads ASCII files
- can edit these files, including the QuickPascal environment.%@NL@%
- %@NL@%
- %@CR:MQP90002@%%@4@%Pascal writes and reads text files sequentially, in much the same way an%@EH@%
- audio cassette player records or plays back a tape. Adding basic file input
- and output (I/O) capabilities to your programs lets you store and retrieve
- data from this "tape" for both long- and short-term use.%@NL@%
- %@NL@%
- %@CR:MQP90003@%%@4@%This chapter covers how to name, open, read, write, and close a file, and%@EH@%
- how to redirect text information between your disk, screen, and printer. It
- also lists the standard procedures used to work with text files.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP91000@%%@2@%%@AB@%9.1 Working with Text Files%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP91001@%%@4@%Working with text files means taking a few straightforward actions:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP91002@% ■ Declaring a file variable and a file name%@NL@%
- %@NL@%
- ■ Creating a new file or opening an existing one%@NL@%
- %@NL@%
- ■ Writing or appending data to a file%@NL@%
- %@NL@%
- ■ Reading data from a file%@NL@%
- %@NL@%
- ■ Closing a file%@NL@%
- %@NL@%
- %@CR:MQP91003@%%@4@%The following sections address these steps in detail.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP91004@%%@4@%As a general introduction, look at the following sample program:%@EH@%%@NL@%
- %@NL@%
- %@AS@% PROGRAM filetest;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% datafile : Text;%@NL@%
- %@AS@% i : Integer;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Assign( datafile, 'RAN_DATA.DAT' );%@NL@%
- %@AS@% Rewrite( datafile );%@NL@%
- %@NL@%
- %@AS@% FOR i := 1 TO 100 DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( datafile, Random(50) );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% Close( datafile );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQP91005@%%@4@%The rest of this chapter frequently refers back to this example.%@EH@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP91100@%%@3@%%@AB@%9.1.1 Declaring a File Variable and File Name%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP91101@%%@4@%Declaring a file variable means telling QuickPascal how you want to refer to%@EH@%
- the file from within the program. It is the variable name by which the
- program knows the file. You declare it in the same way you would declare any
- other text variable:%@NL@%
- %@NL@%
- %@AB@%VAR%@AE@% %@NL@%
- %@AI@%FileVar%@AE@%%@AB@% : Text%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP91102@%%@4@%When you later read or write information to the file, you refer to the file%@EH@%
- by the name you give %@AI@%FileVar%@AE@%. For example,%@NL@%
- %@NL@%
- %@AS@% VAR datafile : Text;%@NL@%
- %@NL@%
- %@CR:MQP91103@%%@4@%creates a file variable with the name %@AS@%datafile%@AE@%.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP91104@%%@4@%QuickPascal also needs to know what name you want to assign to the text file%@EH@%
- that is saved on the disk. The %@AB@%Assign%@AE@% procedure associates the file variable
- with the disk file name:%@NL@%
- %@NL@%
- %@AB@%Assign (%@AE@%%@AI@%FileVar%@AE@%%@AB@%,%@AE@% %@AI@%FileName%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP91105@%%@4@%QuickPascal accepts this assignment as meaning, "Whenever I say to read or%@EH@%
- write to the file variable %@AI@%FileVar%@AE@%, send the information to the disk file
- with the name %@AI@%FileName%@AE@%." You can make the two names similar, but keep in
- mind that %@AI@%FileName%@AE@% must follow the DOS file-naming conventions. For
- instance,%@NL@%
- %@NL@%
- %@AS@% Assign( datafile, 'RAN_DATA.DAT' );%@NL@%
- %@NL@%
- %@CR:MQP91106@%%@4@%equates the file variable %@AS@%datafile%@AE@% with the disk file %@AS@%RAN_DATA.DAT%@AE@%.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP91107@%%@4@%For more versatility, you can use a string variable in place of a literal%@EH@%
- string such as %@AS@%'RAN_DATA.DAT'%@AE@%. Using a string variable allows your program
- to prompt for a file name. For example,%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% datafile : Text;%@NL@%
- %@AS@% filename : String;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Write('Enter name of data file to open: ');%@NL@%
- %@AS@% Readln( filename );%@NL@%
- %@AS@% Assign( datafile, filename );%@NL@%
- %@AS@% Reset( datafile );%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP91200@%%@3@%%@AB@%9.1.2 Opening a Text File%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP91201@%%@4@%With the file variable and the file name both assigned, you can either%@EH@%
- create (and then open) a new file or open an existing one.%@NL@%
- %@NL@%
- %@CR:MQP91210@%%@4@%%@AB@%9.1.2.1 Opening a New Text File%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP91211@%%@4@%The standard procedure %@AB@%Rewrite%@AE@% creates and opens a new text file. It uses%@EH@%
- the general syntax:%@NL@%
- %@NL@%
- %@AB@%Rewrite(%@AE@%%@AI@%FileVar%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP91212@%%@4@%The example program at the beginning of the chapter creates and opens a new%@EH@%
- text file with the line:%@NL@%
- %@NL@%
- %@AS@% Rewrite( datafile );%@NL@%
- %@NL@%
- %@CR:MQP91213@%%@4@%Since the %@AB@%Assign%@AE@% procedure associated the file variable %@AS@%datafile%@AE@% with the%@EH@%
- name %@AS@%RAN_DATA.DAT%@AE@%, this %@AB@%Rewrite%@AE@% statement creates a new file on the disk
- also called %@AS@%RAN_DATA.DAT%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQP91214@%%@4@%Note that if a file already exists with the same name, %@AB@%Rewrite%@AE@% destroys the%@EH@%
- old file. So, it's best to use only file names you know are "safe," or have
- your program ask the user to confirm the name selected.%@NL@%
- %@NL@%
- %@CR:MQP91215@%%@4@%Once you open a new file, you can immediately write new text to it.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP91220@%%@4@%%@AB@%9.1.2.2 Opening an Existing Text File%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP91221@%%@4@%You can perform both read and write operations with an existing text file.%@EH@%
- Keep in mind, however, that trying to open a nonexistent file causes a "File
- not found" run-time error. A short procedure that verifies the existence of
- the file could save you some time.%@NL@%
- %@NL@%
- %@CR:MQP91222@%%@4@%To open files for reading data, use the %@AB@%Reset%@AE@% procedure:%@EH@%%@NL@%
- %@NL@%
- %@AB@%Reset(%@AE@%%@AI@%FileVar%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP91223@%%@4@%For example, to open the file named %@AS@%RAN_DATA.DAT%@AE@% created by this chapter's%@EH@%
- example program, you would use%@NL@%
- %@NL@%
- %@AS@% Reset( datafile );%@NL@%
- %@NL@%
- %@CR:MQP91224@%%@4@%%@AB@%Reset%@AE@% opens the file and moves the "file pointer" (an internal bookmark that%@EH@%
- tells the program where it is in the file) to the first character in the
- file, ready to begin reading.%@NL@%
- %@NL@%
- %@CR:MQP91225@%%@4@%If you want to add text to the end of an existing file, open the file with%@EH@%
- the %@AB@%Append%@AE@% procedure:%@NL@%
- %@NL@%
- %@AB@%Append(%@AE@%%@AI@%FileVar%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP91226@%%@4@%To append data to the %@AS@%RAN_DATA.DAT%@AE@% file, type in:%@EH@%%@NL@%
- %@NL@%
- %@AS@% Append( datafile );%@NL@%
- %@NL@%
- %@CR:MQP91227@%%@4@%This opens the file and sets the file pointer to the end of the file. Text%@EH@%
- that is currently in the file remains unaltered.%@NL@%
- %@NL@%
- %@CR:MQP91228@%%@4@%Once you open a file, you can immediately read text from it or write new%@EH@%
- text to it.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP91300@%%@3@%%@AB@%9.1.3 Writing Text to a File%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP91301@%%@4@%You write to a text file in much the same way as you write to the screen.%@EH@%
- You still use the %@AB@%Write%@AE@% or %@AB@%Writeln%@AE@% procedure and any of its standard
- formatting codes, but you specify the file variable as well.%@NL@%
- %@NL@%
- %@CR:MQP91302@%%@4@%In the example at the beginning of this chapter, the loop%@EH@%%@NL@%
- %@NL@%
- %@AS@% FOR i := 1 TO 100 DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( datafile, Random(50) );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQP91303@%%@4@%sends %@AS@%100%@AE@% random integers to the %@AS@%RAN_DATA.DAT%@AE@% text file specified by the%@EH@%
- %@AS@%datafile%@AE@% file variable.%@NL@%
- %@NL@%
- %@CR:MQP91304@%%@4@%You can just as easily write text or formatted numbers to the file, but%@EH@%
- remember that even formatted numbers are stored in the file as text. Any
- acceptable form of %@AB@%Write%@AE@% or %@AB@%Writeln%@AE@% can send data to a text file.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP91400@%%@3@%%@AB@%9.1.4 Reading Text from a File%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP91401@%%@4@%Use the %@AB@%Read%@AE@% or %@AB@%Readln%@AE@% procedure to read data from an open text file,%@EH@%
- specifying the file variable. For example,%@NL@%
- %@NL@%
- %@AS@% Readln( datafile, line_o_text );%@NL@%
- %@NL@%
- %@CR:MQP91402@%%@4@%reads a line of text from the text file associated with the variable%@EH@%
- %@AS@%datafile%@AE@% into the string %@AS@%line_o_text%@AE@%. %@AB@%Read%@AE@% has the same effect but reads one
- variable at a time rather than an entire line.%@NL@%
- %@NL@%
- %@CR:MQP91403@%%@4@%In the example at the beginning of this chapter, with the %@AB@%FOR%@AE@% loop, the%@EH@%
- program creates a file called %@AS@%RAN_DATA.DAT%@AE@% filled with 100 random numbers
- between 0 and 50 (some numbers appear more than once). You could write a
- nearly identical program to read the data back from the file by altering the
- loop to%@NL@%
- %@NL@%
- %@AS@% FOR i := 1 TO 100 DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Readln( datafile, random_number_string );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQP91404@%%@4@%%@AB@%Readln%@AE@% replaces %@AB@%Writeln%@AE@%, and you must declare %@AS@%random_number_string%@AE@% as a%@EH@%
- variable of type %@AB@%STRING%@AE@%. (You would also need to open the file for reading
- with %@AB@%Reset%@AE@% rather than writing.) To change %@AS@%random_number_string%@AE@% back into
- numerical data, you need to add%@NL@%
- %@NL@%
- %@AS@% Val( random_number_string, ran_num, errpos )%@NL@%
- %@NL@%
- %@CR:MQP91405@%%@4@%after the %@AB@%Readln%@AE@% procedure. (You would also need to declare %@AS@%ran_num%@AE@% and%@EH@%
- %@AS@%errpos%@AE@% as integers.) In cases where you don't know the length of a file in
- advance, you can use a loop that checks for the end of the file with the %@AB@%Eof%@AE@%
- function. For example, if you didn't know the length of the %@AS@%RAN_DATA.DAT%@AE@%
- file, you could rewrite the previous loop as%@NL@%
- %@NL@%
- %@AS@% WHILE NOT Eof( datafile ) DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Readln( datafile, random_number_string );%@NL@%
- %@AS@% Writeln( random_number_string );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQP91406@%%@4@%%@AB@%Eof%@AE@% returns a Boolean result. It returns %@AB@%False%@AE@% as you read through the%@EH@%
- contents of a file and %@AB@%True%@AE@% after you read the file's last entry. The
- end-of-line function, %@AB@%Eoln%@AE@%, works in a similar manner, but returns True when
- you reach the end of a line.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP91500@%%@3@%%@AB@%9.1.5 Closing a Text File%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP91501@%%@4@%You need to close a file when you finish working with it. All files close%@EH@%
- with the same instruction:%@NL@%
- %@NL@%
- %@AB@%Close(%@AE@%%@AI@%FileVar%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP91502@%%@4@%where %@AI@%FileVar%@AE@% specifies an open file.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP91503@%%@4@%Trying to close a file that is not open causes a run-time error. However,%@EH@%
- unless you use a number of similarly named file variables, the compiler
- usually catches potential errors as either undefined variables (often caused
- by typing mistakes) or type mismatches (caused by placing a non-%@AB@%Text%@AE@%
- variable in the place of a file variable).%@NL@%
- %@NL@%
- %@CR:MQP91504@%%@4@%For example, trying to compile the program from the beginning of this%@EH@%
- chapter with the line%@NL@%
- %@NL@%
- %@AS@% Close( datfile ); { 'datafile' misspelled }%@NL@%
- %@NL@%
- %@CR:MQP91505@%%@4@%results in an %@AS@%Unknown identifier%@AE@% compiler error.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP91506@%%@4@%QuickPascal automatically closes any text files still open when a program%@EH@%
- ends.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP92000@%%@2@%%@AB@%9.2 Increasing the Speed for Input and Output%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP92001@%%@4@%The run-time system employs a buffer that temporarily collects text during%@EH@%
- %@AB@%Read%@AE@% and %@AB@%Write%@AE@% operations to text files. By default, the run-time system
- uses a 128-byte buffer.%@NL@%
- %@NL@%
- %@CR:MQP92002@%%@4@%Larger buffers enhance the speed of I/O-intensive programs, but tend not to%@EH@%
- affect programs with moderate or low levels of I/O activity. The larger the
- buffer, the greater the speed. However, unless your programs bog down due to
- I/O operations specifically, the default buffer size usually suffices. Keep
- in mind that while increasing the buffer size can speed up a program, it
- also increases the program's size.%@NL@%
- %@NL@%
- %@CR:MQP92003@%%@4@%The standard procedure %@AB@%SetTextBuf%@AE@% lets you allocate different buffer sizes.%@EH@%
- It uses the general syntax%@NL@%
- %@NL@%
- %@AB@%SetTextBuf(%@AE@%%@AI@%FileVar%@AE@%%@AB@%,%@AE@% %@AI@%Buffer%@AE@%«%@AB@%, %@AE@%%@AI@%Size%@AE@%»%@AB@%)%@AE@%%@NL@%
- %@NL@%
- %@CR:MQP92004@%%@4@%where %@AI@%Buffer%@AE@% refers to a variable to use as the buffer and %@AI@%Size%@AE@% optionally%@EH@%
- indicates the size of the buffer in bytes. You can declare %@AI@%Buffer%@AE@% as any
- type of variable, but you usually use an array of type %@AB@%Char%@AE@%. For example, if
- you wanted to increase the buffer size of the program presented earlier, you
- could rewrite the beginning as%@NL@%
- %@NL@%
- %@AS@% PROGRAM filetest;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% datafile : Text;%@NL@%
- %@AS@% i : Integer;%@NL@%
- %@AS@% buffer : ARRAY[1..2048] OF Char;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Assign( datafile, 'RAN_DATA.DAT' );%@NL@%
- %@AS@% Rewrite( datafile );%@NL@%
- %@AS@% SetTextBuf( datafile, buffer );%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@NL@%
- %@CR:MQP92005@%%@4@%This call to %@AB@%SetTextBuf%@AE@% provides a large array for intermediate storage.%@EH@%
- It's something of an overkill for a group of 100 random integers (based on
- the rest of the example), but would work well for reading or writing large
- text files.%@NL@%
- %@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@AI@%WARNING%@AE@%%@NL@%
- Buffer allocation must occur before or immediately after you open the%@NL@%
- text file. Changing the file buffer size after I/O operations have%@NL@%
- already occurred can lead to data loss.%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP93000@%%@2@%%@AB@%9.3 Redirecting Text Output%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP93001@%%@4@%QuickPascal lets you access a number of standard DOS devices (such as a%@EH@%
- printer and the screen) by specifying the device as an output file name. For
- example, by reassigning the file variable, the same %@AB@%Writeln%@AE@% statement could
- send text data to a disk file, the printer, or the screen.%@NL@%
- %@NL@%
- %@CR:MQP93002@%%@4@%DOS devices use predefined names. The two most common are the printer name,%@EH@%
- PRN (assumed to connect to the LPT1 port), and the screen name, CON (short
- for "console"). Data sent to a device goes to the appropriate computer port.%@NL@%
- %@NL@%
- %@CR:MQP93003@%%@4@%To see how reassignment works, consider a program that, at the end of a%@EH@%
- particularly grueling data-generating session, presents the user with a
- choice of sending the data to the printer, console, or file. Based on the
- selection, the program assigns a file variable to the appropriate device or
- text file.%@NL@%
- %@NL@%
- %@CR:MQP93004@%%@4@%If %@AS@%OutFileVar%@AE@% is the file variable, choosing the printer leads to the%@EH@%
- assignment%@NL@%
- %@NL@%
- %@AS@% Assign( OutFileVar, 'PRN' );%@NL@%
- %@NL@%
- %@CR:MQP93005@%%@4@%to direct the output to the printer. (You could also get the same effect by%@EH@%
- using the %@AB@%Printer%@AE@% unit and substituting %@AS@%LST%@AE@% for the file variable. %@AB@%Printer%@AE@%
- provides the %@AS@%LST%@AE@% text file variable already opened on the LPT1 printer
- port.)%@NL@%
- %@NL@%
- %@CR:MQP93006@%%@4@%Similarly,%@EH@%%@NL@%
- %@NL@%
- %@AS@% Assign( OutFileVar, 'CON' );%@NL@%
- %@NL@%
- %@CR:MQP93007@%%@4@%and%@EH@%%@NL@%
- %@NL@%
- %@AS@% Assign( OutFileVar, NewFile );%@NL@%
- %@NL@%
- %@CR:MQP93008@%%@4@%direct the output to the screen and a disk file, respectively. (%@AS@%NewFile%@AE@%%@EH@%
- must be declared as a string, and must contain the name of the new disk
- file.)%@NL@%
- %@NL@%
- %@CR:MQP93009@%%@4@%The file variable %@AS@%OutFileVar%@AE@% now refers to the correct output location,%@EH@%
- regardless of whether that output is the printer, screen, or a new text
- file. The program opens the device or file with%@NL@%
- %@NL@%
- %@AS@% Rewrite( OutFileVar );%@NL@%
- %@NL@%
- %@CR:MQP9300A@%%@4@%sends the data to the file with%@EH@%%@NL@%
- %@NL@%
- %@AS@% Writeln( OutFileVar, TextOut );%@NL@%
- %@NL@%
- %@CR:MQP9300B@%%@4@%and closes the file when finished with%@EH@%%@NL@%
- %@NL@%
- %@AS@% Close( OutFileVar );%@NL@%
- %@NL@%
- %@CR:MQP9300C@%%@4@%With some planning, the same section of program code can perform three%@EH@%
- different functions: print data, send to the screen, or send to a file. The
- only difference is the file name assigned to the file variable. In the
- example above, a %@AB@%CASE%@AE@% statement, or similar decision-making structure, would
- assign an appropriate file-name variable based on the user's menu selection.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQP94000@%%@2@%%@AB@%9.4 Standard Procedures and Functions for Input and Output%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQP94001@%%@4@%A number of the QuickPascal standard procedures and functions apply to all%@EH@%
- types of data files──text, typed, and untyped. Table 9.1%@BO: 43776@% summarizes those
- procedures and functions available to all file types.%@NL@%
- %@NL@%
- %@CR:MQP9T100@%%@4@%%@AB@%Table 9.1 Standard Procedures and Functions for All File Types%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Routine Purpose%@AE@%%@NL@%
- %@NL@%
- %@AB@%Assign%@AE@% Associates a file buffer with a filename%@NL@%
- %@NL@%
- %@AB@%Close%@AE@% Closes the file buffer%@NL@%
- %@NL@%
- %@AB@%Eof%@AE@% Returns the end-of-file status%@NL@%
- %@NL@%
- %@AB@%Erase%@AE@% Deletes a file%@NL@%
- %@NL@%
- %@AB@%IOResult%@AE@% Returns the error status of the last I/O%@NL@%
- %@NL@%
- %@AB@%Read%@AE@% Reads one or more elements from a file%@NL@%
- %@NL@%
- %@AB@%Rename%@AE@% Renames a file%@NL@%
- %@NL@%
- %@AB@%Reset%@AE@% Opens an existing file%@NL@%
- %@NL@%
- %@AB@%Rewrite%@AE@% Creates and opens a new file, after closing and erasing%@NL@%
- any file with the same name%@NL@%
- %@NL@%
- %@AB@%Write%@AE@% Writes one or more elements to a file%@NL@%
-
- %@CR:MQP94002@%%@4@%Several other standard procedures and functions apply only to text files.%@EH@%
- They appear in Table 9.2%@BO: 43bda@% below.%@NL@%
- %@NL@%
- %@CR:MQP9T200@%%@4@%%@AB@%Table 9.2 Standard Procedures and Functions for Text Files%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Routine Purpose%@AE@%%@NL@%
- %@NL@%
- %@AB@%Append%@AE@% Opens an existing text file for adding more text to the%@NL@%
- end of the file%@NL@%
- %@NL@%
- %@AB@%Eoln%@AE@% Returns the end-of-line status%@NL@%
- %@NL@%
- %@AB@%Flush%@AE@% Clears the text buffer%@NL@%
- %@NL@%
- %@AB@%Readln%@AE@% Reads one or more data items, one line at a time%@NL@%
- %@NL@%
- %@AB@%SeekEof%@AE@% Returns the end-of-file status, ignoring any blanks, tabs,%@NL@%
- and end-of-line markers%@NL@%
- %@NL@%
- %@AB@%SeekEoln%@AE@% Returns the end-of-line status, ignoring any blanks and%@NL@%
- tabs%@NL@%
- %@NL@%
- %@AB@%SetTextBuf%@AE@% Assigns a text file I/O buffer%@NL@%
- %@NL@%
- %@AB@%Writeln%@AE@% Writes one or more data items and appends an end-of-line%@NL@%
- marker%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPA0000@%%@1@%%@AB@%Chapter 10 Binary Files%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQPA0001@%%@4@%A binary file contains program data stored on disk. Each item in a binary%@EH@%
- file is stored in the same binary representation used by a QuickPascal
- program. Binary files provide optimal storage of numbers, Booleans, and
- enumerated types. For example, to store the integer 21,000 in a text file,
- you write a string of at least five characters to disk. To store the number
- in a binary file, you write just two bytes. However, you cannot display a
- binary file directly or view it with a word processor.%@NL@%
- %@NL@%
- %@CR:MQPA0002@%%@4@%You access each binary file as either a typed file or an untyped file:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPA0003@% ■ A "typed file" contains a series of discrete units called%@NL@%
- "components." Each component must have the same type, which can be%@NL@%
- almost any data type supported by QuickPascal but is typically a%@NL@%
- record.%@NL@%
- %@NL@%
- ■ An "untyped file" is treated as a raw, unstructured series of bytes.%@NL@%
- None of the text-oriented read and write functions is available.%@NL@%
- Typically, programs use untyped files for large block operations such%@NL@%
- as copying an entire file to another. Any file can be declared as an%@NL@%
- untyped file.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPA1000@%%@2@%%@AB@%10.1 Typed Files%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPA1001@%%@4@%Like an array, a typed file is a series of components all having the same%@EH@%
- type. Unlike an array, a typed file has no definite size. A file starts at
- length zero and automatically grows as you append data. Furthermore, files
- serve as permanent records that exist after the program terminates.%@NL@%
- %@NL@%
- %@CR:MQPA1002@%%@4@%In essence, typed files are formatted data files. The format is determined%@EH@%
- by the component type, which you should choose carefully to solve a given
- programming task. For example, to implement an airline reservation system,
- you would set up a record type to store all of the needed data for one
- reservation. Then you might create a file made up of these records. Every
- program in the system must use this same record type to correctly read the
- file.%@NL@%
- %@NL@%
- %@CR:MQPA1003@%%@4@%The structure of a typed file supports random access. For example, in a file%@EH@%
- of records, you can directly access record 367 without having to read
- through the first 366.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPA1100@%%@3@%%@AB@%10.1.1 Declaring Typed Files%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPA1101@%%@4@%Not surprisingly, the syntax for defining a typed file is similar to that%@EH@%
- for arrays:%@NL@%
- %@NL@%
- %@AB@%FILE OF %@AE@%%@AI@%ComponentType%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPA1102@%%@4@%In the syntax display above, %@AI@%ComponentType%@AE@% can be any valid data type, with%@EH@%
- one restriction: the component type cannot be a file type or a type that
- contains a file type. Thus, files of arrays are legal, as are arrays of
- files. However, a file of arrays of files is illegal.%@NL@%
- %@NL@%
- %@CR:MQPA1103@%%@4@%The component type is frequently a record. (In fact, other programming%@EH@%
- languages often use the term "record" to refer to a component of a file.)
- For example, you might define a record type to hold a name and phone number
- for one person. To create a permanent list of phone numbers for many people,
- you could create a file made up of these records.%@NL@%
- %@NL@%
- %@CR:MQPA1104@%%@4@%The following code shows examples of valid file types:%@EH@%%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% phonerec = RECORD%@NL@%
- %@AS@% name : STRING[20];%@NL@%
- %@AS@% long_distance : Boolean;%@NL@%
- %@AS@% phone : LongInt;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% phone_list = FILE OF phonerec;%@NL@%
- %@AS@% math_file = FILE OF ARRAY[1..10] OF Real;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% master_list : ARRAY[1..20] OF phone_list;%@NL@%
- %@AS@% celebs : phone_list;%@NL@%
- %@AS@% lucky_numbers : FILE OF Integer;%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPA1200@%%@3@%%@AB@%10.1.2 Accessing Data in a Typed File%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPA1201@%%@4@%After declaring a file variable, you may assign it to a physical disk file%@EH@%
- with the %@AB@%Assign%@AE@% procedure, as described in the last chapter. Then you can
- open the file for writing (with %@AB@%Rewrite%@AE@%) or for both reading and writing
- (with %@AB@%Reset%@AE@%).%@NL@%
- %@NL@%
- %@CR:MQPA1202@%%@4@%For example, the following code declares a file of integers, assigns the%@EH@%
- file variable to the disk file MYFILE.DAT (in the root directory of drive
- C:), and then opens the file for reading and writing:%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% intfile : FILE OF Integer;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Assign( intfile, 'C:\MYFILE.DAT' );%@NL@%
- %@AS@% Reset( intfile );%@NL@%
- %@NL@%
- %@CR:MQPA1203@%%@4@%After you open the file, you can read and write any number of components%@EH@%
- sequentially with the %@AB@%Read%@AE@% and %@AB@%Write%@AE@% procedures. (The next section shows how
- to use random access.) These procedures work with both text files and typed
- files, and take the same syntax in either case. But with typed files, each
- item you read or write must be a variable of the component type.%@NL@%
- %@NL@%
- %@CR:MQPA1204@%%@4@%For example, if %@AS@%int_file%@AE@% is a file of integers, and %@AS@%a%@AE@%, %@AS@%b%@AE@%, and %@AS@%c%@AE@% are integer%@EH@%
- variables, you can read or write the file as follows:%@NL@%
- %@NL@%
- %@AS@% Write( int_file, a,b,c ); { Write a, b, c to the file }%@NL@%
- %@AS@% Read( int_file, n ); { Read next integer in file }%@NL@%
- %@NL@%
- %@CR:MQPA1205@%%@4@%The %@AB@%Read%@AE@% and %@AB@%Write%@AE@% procedures do not do any text formatting when used with%@EH@%
- typed files. In the example above, the procedures read and write the numeric
- value of the integers directly to and from the disk. If %@AS@%int_file%@AE@% were a text
- file, the %@AB@%Read%@AE@% procedure would translate the numbers to character strings
- before writing them.%@NL@%
- %@NL@%
- %@CR:MQPA1206@%%@4@%As you read components of a file, use the %@AB@%Eof%@AE@% function or %@AB@%FileSize%@AE@% function%@EH@%
- (described below) to make sure you don't read past the end of the file. The
- %@AB@%Eof%@AE@% function returns %@AB@%True%@AE@% if the last read operation took you beyond the end
- of the file.%@NL@%
- %@NL@%
- %@CR:MQPA1207@%%@4@%You can use a number of other procedures with typed files, including the%@EH@%
- procedures listed in Table 9.1%@BO: 43776@% in Chapter 9, "Text Files." In addition, you
- can use those listed below.%@NL@%
- %@NL@%
- %@CR:MQPA1208@%%@AB@%Procedure Description %@AE@%%@NL@%
- %@NL@%
- %@AB@%FilePos%@AE@% Takes a file variable as a parameter, and%@NL@%
- returns the current file position (in terms of%@NL@%
- components or blocks)%@NL@%
- %@NL@%
- %@AB@%FileSize%@AE@% Takes a file variable as a parameter, and%@NL@%
- returns the size of the file in bytes; result%@NL@%
- has type %@AB@%LongInt%@AE@%%@NL@%
- %@NL@%
- %@AB@%Seek%@AE@% Takes a file variable and a long integer as%@NL@%
- parameters, and moves the file position to the%@NL@%
- component or block designated by the integer%@NL@%
- %@NL@%
- %@AB@%Truncate%@AE@% Takes a file variable as a parameter, and%@NL@%
- truncates the file at the current file position%@NL@%
- %@NL@%
- %@CR:MQPA1209@%%@4@%The %@AB@%FilePos%@AE@% and %@AB@%Seek%@AE@% procedures let you treat a binary file as a%@EH@%
- random-access file, and the next section provides more detail on how to use
- them. Note that you do not have to treat a typed file as strictly a
- sequential or random-access file. You can use any combination of functions
- supported for the file type.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPA1300@%%@3@%%@AB@%10.1.3 Using Random Access%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPA1301@%%@4@%You can use random-access procedures with any typed file. "Random access" is%@EH@%
- the capability to read or write components to any place in the file and in
- any order.%@NL@%
- %@NL@%
- %@CR:MQPA1302@%%@4@%Random access is like placing a phone call. You can immediately connect to%@EH@%
- any place in the system by giving the right number. Sequential access is
- like reading a novel. You advance from one page to the next in the order
- given.%@NL@%
- %@NL@%
- %@CR:MQPA1303@%%@4@%The two principal random-access procedures are %@AB@%Seek%@AE@% and %@AB@%FilePos%@AE@%. The %@AB@%Seek%@AE@%%@EH@%
- procedure sets the file buffer to the component denoted by the number you
- specify. The first component is denoted by 0, the second by 1, and so on.
- The syntax is%@NL@%
- %@NL@%
- %@AB@%Seek (%@AE@%%@AI@%FileVar%@AE@%%@AB@%, %@AE@%%@AI@%Position%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPA1304@%%@4@%in which %@AI@%FileVar%@AE@% is a file variable, and %@AI@%Position%@AE@% is a constant or variable%@EH@%
- of type %@AB@%LongInt%@AE@%. For example:%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% phone_rec = RECORD%@NL@%
- %@AS@% name,%@NL@%
- %@AS@% notes : STRING;%@NL@%
- %@AS@% number : LongInt;%@NL@%
- %@AS@% END;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% phone_list : FILE OF phone_rec;%@NL@%
- %@AS@% rec10, rec11, rec15, rec25 : phone_rec;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Assign( phone_list, 'FONEHOME.DAT' );%@NL@%
- %@AS@% Reset( phone_list );%@NL@%
- %@AS@% Seek( phone_list, 9 ); { Get 10th & 11th record }%@NL@%
- %@AS@% Read( phone_list, rec10, rec11 );%@NL@%
- %@AS@% Seek( phone_list, 14 ); { Get 15th record }%@NL@%
- %@AS@% Read( phone_list, rec15 );%@NL@%
- %@AS@% Seek( phone_list, 24 ); { Get 25th record }%@NL@%
- %@AS@% Read( phone_list, rec25 );%@NL@%
- %@NL@%
- %@CR:MQPA1305@%%@4@%The example above copies records at predefined locations in the file. More%@EH@%
- often, a practical application determines the record number interactively.
- For example, the following code prompts the user for the record number and
- data, then enters this data into the file:%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% phone_list : FILE OF phone_rec;%@NL@%
- %@AS@% temp_rec : phone_rec;%@NL@%
- %@AS@% n : LongInt;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Assign( phone_list, 'FONEHOME.DAT' );%@NL@%
- %@AS@% Reset( phone_list );%@NL@%
- %@AS@% Write( 'Enter record number: ' );%@NL@%
- %@AS@% Readln( n );%@NL@%
- %@AS@% Write( 'Enter name: ' ); { Prompt for data }%@NL@%
- %@AS@% Readln( temp_rec.name );%@NL@%
- %@AS@% Write( 'Enter number: ' );%@NL@%
- %@AS@% Readln( temp_rec.number );%@NL@%
- %@AS@% Seek( phone_list, n ); { Access record requested }%@NL@%
- %@AS@% Write( phone_list, temp_rec ); { Write data to file }%@NL@%
- %@NL@%
- %@CR:MQPA1306@%%@4@%The %@AB@%FilePos%@AE@% function takes a file variable as a parameter and returns the%@EH@%
- number (again, a %@AB@%LongInt%@AE@%) of the current component.%@NL@%
- %@NL@%
- %@CR:MQPA1307@%%@4@%The %@AB@%Eof%@AE@% function is useful for both sequential-access and random-access%@EH@%
- operations. This function takes a file variable as its parameter and returns
- %@AB@%True%@AE@% if the current component is past the end of the file. Thus, it tells
- you when you have read to the end of the file or have a record number
- corresponding to a nonexistent file component.%@NL@%
- %@NL@%
- %@CR:MQPA1308@%%@4@%So far, you have seen how to read and overwrite existing files. You can%@EH@%
- append the end of files with%@NL@%
- %@NL@%
- %@AB@%Seek(%@AE@%%@AI@%f%@AE@%%@AB@%, FilePos(%@AE@%%@AI@%f%@AE@%%@AB@%))%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPA1309@%%@4@%and rewrite files completely with the %@AB@%Rewrite%@AE@% procedure. But there is no%@EH@%
- easy way to insert new components into the middle of a file. The only way to
- insert a component is to read an entire file into memory, manipulate the
- contents, and write the file to disk again.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPA2000@%%@2@%%@AB@%10.2 Untyped Files%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPA2001@%%@4@%Untyped file variables support direct, low-level I/O operations with any%@EH@%
- file. The %@AB@%BlockRead%@AE@% and %@AB@%BlockWrite%@AE@% functions used with untyped files allow
- for fast data transfer for copy and backup of files. You can also use
- untyped file I/O to create sequential binary files with variable-length
- records.%@NL@%
- %@NL@%
- %@CR:MQPA2002@%%@4@%Untyped files differ from typed files in that%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPA2003@% ■ Untyped files can contain any type of data, even text.%@NL@%
- %@NL@%
- ■ Untyped files can be read or written with any record length using%@NL@%
- %@AB@%BlockRead%@AE@% and %@AB@%BlockWrite%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQPA2004@%%@4@%To declare a type or variable as an untyped file, just use the %@AB@%FILE%@AE@% keyword.%@EH@%
- For example,%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% low_level = FILE;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% my_file : low_level;%@NL@%
- %@NL@%
- %@CR:MQPA2005@%%@4@%The %@AB@%Read%@AE@% and %@AB@%Write%@AE@% procedures, supported for use with text files and typed%@EH@%
- files, are not supported with untyped files. (Otherwise, any procedure
- supported for typed files is also supported for untyped files.) Instead, use
- the %@AB@%BlockRead%@AE@% and %@AB@%BlockWrite%@AE@% procedures to access data. %@AB@%BlockRead%@AE@% and
- %@AB@%BlockWrite%@AE@% read and write records to a file. In this context, "record"
- denotes a data block of a specific size. The default block size is 128 bytes
- if you use the standard file-open sequence:%@NL@%
- %@NL@%
- %@AS@% Assign( file_var, 'FILE' );%@NL@%
- %@AS@% Reset( file_var );%@NL@%
- %@NL@%
- %@CR:MQPA2006@%%@4@%With the default block size, the %@AB@%BlockRead%@AE@% procedure reads in units of 128%@EH@%
- bytes at a time. If the last %@AB@%BlockRead%@AE@% finds fewer than 128 bytes, an error
- occurs. Rarely are the contents of a file exactly equal to 128 * %@AI@%n%@AE@%. To avoid
- errors, you have two alternatives:%@NL@%
- %@NL@%
- %@CR:MQPA2007@% 1. Create a file by writing records of a fixed size with %@AB@%BlockWrite%@AE@%. Then%@NL@%
- the file size will be exactly divisible by the size of the record.%@NL@%
- %@NL@%
- 2. Create a record size of one byte (since every file size is a multiple%@NL@%
- of one) by using the statements below:%@NL@%
- %@NL@%
- %@AS@%Assign( file_var, 'FILE' );%@AE@%%@NL@%
- %@AS@%Reset( file_var, 1 );%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPA2008@%%@4@%%@AB@%Reset%@AE@% and %@AB@%Rewrite%@AE@% have an optional parameter to define the number of bytes%@EH@%
- in a record. Once the record size is set to one byte, the procedures
- %@AB@%BlockRead%@AE@% and%@AB@%BlockWrite%@AE@% transfer multiples of one byte whenever they
- execute. No error occurs at the end of the file.%@NL@%
- %@NL@%
- %@CR:MQPA2009@%%@4@%The syntax for %@AB@%BlockRead%@AE@% is%@EH@%%@NL@%
- %@NL@%
- %@AB@%BlockRead(%@AE@%%@AI@%FileVar%@AE@%%@AB@%, %@AE@%%@AI@%Buffer%@AE@%%@AB@%,%@AE@% %@AI@%Count%@AE@% «%@AB@%,%@AE@%%@AI@%NumRead%@AE@%»%@AB@%)%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPA200A@%%@4@%where %@AB@%BlockRead%@AE@% reads %@AI@%Count%@AE@% records (or the number of records remaining,%@EH@%
- whichever is less) from the file into %@AI@%Buffer%@AE@%. The %@AI@%Buffer%@AE@% parameter can be
- any variable large enough to hold the number of bytes read. The actual
- number of complete records read is returned in the optional parameter
- %@AI@%NumRead%@AE@%. Use %@AI@%NumRead%@AE@% to determine whether %@AB@%BlockRead%@AE@% was successful. If the
- parameter %@AI@%NumRead%@AE@% is omitted and %@AB@%BlockRead%@AE@% reads fewer than %@AI@%Count%@AE@% records,
- an I/O error occurs. The parameter list of %@AB@%BlockWrite%@AE@% is the same as that
- for %@AB@%BlockRead%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQPA200B@%%@4@%The following simple program, DUPLICAT.PAS, shows a typical use of block I/O%@EH@%
- to copy a file:%@NL@%
- %@NL@%
- %@AS@% PROGRAM duplicat;%@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% max_buf=16384;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% file_name, copyfile_name : STRING;%@NL@%
- %@AS@% source, target : FILE;%@NL@%
- %@AS@% buffer : ARRAY [1..max_buf] OF Char; { 16K buffer }%@NL@%
- %@AS@% bytes_read, bytes_written : Word;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Write( 'Enter source file_name -> ' );%@NL@%
- %@AS@% Readln( file_name );%@NL@%
- %@AS@% Write( 'Enter name of target file -> ' );%@NL@%
- %@AS@% Readln( copyfile_name );%@NL@%
- %@AS@% Assign( source, file_name );%@NL@%
- %@AS@% Reset( source, 1 ); { 1 byte-block size }%@NL@%
- %@AS@% Assign( target, copyfile_name );%@NL@%
- %@AS@% Rewrite( target, 1 ); { 1 byte-block size }%@NL@%
- %@AS@% REPEAT%@NL@%
- %@AS@% BlockRead( source, buffer, SizeOf( buffer ), bytes_read );%@NL@%
- %@AS@% BlockWrite( target, buffer, bytes_read, bytes_written )%@NL@%
- %@AS@% UNTIL ( bytes_read = 0 ) OR ( bytes_read <> bytes_written );%@NL@%
- %@AS@% Close( source );%@NL@%
- %@AS@% Close( target );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQPA200C@%%@4@%The program detects the end of the file by looking for either of the%@EH@%
- following two conditions:%@NL@%
- %@NL@%
- %@CR:MQPA200D@% 1. No records were read by the last %@AB@%BlockRead%@AE@% call.%@NL@%
- %@NL@%
- 2. The requested number of records does not match the actual number of%@NL@%
- records read.%@NL@%
- %@NL@%
- %@CR:MQPA200E@%%@4@%The block I/O techniques presented in the program above are used to%@EH@%
- implement an extended version of the DOS COPY command in the sample program
- EXCOPY.PAS, available on-line in QuickPascal. The other sample program
- components are the command-line arguments; the %@AB@%FindFirst%@AE@% and %@AB@%FindNext%@AE@%
- routines; a binary tree to detect duplicate file names; I/O error checking
- used with %@AB@%BlockRead%@AE@% and %@AB@%BlockWrite%@AE@%; and screen output informing the user of
- the file copy progress.%@NL@%
- %@NL@%
- %@CR:MQPA200F@%%@4@%The EXCOPY.PAS procedure %@AS@%copyfile%@AE@% has the task of actually copying the%@EH@%
- files, one at a time. Notice the following aspects of the procedure:%@NL@%
- %@NL@%
- %@CR:MQPA200G@% ■ The %@AB@%Reset%@AE@% and %@AB@%Rewrite%@AE@% statements are accompanied by the %@AB@%{$I-}%@AE@% directive%@NL@%
- to prevent run-time errors from stopping the program. After calling%@NL@%
- %@AB@%Reset%@AE@% and %@AB@%Rewrite%@AE@%, the value of the function %@AB@%IOResult%@AE@% is compared with%@NL@%
- 0. If it is not 0, the procedure terminates. This behavior protects%@NL@%
- against errors resulting from bad file names or attempts to copy files%@NL@%
- that cannot be accessed.%@NL@%
- %@NL@%
- ■ After the %@AB@%BlockWrite%@AE@% procedure is executed, the parameters %@AS@%bytes_read%@AE@%%@NL@%
- and %@AS@%byte_written%@AE@% are compared. If they are not equal, the destination%@NL@%
- disk becomes full while copying the current file.%@NL@%
- %@NL@%
- ■ If the file cannot be copied, then a message is displayed to that%@NL@%
- effect and the target file is erased. Consequently, any partially used%@NL@%
- disk space is freed for other smaller files to be copied. In addition,%@NL@%
- the above procedure also wipes off zero-byte files that would otherwise%@NL@%
- appear in the target directory.%@NL@%
- %@NL@%
- %@CR:MQPA200H@%%@4@%To run EXCOPY.EXE, first compile the program EXCOPY.PAS. The current%@EH@%
- directory should contain the source files you wish to copy. Enter the
- command line arguments as%@NL@%
- %@NL@%
- %@AB@%EXCOPY %@AE@%%@AI@%TargetDirectory%@AE@% «%@AI@%FileList%@AE@%»%@NL@%
- %@NL@%
- %@CR:MQPA200I@%%@4@%The %@AI@%FileList%@AE@% argument can contain one or more file names separated by%@EH@%
- spaces. Each file name can contain the wildcard characters %@AB@%*%@AE@% and %@AB@%?%@AE@%. If you
- omit %@AI@%FileList%@AE@%, EXCOPY uses the default file specification %@AB@%*.*%@AE@% as the file
- list.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPB0000@%%@1@%%@AB@%Chapter 11 Pointers and Dynamic Memory%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQPB0001@%%@4@%A pointer is a variable that contains the numeric address of another data%@EH@%
- object. A pointer provides indirect access to data. For example, if you have
- a pointer to a record and you pass this pointer to a procedure, then the
- procedure can manipulate any field by using the pointer. The procedure does
- not need its own copy of the data.%@NL@%
- %@NL@%
- %@CR:MQPB0002@%%@4@%In Pascal, you use pointers primarily as handles to dynamic-memory objects.%@EH@%
- "Dynamic memory" consists of memory that the program explicitly requests at
- run time. Dynamic memory gives you many advantages. It lets your memory
- usage grow and contract as your needs require──you do not need to specify a
- maximum size or limit.%@NL@%
- %@NL@%
- %@CR:MQPB0003@%%@4@%Because dynamic memory is allocated at run time, your program cannot know in%@EH@%
- advance where the block is located. Pascal, therefore, returns a pointer
- when it allocates dynamic memory. The pointer provides the access to the
- data.%@NL@%
- %@NL@%
- %@CR:MQPB0004@%%@4@%Dynamic memory enables you to create powerful data structures such as linked%@EH@%
- lists and binary trees. These structures, described at the end of this
- chapter, are networks of data in which pointers provide the connecting
- links.%@NL@%
- %@NL@%
- %@CR:MQPB0005@%%@4@%In QuickPascal, you can also use pointers to point to ordinary (non-dynamic)%@EH@%
- variables. This chapter begins by explaining the basics of pointers using
- nondynamic variables.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPB1000@%%@2@%%@AB@%11.1 Declaring and Accessing Pointers%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPB1001@%%@4@%Using pointers consists of three major steps, which you must always do in%@EH@%
- this order:%@NL@%
- %@NL@%
- %@CR:MQPB1002@% 1. Declare the pointer as a specific type.%@NL@%
- %@NL@%
- 2. Initialize the pointer.%@NL@%
- %@NL@%
- 3. Use the pointer by assigning its value, testing its value, or accessing%@NL@%
- the value that it points to.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPB1100@%%@3@%%@AB@%11.1.1 Declaring Pointers%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPB1101@%%@4@%Like other variables, pointers have definite types and can only point to a%@EH@%
- variable of the appropriate type. You can declare a pointer with the
- following syntax:%@NL@%
- %@NL@%
- %@AI@%PointerName%@AE@% %@AB@%: ^%@AE@%%@AI@%DataType%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPB1102@%%@4@%Example pointer declarations are shown below:%@EH@%%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% totals = ARRAY[1..10] OF Integer;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% int_ptr : ^Integer;%@NL@%
- %@AS@% char_ptr : ^Char;%@NL@%
- %@AS@% str_ptr : ^STRING;%@NL@%
- %@AS@% real_ptr : ^Real;%@NL@%
- %@AS@% total_ptr : ^totals;%@NL@%
- %@NL@%
- %@CR:MQPB1103@%%@4@%After you declare a pointer, it does not point to any meaningful value; you%@EH@%
- can produce errors if you try to use it. The first thing you must do after
- declaring a pointer is initialize it.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPB1200@%%@3@%%@AB@%11.1.2 Initializing Pointers%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPB1201@%%@4@%After declaring a pointer, you must initialize it to an address. You can%@EH@%
- always initialize a pointer to the special %@AB@%NIL%@AE@% value. This value indicates
- that the pointer is temporarily turned off──it has no object to point to.
- Your program can test for this condition and take appropriate actions. The
- %@AB@%NIL%@AE@% value is useful in indicating the end of a tree or linked list. Here is
- an example of an assignment to %@AB@%NIL%@AE@%:%@NL@%
- %@NL@%
- %@AS@% my_ptr := NIL;%@NL@%
- %@NL@%
- %@CR:MQPB1202@%%@4@%To assign the address of a variable to a pointer, you can use either the%@EH@%
- address-of (%@AB@%@%@AE@%) operator, or the %@AB@%Addr%@AE@% function. The syntax is%@NL@%
- %@NL@%
- %@AI@%Pointer%@AE@% %@AB@%:= Addr(%@AE@%%@AI@%Variable%@AE@%%@AB@%)%@AE@%%@NL@%
- %@AI@%Pointer%@AE@% %@AB@%:= @%@AE@%%@AI@%Variable%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPB1203@%%@4@%The %@AI@%Variable%@AE@% can be any variable of the type that appears in the declaration%@EH@%
- of %@AI@%Pointer%@AE@%. An example is shown below:%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% an_int : Byte;%@NL@%
- %@AS@% byte_ptr : ^Byte;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% an_int := 5;%@NL@%
- %@NL@%
- %@AS@% { These assignment statements put the same%@NL@%
- %@AS@% address in pointer byte_ptr.%@NL@%
- %@AS@% Both Writeln statements print the number 5.%@NL@%
- %@AS@% }%@NL@%
- %@AS@% byte_ptr := Addr( an_int );%@NL@%
- %@AS@% Writeln( byte_ptr^ );%@NL@%
- %@NL@%
- %@AS@% byte_ptr := @an_int;%@NL@%
- %@AS@% Writeln( byte_ptr^ );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQPB1204@%%@4@%In Section 11.2%@BO: 4af71@%, you learn how to assign a value to a pointer by making a%@EH@%
- dynamic-memory procedure call.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPB1300@%%@3@%%@AB@%11.1.3 Manipulating Pointers%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPB1301@%%@4@%Pointer manipulation in Pascal is extremely limited. In addition to the%@EH@%
- methods described above, the only way to manipulate a pointer is to assign
- it the value of another pointer of the same type. For example, the statement%@NL@%
- %@NL@%
- %@AS@% ptr1 := ptr2;%@NL@%
- %@NL@%
- %@CR:MQPB1302@%%@4@%causes %@AS@%ptr1%@AE@% to point to the same location that %@AS@%ptr2%@AE@% does. This kind of%@EH@%
- assignment is frequently useful in dealing with data structures such as
- linked lists (shown in Section 11.3%@BO: 4cd58@%).%@NL@%
- %@NL@%
- %@CR:MQPB1303@%%@4@%Once you declare and initialize a pointer, you can use it in one of the%@EH@%
- following ways:%@NL@%
- %@NL@%
- %@CR:MQPB1304@% ■ Assign the value of the pointer itself to another pointer.%@NL@%
- %@NL@%
- ■ Test the value of the pointer itself.%@NL@%
- %@NL@%
- ■ Access the value of the variable pointed to.%@NL@%
- %@NL@%
- %@CR:MQPB1305@%%@4@%The number of operations you can do with the value of the pointer is%@EH@%
- limited. As described above, you can assign the value of a pointer to
- another pointer of the same type. You can also test a pointer for equality
- to %@AB@%NIL%@AE@% or to another pointer. For example, the statement%@NL@%
- %@NL@%
- %@AS@% IF (ptr1 = ptr2) THEN ...%@NL@%
- %@NL@%
- %@CR:MQPB1306@%%@4@%executes the statement following %@AB@%THEN%@AE@% if %@AS@%ptr1%@AE@% and %@AS@%ptr2%@AE@% point to the same%@EH@%
- variable. Note that if %@AS@%ptr1%@AE@% and %@AS@%ptr2%@AE@% point to different locations, then the
- expression %@AS@%ptr1 = ptr2%@AE@% evaluates as %@AB@%False%@AE@%, even if the objects that %@AS@%ptr1%@AE@% and
- %@AS@%ptr2%@AE@% point to are equal.%@NL@%
- %@NL@%
- %@CR:MQPB1307@%%@4@%You can also access the value of the variable indicated by the pointer. This%@EH@%
- value can be manipulated in any way you can manipulate the variable itself.
- Use the following syntax to access the variable indicated by the pointer:%@NL@%
- %@NL@%
- %@AI@%PointerName%@AE@%%@AB@%^%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPB1308@%%@4@%This operation is called "dereferencing" the pointer. For example, the%@EH@%
- following code sets the value of %@AS@%x%@AE@% to %@AS@%5%@AE@%, and then assigns this value to %@AS@%y%@AE@%:%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% x, y : Byte;%@NL@%
- %@AS@% byte_ptr : ^Byte;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% byte_ptr := Addr( x );{ byte_ptr now points to x }%@NL@%
- %@AS@% byte_ptr^ := 5; { assign 5 to x }%@NL@%
- %@AS@% y := byte_ptr^; { assign value of x to y }%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQPB1309@%%@4@%In testing pointer values, bear in mind the difference between a pointer and%@EH@%
- the variable pointed to. For example, the statement%@NL@%
- %@NL@%
- %@AS@% IF (ptr1^ = ptr2^) THEN ...%@NL@%
- %@NL@%
- %@CR:MQPB130A@%%@4@%executes the statement following %@AB@%THEN%@AE@% if the objects pointed to by %@AS@%ptr1%@AE@% and%@EH@%
- %@AS@%ptr2%@AE@% are equal. Contrast this example with the previous %@AB@%IF%@AE@%-statement
- example, which evaluated to %@AB@%True%@AE@% only if %@AS@%ptr1%@AE@% and %@AS@%ptr2%@AE@% pointed to the same
- object.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPB2000@%%@2@%%@AB@%11.2 Dynamic-Memory Allocation%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPB2001@%%@4@%In most programs, you need to evaluate the maximum amount of memory the%@EH@%
- program will require. If the amount of data becomes larger than you foresaw,
- you must rewrite the program and then recompile. However, dynamic memory
- lets your memory usage grow along with the needs of the program. The amount
- of physical memory available is the only ultimate limit to dynamic memory.%@NL@%
- %@NL@%
- %@CR:MQPB2002@%%@4@%The use of pointers is essential to all dynamic-memory operations. When%@EH@%
- QuickPascal allocates memory, it returns a pointer. The pointer gives you
- access to the memory block.%@NL@%
- %@NL@%
- %@CR:MQPB2003@%%@4@%There are two basic ways of dynamically allocating memory:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPB2004@% 1. Allocating one object at a time (%@AB@%New%@AE@% and %@AB@%Dispose%@AE@%)%@NL@%
- %@NL@%
- 2. Allocating a block of memory (%@AB@%GetMem%@AE@% and %@AB@%FreeMem%@AE@%)%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPB2100@%%@3@%%@AB@%11.2.1 Allocating a Single Object%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPB2101@%%@4@%By using the %@AB@%New%@AE@% procedure, you allocate space equal to the size of the data%@EH@%
- type associated with the pointer. The syntax is%@NL@%
- %@NL@%
- %@AB@%New(%@AE@%%@AI@%Pointer%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPB2102@%%@4@%Once the %@AB@%New%@AE@% function executes, QuickPascal assigns the address of the%@EH@%
- dynamic-memory block to %@AI@%Pointer%@AE@%. The %@AI@%Pointer%@AE@% must be a variable previously
- declared. The following example shows how to declare a pointer of type %@AS@%Byte%@AE@%;
- allocate memory through the pointer; and then use the dynamic variable to
- hold, manipulate, and display a value.%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% int_ptr : ^Byte;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% int_ptr := NIL;%@NL@%
- %@AS@% { create a Byte-type dynamic variable }%@NL@%
- %@AS@% New( int_ptr );%@NL@%
- %@AS@% int_ptr^ := 100; { assign a value to the dynamic%@NL@%
- %@AS@% variable }%@NL@%
- %@AS@% Inc( int_ptr^, 10 ); { increment it }%@NL@%
- %@AS@% Writeln( int_ptr^ ); { display its value }%@NL@%
- %@AS@% Dispose( int_ptr );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQPB2103@%%@4@%As described in the previous section, %@AS@%int_ptr^%@AE@% is an example of a%@EH@%
- dereferenced pointer. %@AS@%int_ptr%@AE@% itself is a pointer, which can only be
- manipulated in a few restricted ways. However, %@AS@%int_ptr^%@AE@% is equivalent to an
- ordinary variable of type %@AS@%Byte%@AE@%. Use %@AS@%int_ptr^%@AE@% anywhere you would use a %@AS@%Byte%@AE@%
- variable.%@NL@%
- %@NL@%
- %@CR:MQPB2104@%%@4@%To remove a dynamic-memory object created with the %@AB@%New%@AE@% function, use the%@EH@%
- %@AB@%Dispose%@AE@% function. See Section 11.3%@BO: 4cd58@%, "Linked Lists," for more examples of
- %@AB@%New%@AE@% and %@AB@%Dispose%@AE@%.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPB2200@%%@3@%%@AB@%11.2.2 Allocating a Memory Block%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPB2201@%%@4@%The %@AB@%GetMem%@AE@% and %@AB@%FreeMem%@AE@% functions are similar to %@AB@%New%@AE@% and %@AB@%Dispose%@AE@%. However,%@EH@%
- %@AB@%GetMem%@AE@% and %@AB@%FreeMem%@AE@% deal with entire blocks of memory rather than one object
- at a time. Once a block is allocated, you access it as if it were an array
- of indefinite size.%@NL@%
- %@NL@%
- %@CR:MQPB2202@%%@4@%Use the %@AB@%GetMem%@AE@% procedure to select the size of a dynamic-memory block. The%@EH@%
- size should be a multiple of the size of the element type of the array.
- Therefore, if %@AS@%size%@AE@% is the number of elements you want to allocate, and
- %@AS@%base_type%@AE@% is the element type of the array, then pass the following
- parameters to %@AB@%GetMem%@AE@%:%@NL@%
- %@NL@%
- %@AS@% Size * SizeOf(base_type)%@NL@%
- %@NL@%
- %@CR:MQPB2203@%%@4@%A common way to use %@AB@%GetMem%@AE@% is to declare an array type of %@AS@%max_elements%@AE@%%@EH@%
- elements first, where %@AS@%max_elements%@AE@% is the largest possible number of
- elements of the base type. Because the type is an array, you can access
- memory throughout the block with an array index. For example, the following
- code makes the necessary declarations and then calls %@AB@%GetMem%@AE@% to return a
- memory block:%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% max_elements = 65520 DIV SizeOf( base_type );%@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% big_array = ARRAY[1..max_elements] OF base_type;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% array_ptr : ^big_array;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% GetMem( array_ptr, size * SizeOf(base_type) );%@NL@%
- %@NL@%
- %@CR:MQPB2204@%%@4@%The %@AS@%array_ptr%@AE@% now points to an array of type %@AS@%base_type%@AE@%. You can treat%@EH@%
- %@AS@%array_ptr%@AE@% just like any array. The largest index in this array is %@AS@%size%@AE@%. To
- access any element in this array, use the following syntax:%@NL@%
- %@NL@%
- %@AI@%ArrayPointer%@AE@%%@AB@%^[%@AE@%%@AI@%Index%@AE@%%@AB@%]%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPB2205@%%@4@%The example shown below requests a memory block %@AS@%100%@AE@% elements long. In this%@EH@%
- case, %@AS@%array_size%@AE@% is set to %@AS@%100%@AE@%, but at run time, the program could set
- %@AS@%array_size%@AE@% to whatever length it needed.%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% max_elements = 65520 DIV SizeOf( Real );%@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% some_reals : ARRAY[1..max_elements] OF Real;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% rptr : ^some_reals;%@NL@%
- %@AS@% i : Byte;%@NL@%
- %@AS@% array_size : Word;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% array_size := 100;%@NL@%
- %@AS@% GetMem( rptr, array_size * SizeOf(Real) );%@NL@%
- %@AS@% FOR i := 1 TO array_size DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% rptr^[i] := i;%@NL@%
- %@AS@% Writeln( rptr^[i] );%@NL@%
- %@AS@% END;%@NL@%
- %@AS@% FreeMem( rptr, array_size * SizeOf( Real ));%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQPB2206@%%@4@%The %@AB@%FreeMem%@AE@% procedure frees up memory blocks allocated by %@AB@%GetMem%@AE@%. If you no%@EH@%
- longer need to use a particular memory block, it is a good idea to free the
- memory. Otherwise, the program can use up all of the available memory over
- time. The %@AB@%FreeMem%@AE@% procedure takes the same parameters that %@AB@%GetMem%@AE@% does. Make
- sure that the size you specify in %@AB@%FreeMem%@AE@% matches the size allocated with
- %@AB@%GetMem%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQPB2207@%%@4@%Table 11.1%@BO: 4c9f4@% summarizes the procedures provided by QuickPascal for use with%@EH@%
- pointers.%@NL@%
- %@NL@%
- %@CR:MQPBT100@%%@4@%%@AB@%Table 11.1 Pointer Procedures%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Routine Purpose Example%@AE@%%@NL@%
- %@NL@%
- %@AB@%Addr%@AE@% Returns the address of a data %@AS@%aptr := Addr( I );%@AE@%%@NL@%
- object (same as the %@AB@%@%@AE@% operator)%@NL@%
- %@NL@%
- %@AB@%Dispose%@AE@% Disposes of a dynamic variable %@AS@%Dispose( nextptr );%@AE@%%@NL@%
- %@NL@%
- %@AB@%FreeMem%@AE@% Disposes of a dynamic variable %@AS@%FreeMem( aptr, 512 );%@AE@%%@NL@%
- of given size in bytes
- %@NL@%
- %@AB@%GetMem%@AE@% Creates a dynamic variable of a %@AS@%GetMem( aptr, 512 );%@AE@%%@NL@%
- given size in bytes%@NL@%
-
- %@AB@%New%@AE@% Creates a dynamic variable %@AS@%New( aptr );%@AE@%%@NL@%
-
- %@NL@%
- %@CR:MQPB3000@%%@2@%%@AB@%11.3 Linked Lists%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPB3001@%%@4@%Stacks, queues, and trees are data structures that are linked lists. A%@EH@%
- "linked list" is a collection of dynamically allocated records, each having
- a field that is a pointer to the next record. Essentially, the pointers
- serve as the connectors between any two items. By altering the value of the
- pointers, you can sort or reorganize the list in any way──without physically
- moving any of the stored records.%@NL@%
- %@NL@%
- %@CR:MQPB3002@%%@4@%If your program implements a straightforward algorithm, you do not need to%@EH@%
- use these data structures. However, these structures give you a great deal
- of power to solve complex computing tasks. They can grow to any size, and
- they let the program traverse, analyze, and restructure a network of data
- paths. The only limit to the complexity is your own imagination.%@NL@%
- %@NL@%
- %@CR:MQPB3003@%%@4@%The LIST.PAS program adds records to a list, deletes them, and prints the%@EH@%
- contents of the list. The data is stored in a record declared as:%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% rec_ptr = ^stack_rec;%@NL@%
- %@AS@% stack_rec = RECORD%@NL@%
- %@AS@% data : Integer;%@NL@%
- %@AS@% next_rec : rec_ptr;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQPB3004@%%@4@%Note that the second field of type %@AS@%stack_rec%@AE@% points to another record──also%@EH@%
- of type %@AS@%stack_rec%@AE@%. Though this self reference may seem paradoxical, it is
- perfectly legal. It simply means that the second field is the connector to
- another record of the same type. The %@AS@%data%@AE@% field contains the data to be
- stored. For more complex programs, the record could have any number of
- appropriate data fields.%@NL@%
- %@NL@%
- %@CR:MQPB3005@%%@4@%To create a list, first declare a pointer to the start of the list and%@EH@%
- initialize this pointer to %@AB@%NIL%@AE@%:%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% stack_ptr : rec_ptr;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% stack_ptr := NIL;%@NL@%
- %@NL@%
- %@CR:MQPB3006@%%@4@%The program has two major procedures, %@AS@%push%@AE@% and %@AS@%pop%@AE@%. These procedures model%@EH@%
- the behavior of the %@AB@%PUSH%@AE@% and %@AB@%POP%@AE@% instructions of the processor. The linked
- list in this program is a last-in, first-out mechanism, just like the stack
- of the 8086 microprocessor. The %@AS@%push%@AE@% procedure adds items to the front of
- the list, and %@AS@%pop%@AE@% removes these items from the front as well. Therefore, the
- last item stored is also the first item retrieved.%@NL@%
- %@NL@%
- %@CR:MQPB3007@%%@4@%The code in the %@AS@%push%@AE@% procedure inserts a new record at the front of the list%@EH@%
- and then assigns the new value (%@AS@%x%@AE@%) to the %@AS@%data%@AE@% field. These actions simulate
- the action of pushing %@AS@%x%@AE@% onto the top of a stack.%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% temp : rec_ptr;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% New( temp );%@NL@%
- %@AS@% temp^.next_rec := stack_ptr;%@NL@%
- %@AS@% stack_ptr := temp;%@NL@%
- %@AS@% stack_ptr^.data := x;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQPB3008@%%@4@%The above lines of code show the four steps required for the %@AS@%push%@AE@% procedure%@EH@%
- to add a new record to the linked list. These four steps are listed below:%@NL@%
- %@NL@%
- %@CR:MQPB3009@% 1. The first statement, %@AS@%New(temp)%@AE@%, allocates a memory location large%@NL@%
- enough to hold a record with the fields %@AS@%data%@AE@% and %@AS@%next_rec%@AE@%. The pointer%@NL@%
- %@AS@%temp%@AE@% now points to this new record.%@NL@%
- %@NL@%
- 2. To insert this record at the front of the list, the code reassigns two%@NL@%
- pointer values. First, the procedure sets the %@AS@%next_rec%@AE@% field to point%@NL@%
- to the current item at the front of the list. The pointer variable%@NL@%
- %@AS@%stack_ptr%@AE@% points to the front of the list, so the following line of%@NL@%
- code assigns the value %@AS@%stack_ptr%@AE@% to the %@AS@%next_rec%@AE@% field of the new%@NL@%
- record (the new record is referred to as %@AS@%temp^%@AE@%).%@NL@%
- %@NL@%
- %@AS@%temp^.next_rec := stack_ptr;%@AE@%%@NL@%
- %@NL@%
- 3. Next, the pointer %@AS@%stack_ptr%@AE@% must be reassigned to %@AS@%temp%@AE@%. The result is%@NL@%
- that the item previously at the front of the list is now the second%@NL@%
- item (because of step 2), and the new record is at the very front.%@NL@%
- %@NL@%
- 4. Now that the new record has been created and inserted, you can simply%@NL@%
- load the new data into the record. The following statement assigns the%@NL@%
- value of %@AS@%x%@AE@% to the %@AS@%data%@AE@% field of the new record. Note that because of%@NL@%
- step 3, the new record can be referred to as %@AS@%stack_ptr^%@AE@%.%@NL@%
- %@NL@%
- %@AS@%stack_ptr^.data := x;%@AE@%%@NL@%
- %@NL@%
- Note that %@AS@%temp%@AE@% still points to the new record, but now %@AS@%temp%@AE@% can be%@NL@%
- ignored because %@AS@%stack_ptr%@AE@% also points to this record.%@NL@%
- %@NL@%
- %@CR:MQPB300A@%%@4@%Figure 11.1%@BO: 4e1ca@% illustrates the %@AS@%push%@AE@% procedure.%@EH@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPBf100@%%@4@%%@AB@%Figure 11.1 The Push Procedure%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Initial Condition%@AE@%%@NL@%
- ┌───────────┐ ┌───────────┐%@NL@%
- │ data │ │ data │%@NL@%
- ┌───────────┐┌├───────────┤┌├───────────┤ ┌──────────┐%@NL@%
- │ stack_ptr ├┘ │ next_rec ├┘ │ next_rec ├─ ∙∙∙ ─│ NIL │%@NL@%
- └───────────┘ └───────────┘ └───────────┘ └──────────┘%@NL@%
- %@NL@%
- %@AB@%Step 1%@AE@% %@AS@%New (temp) ;%@AE@%%@NL@%
- ┌───────────┐%@NL@%
- │ data │%@NL@%
- ┌───────────┐┌├───────────┤%@NL@%
- │ stack_ptr ├┘ │ next_rec │%@NL@%
- └───────────┘ └───────────┘%@NL@%
- %@NL@%
- %@AB@%Step 2%@AE@% %@AS@%temp^.next_rec := stack_ptr;%@AE@%%@NL@%
- ┌───────────┐ ┌───────────┐%@NL@%
- ┌───────────┐ │ data │ │ data │%@NL@%
- │ stack_ptr ├┬├───────────┤┌├───────────┤ ┌──────────┐%@NL@%
- └───────────┘│ │ next_rec ├┘ │ next_rec ├─ ∙∙∙ ─│ NIL │%@NL@%
- ┌───────────┐│ └───────────┘ └───────────┘ └──────────┘%@NL@%
- │ data ││%@NL@%
- ┌───────────┐┌├───────────┤│%@NL@%
- │ stack_ptr ├┘ │ next_rec ├┘%@NL@%
- └───────────┘ └───────────┘%@NL@%
- %@NL@%
- %@AB@%Step 3%@AE@% %@AS@%stack_ptr := temp;%@AE@%%@NL@%
- ┌───────────┐ ┌───────────┐%@NL@%
- ┌───────────┐ │ data │ │ data │%@NL@%
- ┌─┤ stack_ptr │┌├───────────┤┌├───────────┤ ┌──────────┐%@NL@%
- │ └───────────┘│ │ next_rec ├┘ │ next_rec ├─ ∙∙∙ ─│ NIL │%@NL@%
- │ ┌───────────┐│ └───────────┘ └───────────┘ └──────────┘%@NL@%
- │ │ data ││%@NL@%
- ┌───────────┐├├───────────┤│%@NL@%
- │ stack_ptr ├┘ │ next_rec ├┘%@NL@%
- └───────────┘ └───────────┘%@NL@%
- %@NL@%
- %@AB@%Step 4%@AE@% %@AS@%stack_ptr^.data := x;%@AE@%%@NL@%
- ┌───────────┐ ┌───────────┐%@NL@%
- ┌───────────┐ │ data │ │ data │%@NL@%
- ┌─┤ stack_ptr │┌├───────────┤┌├───────────┤ ┌──────────┐%@NL@%
- │ └───────────┘│ │ next_rec ├┘ │ next_rec ├─ ∙∙∙ ─│ NIL │%@NL@%
- │ ┌───────────┐│ └───────────┘ └───────────┘ └──────────┘%@NL@%
- │ │ │┐┌───────────┐%@NL@%
- └├───────────┤│└┤ x │%@NL@%
- │ next_rec ├┘ └───────────┘%@NL@%
- └───────────┘%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPB300B@%%@4@%The %@AS@%pop%@AE@% procedure works by executing the series of steps in reverse, as%@EH@%
- shown in the code below:%@NL@%
- %@NL@%
- %@AS@% z := stack_ptr^.data;%@NL@%
- %@AS@% temp := stack_ptr;%@NL@%
- %@AS@% stack_ptr := stack_ptr^.next_rec;%@NL@%
- %@AS@% Dispose(temp);%@NL@%
- %@NL@%
- %@CR:MQPB300C@% 1. The procedure pops the value off the top of the stack by saving the%@NL@%
- value in the %@AS@%data%@AE@% field of the first record. The following statement%@NL@%
- saves this value by loading it into %@AS@%z%@AE@%, the output value of the%@NL@%
- procedure.%@NL@%
- %@NL@%
- %@AS@%z := stack_ptr^.data;%@AE@%%@NL@%
- %@NL@%
- 2. Note that the current record at the front of the list must be deleted.%@NL@%
- The pointer %@AS@%temp%@AE@% points to this record, so that the procedure can use%@NL@%
- %@AS@%temp%@AE@% to delete the record later on.%@NL@%
- %@NL@%
- %@AS@%temp := stack_ptr;%@AE@%%@NL@%
- %@NL@%
- 3. Then the pointer to the top of the stack, %@AS@%stack_ptr%@AE@%, is moved so it%@NL@%
- points to %@AS@%stack_ptr^.next_rec%@AE@%. Note that %@AS@%stack_ptr%@AE@% points to the top%@NL@%
- record in the list, which is a record with two fields: the %@AS@%data%@AE@% field%@NL@%
- and the %@AS@%next_rec%@AE@% field. The %@AS@%next_rec%@AE@% field in that top record currently%@NL@%
- points to the next record in the list. The statement%@NL@%
- %@NL@%
- %@AS@%stack_ptr := stack_ptr^.next_rec;%@AE@%%@NL@%
- %@NL@%
- moves %@AS@%stack_ptr%@AE@% to point to the same record that %@AS@%stack_ptr^.next%@AE@%%@AS@%_rec%@AE@%%@NL@%
- is pointing to. By assigning %@AS@%stack_ptr%@AE@% to point to the same record to%@NL@%
- which the top record was pointing, there is now no pointer in the list%@NL@%
- pointing to the record that was on top. The record has been removed%@NL@%
- from the list.%@NL@%
- %@NL@%
- 4. The old record at the front of the list, pointed to by %@AS@%temp%@AE@%, is now%@NL@%
- deleted from memory.%@NL@%
- %@NL@%
- %@AS@%Dispose( temp );%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPB300D@%%@4@%Figure 11.2%@BO: 4f47e@% illustrates the %@AS@%pop%@AE@% procedure.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPBf200@%%@4@%%@AB@%Figure 11.2 The Pop Procedure%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Step 1%@AE@% %@AS@%z := stack_ptr^.data;%@AE@%%@NL@%
- ┌───────────┐%@NL@%
- ┌│ Z │%@NL@%
- │ └───────────┘%@NL@%
- ┌───────────┐│ ┌───────────┐%@NL@%
- │ data ├┘ │ data │%@NL@%
- ┌───────────┐ ┌─├───────────┤┌├───────────┤ ┌──────────┐%@NL@%
- │ stack_ptr ├─┘ │ next_rec ├┘ │ next_rec ├─ ∙∙∙ ─│ NIL │%@NL@%
- └───────────┘ └───────────┘ └───────────┘ └──────────┘%@NL@%
- %@NL@%
- %@AB@%Step 2%@AE@% %@AS@%temp := stack_ptr;%@AE@%%@NL@%
- ┌───────────┐ ┌───────────┐%@NL@%
- │ data │ │ data │%@NL@%
- ┌───────────┐ ┌─├───────────┤┌├───────────┤ ┌──────────┐%@NL@%
- │ stack_ptr ├─┤ │ next_rec ├┘ │ next_rec ├─ ∙∙∙ ─│ NIL │%@NL@%
- └───────────┘ │ └───────────┘ └───────────┘ └──────────┘%@NL@%
- ┌───────────┐ │%@NL@%
- │ temp ├─┘%@NL@%
- └───────────┘%@NL@%
- %@NL@%
- %@AB@%Step 3%@AE@% %@AS@%stack_ptr := stack_ptr^.next_rec;%@AE@%%@NL@%
- ┌────────────────┐%@NL@%
- │ ┌───────────┐│ ┌───────────┐%@NL@%
- │ │ data ││ │ data │%@NL@%
- ┌───────────┐│┌─├───────────┤├├───────────┤ ┌──────────┐%@NL@%
- │ stack_ptr ├┘│ │ next_rec ├┘ │ next_rec ├─ ∙∙∙ ─│ NIL │%@NL@%
- └───────────┘ │ └───────────┘ └───────────┘ └──────────┘%@NL@%
- ┌───────────┐ │%@NL@%
- │ temp ├─┘%@NL@%
- └───────────┘%@NL@%
- %@NL@%
- %@AB@%Step 4%@AE@% %@AS@%Dispose (temp) ;%@AE@%%@NL@%
- ┌────────────────┐%@NL@%
- │ ┌ ─ ─ ─ ─ ─ ┐ │ ┌───────────┐%@NL@%
- │ │ │ data │%@NL@%
- ┌───────────┐│ │ │ └├───────────┤ ┌──────────┐%@NL@%
- │ stack_ptr ├┘ │ next_rec ├─ ∙∙∙ ─│ NIL │%@NL@%
- └───────────┘ └ ─ ─ ─ ─ ─ ┘ └───────────┘ └──────────┘%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPB4000@%%@2@%%@AB@%11.4 Binary Trees%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPB4001@%%@4@%Binary trees are one of the many types of tree structures that can be%@EH@%
- created with pointer variables. Binary trees are more complex than the
- linked lists described in the previous section. Each record (called a
- "node") has not one, but two pointers. Each of these pointers connects the
- node to two other nodes (called "children")──one on its left and one on its
- right.%@NL@%
- %@NL@%
- %@CR:MQPB4002@%%@4@%Figure 11.3%@BO: 50034@% shows a sample binary tree. As you can see, a left child always%@EH@%
- contains a smaller value than the "parent node," and the right child
- contains a value larger than the parent node. Moreover, the %@AI@%entire subtree%@AE@%
- of a given node contains smaller values than the parent, if on the left
- side, or larger values than the parent, if on the right side. This
- organization permits efficient searching for any value in the tree.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPBf300@%%@4@%%@AB@%Figure 11.3 A Binary Tree%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Root Node%@AE@%%@NL@%
- ┌─────────┐%@NL@%
- ┌───────┤ 702 ├─────────┐%@NL@%
- │ └─────────┘ │%@NL@%
- ┌────┴────┐ ┌────┴────┐%@NL@%
- ┌────────┤ 659 │ │ 833 ├────────┐%@NL@%
- │ └─────────┘ └─────────┘ │%@NL@%
- ┌────┴────┐ ┌────┴────┐%@NL@%
- │ 100 ├────────┐ │ 853 │%@NL@%
- └─────────┘ │ └─────────┘%@NL@%
- ┌────┴────┐%@NL@%
- ┌────────┤ 362 ├────────┐%@NL@%
- │ └─────────┘ │%@NL@%
- ┌────┴────┐ ┌────┴────┐%@NL@%
- │ 239 │ ┌────────┤ 640 │%@NL@%
- └─────────┘ │ └─────────┘%@NL@%
- ┌────┴────┐%@NL@%
- ┌────────┤ 622 │%@NL@%
- │ └─────────┘%@NL@%
- ┌────┴────┐%@NL@%
- │ 619 │%@NL@%
- └─────────┘%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPB4003@%%@4@%This sample binary tree contains only simple arithmetic nodes. However, you%@EH@%
- can create binary trees containing any kind of information (as long as each
- node is the same type). You can also organize or sort items in the tree
- using a variety of methods.%@NL@%
- %@NL@%
- %@CR:MQPB4004@%%@4@%To build a binary tree, first declare the following types:%@EH@%%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% node_ptr = ^node;%@NL@%
- %@AS@% node = RECORD%@NL@%
- %@AS@% left,%@NL@%
- %@AS@% right : node_ptr;%@NL@%
- %@AS@% data : Word;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQPB4005@%%@4@%Similar to the record type of a linked list, the %@AS@%Node%@AE@% type contains pointers%@EH@%
- that point to other records of the same type. If the node currently lacks a
- left or right child, the corresponding pointer field should be initialized
- to %@AB@%NIL%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQPB4006@%%@4@%To create a tree, first declare a pointer to the start of the tree and%@EH@%
- initialize this pointer to %@AB@%NIL%@AE@%, as shown below. Although no node currently
- exists in the tree, one will be inserted eventually. The first node will
- become the original ancestor of all other nodes in the tree.%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% root_ptr : node_ptr;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% root_ptr := NIL;%@NL@%
- %@NL@%
- %@CR:MQPB4007@%%@4@%You can start building the tree by inserting values, which can be generated%@EH@%
- in a number of ways──standard input, a data file, or with the %@AB@%Random%@AE@%
- function. Each time you get a value, add it to the tree by using the
- following five steps:%@NL@%
- %@NL@%
- %@CR:MQPB4008@% 1. Examine %@AS@%root_ptr%@AE@%, the pointer to the first node of the tree. The%@NL@%
- expression %@AS@%root_ptr^%@AE@% is equivalent to the first node, if one exists. If%@NL@%
- no node exists, %@AS@%root_ptr%@AE@% is equal to %@AB@%NIL%@AE@%.%@NL@%
- %@NL@%
- 2. If the pointer is %@AB@%NIL%@AE@%, add a new record and assign the pointer to point%@NL@%
- to this record. Load the %@AS@%data%@AE@% field of the new record with the value to%@NL@%
- be added.%@NL@%
- %@NL@%
- 3. If the pointer is not %@AB@%NIL%@AE@%, then a node exists and must be compared to%@NL@%
- the new value. Compare the value to the %@AS@%data%@AE@% field of the node.%@NL@%
- %@NL@%
- 4. If the new value is less than the one at the node, use the %@AS@%left%@AE@% field%@NL@%
- as the new pointer value, and go to step 2.%@NL@%
- %@NL@%
- 5. If the new value is greater than the one at the node, use the %@AS@%right%@AE@%%@NL@%
- field as the new pointer value, and go to step 2.%@NL@%
- %@NL@%
- %@CR:MQPB4009@%%@4@%You can use a recursive procedure to implement these steps. Linked lists and%@EH@%
- trees are often good subjects for recursive solutions. As explained in
- Chapter 3%@BO: 13ad7@%, "Procedures and Functions," a "recursive" procedure presents a
- simplified algorithm by calling itself repeatedly. In the case of binary
- trees, a recursive procedure traces left and right branches repeatedly until
- it finds a matching value at the end of the tree.%@NL@%
- %@NL@%
- %@CR:MQPB400A@%%@4@%In the case of the steps discussed above, you initially call the procedure%@EH@%
- by passing the value you want to insert and %@AS@%root_ptr%@AE@% as arguments. The
- procedure calls itself to trace the left or right subtree, each time passing
- the %@AS@%left%@AE@% or %@AS@%right%@AE@% field as the pointer argument, as follows:%@NL@%
- %@NL@%
- %@AS@% PROCEDURE insert( x : Integer; VAR ptr : node_ptr );%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% IF (ptr = NIL) THEN%@NL@%
- %@AS@% create_node( x, ptr )%@NL@%
- %@AS@% ELSE IF (x <ptr^.data) THEN%@NL@%
- %@AS@% insert( x, ptr^.left )%@NL@%
- %@AS@% ELSE%@NL@%
- %@AS@% insert( x, ptr^.right );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQPB400B@%%@4@%Notice how short the above procedure is. The actual work of inserting the%@EH@%
- node is the last step of the process, and it is carried out by a separate
- procedure written just for that purpose:%@NL@%
- %@NL@%
- %@AS@% PROCEDURE create_node( x : Integer; VAR ptr : node_ptr );%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% New( ptr );%@NL@%
- %@AS@% ptr^.data := x;%@NL@%
- %@AS@% ptr^.left := NIL;%@NL@%
- %@AS@% ptr^.right := NIL;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQPB400C@%%@4@%The initialization of the %@AS@%left%@AE@% and %@AS@%right%@AE@% fields to %@AB@%NIL%@AE@% is critical.%@EH@%
- Otherwise, the %@AS@%insert%@AE@% procedure produces unpredictable results when it
- reaches the end of the tree and attempts a comparison. The procedures above
- effectively use %@AB@%NIL%@AE@% as the end-of-the-tree indicator.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC0000@%%@1@%%@AB@%Chapter 12 Advanced Topics%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQPC0001@%%@4@%This chapter gives you a look inside QuickPascal. You can accomplish most%@EH@%
- any standard programming task by using the techniques presented in prior
- chapters. This chapter helps you deal with special situations, such as
- running out of dynamic memory, analyzing internal data formats, and linking
- to assembly language.%@NL@%
- %@NL@%
- %@CR:MQPC0002@%%@4@%The bitwise operators are of special interest to assembly-language%@EH@%
- programmers, but are useful even if you don't use assembly language. You can
- use the bitwise operators to mask out bits within an integer, manipulate
- individual bits, or test a variable to see which bits are on.%@NL@%
- %@NL@%
- %@CR:MQPC0003@%%@4@%After presenting the bitwise operators, the chapter shows a general picture%@EH@%
- of how QuickPascal organizes memory. Then the chapter illustrates internal
- data formats and explains how to link to assembly language.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC1000@%%@2@%%@AB@%12.1 The Bitwise Operators%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC1001@%%@4@%You can access and manipulate bits by using the standard Boolean operators%@EH@%
- and the shift operators.%@NL@%
- %@NL@%
- %@CR:MQPC1002@%%@4@%The logical operators %@AB@%NOT%@AE@%, %@AB@%AND%@AE@%, %@AB@%OR%@AE@%, and %@AB@%XOR%@AE@% work as bitwise operators when%@EH@%
- you use them with integer types. Bitwise operations take two data items of
- the same size and compare each bit in one operand to the corresponding bit
- in the other. For example, consider the following statement:%@NL@%
- %@NL@%
- %@CR:MQPC1003@%%@4@%%@AS@%Result := $FF00 AND $9055;%@AE@% QuickPascal implements this statement by%@EH@%
- comparing each bit in the constant %@AS@%$FF00%@AE@% to each corresponding bit in the
- constant %@AS@%$9055%@AE@%. The %@AB@%AND%@AE@% operator sets a bit in the result to 1, if and only
- if the corresponding bits in both operands have a value of 1:%@NL@%
- %@NL@%
- %@AS@% $FF00 = 1111 1111 0000 0000%@NL@%
- %@AS@% AND $90FF = 1001 0000 1111 1111%@NL@%
- %@NL@%
- %@AS@% Result $9000 = 1001 0000 0000 0000%@NL@%
- %@NL@%
- %@CR:MQPC1004@%%@4@%The result of the operation is %@AS@%$9000%@AE@%. In the example above, using the %@AB@%AND%@AE@%%@EH@%
- operator with the constant %@AS@%$FF00%@AE@% in effect masks out the low 8 bits of a
- 16-bit integer. You can create other constants to selectively mask out any
- combination of bits. For example, you can use the %@AB@%AND%@AE@% operator to test
- whether a value is a multiple of four by masking out all but the lowest two
- bits and determining whether the result is zero:%@NL@%
- %@NL@%
- %@AS@% IF (x AND $0003 = 0) THEN%@NL@%
- %@AS@% Writeln( 'x is multiple of 4.' );%@NL@%
- %@NL@%
- %@CR:MQPC1005@%%@4@%Conversely, you can use the %@AB@%OR%@AE@% operator to set specific bits to 1. All of%@EH@%
- the bitwise operators work in a similar way. The following list shows how
- each operator works:%@NL@%
- %@NL@%
- %@CR:MQPC1006@%%@AB@%Operator Sets a bit to 1 if: %@AE@%%@NL@%
- %@NL@%
- %@AB@%NOT%@AE@% The corresponding bit in operand is 0. (This%@NL@%
- operator takes just one operand.)%@NL@%
- %@NL@%
- %@AB@%AND%@AE@% Both corresponding bits in the operands have the%@NL@%
- value 1.%@NL@%
- %@NL@%
- %@AB@%OR%@AE@% Either one of the corresponding bits in the%@NL@%
- operand has the value 1.%@NL@%
- %@NL@%
- %@AB@%XOR%@AE@% Either one, but not both, of the corresponding%@NL@%
- bits has the value 1.%@NL@%
- %@NL@%
- %@CR:MQPC1007@%%@4@%The %@AB@%AND%@AE@%, %@AB@%OR%@AE@%, and %@AB@%XOR%@AE@% operators all take two operands each. With each of%@EH@%
- these operators, the two integers you specify must be of the same type. For
- all the bitwise operators, the integer operands may be 8, 16, or 32 bits
- long. (Thus, operations with %@AB@%LongInt%@AE@% types are valid.)%@NL@%
- %@NL@%
- %@CR:MQPC1008@%%@4@%The %@AB@%SHL%@AE@% and %@AB@%SHR%@AE@% operators take an integer operand and move the bits by the%@EH@%
- number of positions specified by the second operand. For example, the binary
- number for 12 is%@NL@%
- %@NL@%
- %@AS@% $0C = 00001100%@NL@%
- %@NL@%
- %@CR:MQPC1009@%%@4@%When you execute the statement %@AS@%12 SHR 2%@AE@%, each of the bits is moved two%@EH@%
- positions to the right, and the result looks like this:%@NL@%
- %@NL@%
- %@AS@% $03 = 00000011%@NL@%
- %@NL@%
- %@CR:MQPC100A@%%@4@%The result of the shift is the number 3. Note that shifting right by two is%@EH@%
- equivalent to dividing by 4. Left and right shifts are equivalent to
- multiplying and dividing by a power of two.%@NL@%
- %@NL@%
- %@CR:MQPC100B@%%@4@%The general syntaxes for %@AB@%SHL%@AE@% and %@AB@%SHR%@AE@% are%@EH@%%@NL@%
- %@NL@%
- %@AI@%IntVar%@AE@% %@AB@%SHL%@AE@% %@AI@%NumPositions%@AE@%%@NL@%
- %@AI@%IntVar%@AE@% %@AB@%SHR%@AE@% %@AI@%NumPositions%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPC100C@%%@4@%The result is always of the same type as %@AI@%IntVar%@AE@%. The %@AI@%NumPositions%@AE@% argument%@EH@%
- determines the number of bit positions to shift. If this number is equal to
- or larger than the number of bits in %@AI@%IntVar%@AE@%, the result is always zero.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC2000@%%@2@%%@AB@%12.2 QuickPascal Memory Map%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC2001@%%@4@%The memory map described in this section shows how a QuickPascal program%@EH@%
- uses memory. This information can help you develop strategies for very large
- programs that may run out of memory quickly.%@NL@%
- %@NL@%
- %@CR:MQPC2002@%%@4@%When you execute a QuickPascal program, it uses all available memory%@EH@%
- (subject to the limits imposed by the %@AB@%{$M}%@AE@% compiler directive as described
- below). Figure 12.1%@BO: 52fbf@% shows the general layout of memory in a QuickPascal
- program, and the rest of the section explains the meaning of items in this
- layout.%@NL@%
- %@NL@%
- %@CR:MQPCf100@%%@4@%%@AB@%Figure 12.1 Quick Pascal Memory Map%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Top of DOS Memory%@AE@%%@NL@%
- ┌─────────────────────────────┐%@NL@%
- │ Free List (grows downwards) │%@NL@%
- ├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤──── %@AI@%Free_Ptr%@AE@%%@NL@%
- │ │%@NL@%
- │ Free Memory │%@NL@%
- │ │%@NL@%
- ├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤──── %@AI@%Heap_Ptr%@AE@%%@NL@%
- │ │%@NL@%
- │ Heap (grows upwards) │%@NL@%
- │ │%@NL@%
- ├─────────────────────────────┤──── %@AI@%HeapOrg%@AE@%%@NL@%
- │ Stack (grows downwards) │%@NL@%
- ├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤──── %@AI@%SSeg:SPtr%@AE@%%@NL@%
- │ Free Stack │%@NL@%
- ├─────────────────────────────┤──── %@AI@%SSeg:0000%@AE@%%@NL@%
- │ Global Variables │%@NL@%
- ┌─├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤%@NL@%
- │ │ Typed Constants │%@NL@%
- │ ├─────────────────────────────┤──── %@AI@%DSeg:0000%@AE@%%@NL@%
- │ │ System Unit Code Segment │%@NL@%
- │ ├─────────────────────────────┤%@NL@%
- │ │ First Unit Code Segment │%@NL@%
- │ ├─────────────────────────────┤%@NL@%
- %@AI@%Contents of%@AE@% │%@NL@%
- %@AI@%an executable%@AE@% ─┤ │ Other Unit Code Segments │%@NL@%
- %@AI@%file image%@AE@% │%@NL@%
- │ ├─────────────────────────────┤%@NL@%
- │ │ Last Unit Code Segment │%@NL@%
- │ ├─────────────────────────────┤%@NL@%
- │ │ │%@NL@%
- │ │ Main Program Code Segment │%@NL@%
- │ │ │%@NL@%
- └─├─────────────────────────────┤%@NL@%
- │ Program Segment Prefix (PSP)│%@NL@%
- └─────────────────────────────┘──── %@AI@%PrefixSeg%@AE@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC2003@%%@4@%The solid lines in Figure 12.1%@BO: 52fbf@% show demarcations between segments. A%@EH@%
- "segment" is an area of memory that can be up to 64K in length. Thus, as you
- can see from Figure 12.1%@BO: 52fbf@%, the code segment of the main program can never be
- more than 64K. However, for very large programs, you can surpass the 64K
- limit by simply adding additional units. The amount of code for each unit
- can be as large as 64K.%@NL@%
- %@NL@%
- %@CR:MQPC2004@%%@4@%All global variables and typed constants are placed in a single segment.%@EH@%
- Thus, the total size of these data items cannot exceed 64K across all units.%@NL@%
- %@NL@%
- %@CR:MQPC2005@%%@4@%The stack is placed in its own segment. You can set the stack size with the%@EH@%
- %@AB@%{$M}%@AE@% compiler directive. Increasing the stack lets the program accommodate
- more procedure calls, but may take away from memory available for the heap.
- (See Appendix B%@BO: 857d9@%, "Compiler Directives.")%@NL@%
- %@NL@%
- %@CR:MQPC2006@%%@4@%The heap consists of the rest of available RAM, unless you use the %@AB@%{$M}%@AE@%%@EH@%
- compiler directive to set maximum heap size. The heap contains all dynamic
- variables allocated through calls to %@AB@%New%@AE@% or %@AB@%GetMem%@AE@%. If you know in advance
- that your program %@AI@%must%@AE@% have a certain amount of heap space to run properly,
- you can use the %@AB@%{$M}%@AE@% compiler directive to specify a minimum heap size. DOS
- will not load the program unless it can allocate enough memory for the
- requested minimum heap size.%@NL@%
- %@NL@%
- %@CR:MQPC2007@%%@4@%Certain variables appear in the QuickPascal memory map. These are public%@EH@%
- variables declared in the %@AB@%System%@AE@% unit, and your program can access them at
- any time (no special declaration is needed to use the %@AB@%System%@AE@% unit).%@NL@%
- %@NL@%
- %@CR:MQPC2008@%%@4@%The following list describes the public variables appearing in the memory%@EH@%
- map:%@NL@%
- %@NL@%
- %@CR:MQPC2009@%%@AB@%Variable Description %@AE@%%@NL@%
- %@NL@%
- %@AB@%FreePtr%@AE@% Pointer to beginning of "free list," (as%@NL@%
- described in Section 12.3%@BO: 548d8@%). The free list is a%@NL@%
- series of records that describes the size and%@NL@%
- location of free mem-ory blocks inside the heap.%@NL@%
- As the free list grows, %@AB@%FreePtr%@AE@% decreases%@NL@%
- because the free list grows downward.%@NL@%
- %@NL@%
- %@AB@%HeapPtr%@AE@% Pointer to top of heap. As the amount of space%@NL@%
- needed by dynamic variables increases, %@AB@%HeapPtr%@AE@%%@NL@%
- increases. It decreases only when memory is%@NL@%
- freed from the top of the heap.%@NL@%
- %@NL@%
- %@AB@%HeapOrg%@AE@% Pointer to beginning of heap. This variable has%@NL@%
- the generic type %@AB@%POINTER%@AE@%, as do the other%@NL@%
- pointers declared in the %@AB@%System%@AE@% unit. You cannot%@NL@%
- dereference pointers of this type, but you can%@NL@%
- assign the value of such a pointer to any other%@NL@%
- pointer, regardless of type.%@NL@%
- %@NL@%
- %@AB@%PrefixSeg%@AE@% Word variable containing segment address of%@NL@%
- Program Segment Prefix (PSP). When DOS loads%@NL@%
- your program, it constructs the PSP to store%@NL@%
- command-line arguments, interrupt vectors, and%@NL@%
- other information. See the %@AI@%MS-DOS Programmer's%@AE@%%@NL@%
- %@AI@%Reference%@AE@% or %@AI@%MS-DOS Encyclopedia%@AE@% for more%@NL@%
- information.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC3000@%%@2@%%@AB@%12.3 Managing the Heap%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC3001@%%@4@%The simplest way to create dynamic variables is to make calls to %@AB@%New%@AE@% and%@EH@%
- %@AB@%GetMem%@AE@%. In small programs, you can generally call these procedures without
- worrying about how the heap is managed. However, if your programs make heavy
- use of dynamic memory, you can sometimes avoid running out of memory by
- knowing how the heap works.%@NL@%
- %@NL@%
- %@CR:MQPC3002@%%@4@%The basic model of the heap is simple. Initially, the %@AB@%New%@AE@% and %@AB@%GetMem%@AE@%%@EH@%
- procedures simply increment %@AB@%HeapPtr%@AE@% by the size of the memory block you
- request and return a pointer to the beginning of the block.%@NL@%
- %@NL@%
- %@CR:MQPC3003@%%@4@%The structure of the heap becomes more complicated when you start freeing%@EH@%
- blocks of memory. If you free memory at the current top of the heap, %@AB@%HeapPtr%@AE@%
- is decreased by the amount of memory freed. More often, however, the block
- to be freed is somewhere in the middle of the heap. In this case, the
- free-memory procedure (%@AB@%Dispose%@AE@% or %@AB@%FreeMem%@AE@%) adds a record to the free list to
- record the existence of the freed block.%@NL@%
- %@NL@%
- %@CR:MQPC3004@%%@4@%The free block is then like a hole in the middle of the heap. The next time%@EH@%
- you request memory, the allocation procedure attempts to allocate memory
- from a free block if it can. Furthermore, if a block is freed adjacent to an
- existing free block, the two blocks form one larger free block, and the free
- list is updated to reflect this fact.%@NL@%
- %@NL@%
- %@CR:MQPC3005@%%@4@%The maximum number of free blocks that Pascal programs can maintain is%@EH@%
- 8,192. Programs rarely reach this limit. However, you can use a variety of
- techniques to manage the heap, each of which is explained in a section
- below:%@NL@%
- %@NL@%
- %@CR:MQPC3006@% ■ Use the %@AB@%Mark%@AE@% and %@AB@%Release%@AE@% functions to free memory efficiently%@NL@%
- %@NL@%
- ■ Determine the amount of heap space left and the number of records in%@NL@%
- the free list%@NL@%
- %@NL@%
- ■ Set the %@AB@%FreeMin%@AE@% variable to prevent a deadlock between the heap and the%@NL@%
- free list%@NL@%
- %@NL@%
- ■ Write a customized %@AB@%HeapError%@AE@% function to control how the program%@NL@%
- responds when you run out of heap space (the default action is to abort%@NL@%
- execution)%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC3100@%%@3@%%@AB@%12.3.1 Using Mark and Release to Free Memory%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC3101@%%@4@%The %@AB@%Mark%@AE@% and %@AB@%Release%@AE@% procedures provide a simpler and more efficient way to%@EH@%
- free memory than %@AB@%Dispose%@AE@% or %@AB@%FreeMem%@AE@%. However, the use of %@AB@%Mark%@AE@% and %@AB@%Release%@AE@%
- requires that you release memory in the reverse order to that in which you
- allocated it. Not all programs can adhere to this requirement.%@NL@%
- %@NL@%
- %@CR:MQPC3102@%%@4@%The %@AB@%Mark%@AE@% procedure sets a pointer to point to the current top of the heap.%@EH@%
- The pointer can have any base type. Then if you allocate more dynamic
- memory, the new memory is higher in memory than the marked location (because
- the heap grows upward).%@NL@%
- %@NL@%
- %@CR:MQPC3103@%%@4@%The %@AB@%Release%@AE@% procedure takes a single pointer as an argument, just as %@AB@%Mark%@AE@%%@EH@%
- does, and releases all dynamic memory above the pointer. In other words, it
- releases all memory allocated after the %@AB@%Mark%@AE@% procedure was called. The
- %@AB@%Release%@AE@% procedure basically works by setting %@AB@%HeapPtr%@AE@% to the value of the
- pointer argument.%@NL@%
- %@NL@%
- %@CR:MQPC3104@%%@4@%For example, the following code allocates five dynamic variables:%@EH@%%@NL@%
- %@NL@%
- %@AS@% New( PtrA );%@NL@%
- %@AS@% New( PtrB );%@NL@%
- %@AS@% Mark( Ptrs );%@NL@%
- %@AS@% New( PtrC );%@NL@%
- %@AS@% New( PtrD );%@NL@%
- %@NL@%
- %@CR:MQPC3105@%%@4@%The next line of code releases the pointers declared after the %@AS@%Mark( Ptrs )%@AE@%%@EH@%
- statement. Specifically, it frees the memory pointed to by %@AS@%PtrC%@AE@% and %@AS@%PtrD%@AE@%:%@NL@%
- %@NL@%
- %@AS@% Release( Ptrs );%@NL@%
- %@NL@%
- %@CR:MQPC3106@%%@4@%%@AB@%Mark%@AE@% and %@AB@%Release%@AE@% impose significant limitations on program logic because%@EH@%
- they do not let you randomly free any block of memory; you can only free
- contiguous blocks at the top of the heap. However, if you use these
- procedures, you have none of the problems that sometimes occur with a free
- list.%@NL@%
- %@NL@%
- %@CR:MQPC3107@%%@4@%Note that the %@AB@%Mark%@AE@% and %@AB@%Release%@AE@% procedures are not compatible with %@AB@%Dispose%@AE@%%@EH@%
- and %@AB@%FreeMem%@AE@%. Once you use one of the latter two procedures, you should not
- call %@AB@%Release%@AE@%.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC3200@%%@3@%%@AB@%12.3.2 Determining Free Memory and Size of the Free List%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC3201@%%@4@%Two functions let you determine the amount of free memory available:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC3202@% ■ The %@AB@%MemAvail%@AE@% function returns the total number of free bytes in the%@NL@%
- heap.%@NL@%
- %@NL@%
- ■ The %@AB@%MaxAvail%@AE@% function returns the size of the largest single free block%@NL@%
- in the heap──in other words, the largest amount of memory that you can%@NL@%
- successfully request.%@NL@%
- %@NL@%
- %@CR:MQPC3203@%%@4@%Generally, the %@AB@%MaxAvail%@AE@% function is the more useful of the two functions,%@EH@%
- since it lets you know whether any given call to %@AB@%New%@AE@% or %@AB@%GetMem%@AE@% will be
- successful. Both the %@AB@%MemAvail%@AE@% and %@AB@%MaxAvail%@AE@% functions return a %@AB@%LongInt%@AE@%
- result, and neither takes any parameters.%@NL@%
- %@NL@%
- %@CR:MQPC3204@%%@4@%Determining the size of the free list also helps you discover if you are%@EH@%
- going to run out of memory. The free list is declared as follows:%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% FreeRec = RECORD%@NL@%
- %@AS@% OrgPtr, EndPtr : Pointer;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% FreeList = ARRAY [0..8190] OF FreeRec;%@NL@%
- %@AS@% FreeListP = ^FreeList;%@NL@%
- %@NL@%
- %@CR:MQPC3205@%%@4@%Each record in the free list defines a single free memory block; the %@AS@%OrgPtr%@AE@%%@EH@%
- and %@AS@%EndPtr%@AE@% fields define the beginning and ending address, respectively, of
- the block. %@AS@%EndPtr%@AE@% points to the first byte after the end of the block. You
- can calculate the number of free blocks recorded in the free list by using
- the following statement:%@NL@%
- %@NL@%
- %@AS@% free_blocks := (8192 - Ofs( FreePtr^ ) DIV 8) MOD 8192;%@NL@%
- %@NL@%
- %@CR:MQPC3206@%%@4@%When the offset portion of the address in %@AB@%FreePtr%@AE@% is 0, the free list is%@EH@%
- empty. As a free block is added to the list, %@AB@%FreePtr%@AE@% decreases by eight
- bytes, and the free list also grows downward by eight.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC3300@%%@3@%%@AB@%12.3.3 Preventing Deadlock with the Free List%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC3301@%%@4@%If the top of the heap is very close to the bottom of the free list, then%@EH@%
- deadlock can occur when you try to free blocks of memory. If the blocks to
- be freed are at the top of the heap, there is no problem. Otherwise, the
- free list is blocked from expanding.%@NL@%
- %@NL@%
- %@CR:MQPC3302@%%@4@%This problem always causes a run-time error. You can neither allocate new%@EH@%
- dynamic memory nor free any existing memory. The only way to prevent this
- situation is to set a minimum amount of space between the locations pointed
- to by %@AB@%HeapPtr%@AE@% and %@AB@%FreePtr%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQPC3303@%%@4@%The %@AB@%FreeMin%@AE@% system variable sets the minimum free memory space (between the%@EH@%
- top of the heap and bottom of the free list). This variable has type %@AB@%Word%@AE@%
- and represents a distance in bytes. The %@AB@%New%@AE@% and %@AB@%FreeMem%@AE@% procedures will not
- allocate a block of memory if doing so would make the space between the heap
- and the free list fall below %@AB@%FreeMin%@AE@%. The %@AB@%MemAvail%@AE@% and %@AB@%MaxAvail%@AE@% functions
- also take %@AB@%FreeMin%@AE@% into account by subtracting it from the free memory area.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC3400@%%@3@%%@AB@%12.3.4 Writing a Heap-Error Function%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC3401@%%@4@%By default, the %@AB@%New%@AE@% and %@AB@%GetMem%@AE@% procedures simply abort program execution%@EH@%
- when they cannot return a memory block of the requested size. However, you
- can create a customized function to respond to heap errors.%@NL@%
- %@NL@%
- %@CR:MQPC3402@%%@4@%Your heap-error function is called by %@AB@%New%@AE@% and %@AB@%GetMem%@AE@% as needed, and it can%@EH@%
- return one of three values:%@NL@%
- %@NL@%
- %@CR:MQPC3403@%%@AB@%Value Meaning%@AE@%%@NL@%
- %@NL@%
- 0 Failure; abort program%@NL@%
- %@NL@%
- 1 Failure; return the %@AB@%NIL%@AE@% pointer value to the%@NL@%
- caller of %@AB@%New%@AE@% or %@AB@%GetMem%@AE@%, but do not abort program%@NL@%
- %@NL@%
- 2 Memory successfully freed; authorize %@AB@%New%@AE@% or %@AB@%%@AE@%%@NL@%
- %@AB@%GetMem%@AE@% to retry%@NL@%
- %@NL@%
- %@CR:MQPC3404@%%@4@%Your function should return the value 2 only if it was able to find a%@EH@%
- disposable dynamic variable in your program and free the necessary memory.
- If the function returns 2 without freeing memory first, then it will be
- called again.%@NL@%
- %@NL@%
- %@CR:MQPC3405@%%@4@%To create a heap-error function, first declare a function similar to the one%@EH@%
- below:%@NL@%
- %@NL@%
- %@AS@% {$F+}%@NL@%
- %@AS@% FUNCTION heap_err( size : Word ) : Integer;%@NL@%
- %@AS@% {$F-}%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% { Cause FreeMem to return NIL but continue execution }%@NL@%
- %@AS@% heap_err := 1;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQPC3406@%%@4@%You can give the function any name you want and supply any statements in the%@EH@%
- body of the function. However, the rest of the declaration should be the
- same. In particular, the %@AB@%{$F+}%@AE@% compiler directive is necessary to make sure
- the function is compiled for far calls. The single parameter of type %@AB@%Word%@AE@%
- gives the size of the memory block that %@AB@%New%@AE@% or %@AB@%GetMem%@AE@% failed to allocate.%@NL@%
- %@NL@%
- %@CR:MQPC3407@%%@4@%After declaring your heap-error function, set the %@AB@%HeapError%@AE@% system variable%@EH@%
- to point to your function:%@NL@%
- %@NL@%
- %@AS@% HeapError := @heap_err;%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC4000@%%@2@%%@AB@%12.4 Internal Data Formats%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC4001@%%@4@%Knowledge of internal data formats is useful if you want to write%@EH@%
- assembly-language procedures that access data from QuickPascal programs.
- Furthermore, you can use this knowledge to help determine what data types
- most efficiently store information for a given program.%@NL@%
- %@NL@%
- %@CR:MQPC4002@%%@4@%Section 12.4.1%@BO: 574ac@% describes the data formats for all types except%@EH@%
- floating-point numbers. The floating-point data types are described
- separately in Section 12.4.2%@BO: 58bd3@%, because of their complexity.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC4100@%%@3@%%@AB@%12.4.1 Non-Floating-Point Data Types%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC4101@%%@4@%The list that follows describes the internal formats of most data types,%@EH@%
- including structured variables such as arrays and records. Note that any
- given type is stored the same way, whether it is a simple variable or part
- of a record.%@NL@%
- %@NL@%
- %@CR:MQPC4102@%%@4@%Where an integer value is designated as signed, QuickPascal uses the two's%@EH@%
- complement format for storing negative numbers. This format represents the
- negative of a number by logically negating each bit (as is done by the %@AB@%NOT%@AE@%
- operator) and then adding 1. For example, since 00000011 represents 3, then
- 11111100 is the logical negation, and 11111101 is the two's complement of 3.%@NL@%
- %@NL@%
- %@CR:MQPC4103@%%@4@%Therefore, if you declare a %@AB@%Byte%@AE@% constant as -3, QuickPascal stores this%@EH@%
- value as 11111101. Generally speaking, you never have to carry out
- two's-complement conversion yourself. It is simply an internal format
- understood by both Quick-Pascal and the 8086 family of processors.%@NL@%
- %@NL@%
- %@CR:MQPC4104@%%@4@%As a consequence, all nonnegative numbers have 0 in the most significant%@EH@%
- bit; all negative numbers have 1 in the most significant bit. The unsigned
- formats do not consider any number to be negative.%@NL@%
- %@CR:MQPC4105@%%@NL@%
- %@TH: 74 4518 2 28 48 @%
- %@AB@%Data Type Internal Format%@AE@%
-
- %@AB@%Char%@AE@% An unsigned byte. (Values range from 0 to 255.)
-
- %@AB@%Byte%@AE@% A signed byte. (Values range from -128 to 127.)
-
- %@AB@%Integer%@AE@% A signed word. (Values range from -32768 to
- 32767.)
-
- %@AB@%Word%@AE@% An unsigned word. (Values range from 0 to
- 65535.)
-
- %@AB@%LongInt%@AE@% A signed double word. (Values range from
- -2147483648 to 2147483647.)
-
- %@AB@%Comp%@AE@% A signed eight-byte integer. If the
- most-significant bit is 1 and the other bits are
- all 0, this type has the special value NAN (Not
- a Number). Note that with the %@AB@%{N+}%@AE@% directive,
- QuickPascal uses the 8087 coprocessor, if
- installed, to do calculations with %@AB@%Comp%@AE@% types.
-
- %@AB@%Boolean%@AE@% A byte assuming the value 0 (%@AB@%False%@AE@%) or 1 (%@AB@%True%@AE@%).
-
- Enumerated types Stored as an unsigned byte if the type can
- assume 256 values or fewer. Otherwise, the
- enumerated type is stored as an unsigned word.
- The first item in an enumerated-type definition
- corresponds to the value 0, and the rest are
- numbered sequentially in the order given.
-
- %@AB@%STRING%@AE@% types A sequence of bytes in which the first byte
- stores the current length of the string (which
- may be less than its maximum length), and the
- rest of the bytes store the string data.
- QuickPascal allocates enough space for a
- string's maximum length plus one additional byte
- (for the length indicator). The generic %@AB@%STRING%@AE@%
- type is equivalent to %@AS@%STRING[255]%@AE@%, which has the
- maximum limit.
-
- %@AB@%CSTRING%@AE@% Similar to %@AB@%STRING%@AE@% types, except that the first
- byte is not a length indicator, and the string
- data includes a terminating null byte. Maximum
- limit is 255 + null bytes. The generic %@AB@%CSTRING%@AE@%
- type defaults to this length.
-
- %@AB@%SET%@AE@% types Stored as a bit array, in which each bit
- corresponds to a specific element. If a bit is
- on, then the corresponding element is present.
- QuickPascal allocates one byte for each element,
- up to a maximum of 32 bytes (256 elements).
- Elements within a set are stored in order of
- their ordinal value, in which the first element
- is stored in the least-significant bit.
-
- %@AB@%ARRAY%@AE@% types Elements of the array are stored contiguously in
- memory, starting from the lowest-indexed
- component and going in sequence to the highest.
- In multidimensional arrays, the rightmost index
- changes fastest. Thus, in the array declared as
- %@AS@%Grid[Rows,Cols]%@AE@%, all elements for an entire row
- are stored next to each other in memory.
-
- %@AB@%RECORD%@AE@% types A sequence of variables stored contiguously in
- memory (the fields appear in memory in the same
- order they do in source code). With variant
- records, each variant case starts at the same
- address.
-
- Pointer types A double word that contains the offset address
- in the low word and the segment address in the
- high word. The special value %@AB@%NIL%@AE@% is a generic
- pointer containing the value zero.
- %@TE: 74 4518 2 28 48 @%
- %@NL@%
- %@CR:MQPC4200@%%@3@%%@AB@%12.4.2 Floating-Point Data Types%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC4201@%%@4@%Figure 12.2 displays the formats used to represent floating-point numbers of%@EH@%
- different levels of precision. QuickPascal uses these data formats whether
- or not a math coprocessor is installed. If a coprocessor is not installed,
- then Quick-Pascal provides procedures to execute floating-point
- calculations. In cases of rounding, these procedures are not guaranteed to
- produce precisely the same results as a coprocessor.%@NL@%
- %@NL@%
- %@CR:MQPCf200@%%@4@%%@AB@%Figure 12.2 QuickPascal Data Formats%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Real Type%@AE@%%@NL@%
- Width 1 39 8%@NL@%
- ┌───┬──────────────────────────────────────┬─────────────┐%@NL@%
- │ s │ f │ e │%@NL@%
- └───┴──────────────────────────────────────┴─────────────┘%@NL@%
- Bits 47 0%@NL@%
- %@NL@%
- %@AB@%Single Type%@AE@%%@NL@%
- Width 1 8 23%@NL@%
- ┌───┬─────────────┬──────────────────────────────────────┐%@NL@%
- │ s │ e │ f │%@NL@%
- └───┴─────────────┴──────────────────────────────────────┘%@NL@%
- Bits 31 0%@NL@%
- %@NL@%
- %@AB@%Double Type%@AE@%%@NL@%
- Width 1 11 52%@NL@%
- ┌───┬─────────────┬──────────────────────────────────────┐%@NL@%
- │ s │ e │ f │%@NL@%
- └───┴─────────────┴──────────────────────────────────────┘%@NL@%
- Bits 63 0%@NL@%
- %@NL@%
- %@AB@%Extended Type%@AE@%%@NL@%
- Width 1 15 1 63%@NL@%
- ┌───┬───────────┬───┬────────────────────────────────────┐%@NL@%
- │ s │ e │ i │ f │%@NL@%
- └───┴───────────┴───┴────────────────────────────────────┘%@NL@%
- Bits 79 0%@NL@%
- %@NL@%
- %@AB@%Comp Type%@AE@%%@NL@%
- Width 1 63%@NL@%
- ┌───┬────────────────────────────────────────────────────┐%@NL@%
- │ s │ d │%@NL@%
- └───┴────────────────────────────────────────────────────┘%@NL@%
- Bits 63 0%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC4202@%%@4@%With each of the formats illustrated in Figure 12.2%@BO: 58df2@%, the sign bit (s)%@EH@%
- indicates a negative number if on, and a nonnegative number if off. The
- fractional part (f) indicates the fractional part of the mantissa. To save
- space, the data formats all assume that the units' digit in the mantissa is
- equal to 1. Finally, the exponent is adjusted downward by a different number
- for each format. This means that for the four-byte %@AB@%Single%@AE@% type, the value
- represented is equal to%@NL@%
- %@NL@%
- -1^(s) * 1.f * 2^(e-127)%@NL@%
- %@NL@%
- %@CR:MQPC4204@%%@4@%For example, assume a variable of this type contains the following values:%@EH@%%@NL@%
- %@NL@%
- %@AS@% s = 0%@NL@%
- %@AS@% e = 127 decimal%@NL@%
- %@AS@% f = 11110100000000000000000 binary%@NL@%
- %@NL@%
- %@CR:MQPC4205@%%@4@%The value of the variable is 1.111101 binary. Note that (in contrast to%@EH@%
- Figure 12.2%@BO: 58df2@% and the example above) data storage on 8086 processors actually
- runs from least-significant bit (stored lowest in memory) to
- most-significant bit. This fact may make bytes appear to be backward if you
- use a debugging tool to dump a word at a time.%@NL@%
- %@NL@%
- %@CR:MQPC4206@%%@4@%The exponents are automatically reduced by 129 for the six-byte %@AB@%Real%@AE@% format,%@EH@%
- by 1,023 for the %@AB@%Double%@AE@% format, and by 16,383 for the %@AB@%Extended%@AE@% format. This
- automatic reduction lets the exponent field represent a negative number
- (producing a floating-point value between 1 and -1).%@NL@%
- %@NL@%
- %@CR:MQPC4207@%%@4@%In each format, if all bits are set to zero, then the resulting%@EH@%
- floating-point number is equal to zero.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC5000@%%@2@%%@AB@%12.5 Linking to Assembly Language%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC5001@%%@4@%You can link QuickPascal programs to modules written with the Microsoft%@EH@%
- Macro Assembler and other assemblers. However, be forewarned that
- Quick-Pascal has a number of conventions and restrictions that differ from
- other Microsoft languages. When you write an assembly-language procedure to
- link to QuickPascal, your assembly-language module can include%@NL@%
- %@NL@%
- %@CR:MQPC5002@% ■ Procedures and functions that the main program can call%@NL@%
- %@NL@%
- ■ References to global variables or data from a unit declared in an%@NL@%
- %@AB@%INTERFACE%@AE@% statement%@NL@%
- %@NL@%
- ■ Static data that is private to your assembly-language module%@NL@%
- %@NL@%
- %@CR:MQPC5003@%%@4@%However, the assembly-language module cannot declare public data for the%@EH@%
- QuickPascal code to reference. Furthermore, an assembly-language module must
- place all instructions in a single segment named CODE, and cannot use the
- %@AB@%GROUP%@AE@% directive. (Segment conventions are described in Section 12.5.2.%@BO: 5a798@%)
- Sections 12.5.1%@BO: 5a2af@%-12.5.6 list steps for writing an assembly-language module,
- in roughly the order that you would observe them in writing the code. You
- should read all of these sections carefully before attempting to write an
- assembly-language procedure (although the section on return values is
- optional and applies only when you write a function). Section 12.5.7%@BO: 5cf03@% has a
- simple, but complete, example.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC5100@%%@3@%%@AB@%12.5.1 Setting Up a Link to Assembly Language%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC5101@%%@4@%To link to assembly language, you must write an %@AB@%EXTERNAL%@AE@% declaration for%@EH@%
- each assembly-language procedure you're going to call and use the %@AB@%{$L}%@AE@%
- compiler directive to link in the object file.%@NL@%
- %@NL@%
- %@CR:MQPC5102@%%@4@%To write an %@AB@%EXTERNAL%@AE@% declaration, simply write a procedure or function%@EH@%
- heading as you would normally and follow the heading with the keyword
- %@AB@%EXTERNAL%@AE@% as shown below:%@NL@%
- %@NL@%
- %@AS@% FUNCTION compute( a, b, c: Integer ) : Integer; EXTERNAL;%@NL@%
- %@AS@% PROCEDURE switcheroo( VAR a, b, c : Byte ); EXTERNAL;%@NL@%
- %@NL@%
- %@CR:MQPC5103@%%@4@%Place the %@AB@%{$L}%@AE@% compiler directive at the beginning of your QuickPascal main%@EH@%
- program. The %@AB@%{$L}%@AE@% directive takes a single argument: the base file name of
- an object file. Note that you do not use LINK or any other utility to
- produce a program. Instead, QuickPascal sets up the link by copying the
- object file into the program and changing the file into its own internal
- object-code format. (The disk-based copy of the object file is not affected,
- however.)%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC5200@%%@3@%%@AB@%12.5.2 Segment and Data Conventions%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC5201@%%@4@%Observe the following conventions when declaring segments and data:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC5202@% ■ Place all executable statements in a segment named CODE or CSEG. Place%@NL@%
- all data declarations in a segment named DATA or DSEG. All other%@NL@%
- segments are ignored, as are group statements.%@NL@%
- %@NL@%
- ■ The segments can have the %@AB@%BYTE%@AE@% or %@AB@%WORD%@AE@% align type, but QuickPascal will%@NL@%
- always give segments word alignment.%@NL@%
- %@NL@%
- ■ Do not specify class names.%@NL@%
- %@NL@%
- ■ Declare %@AB@%PUBLIC%@AE@% each procedure that you want to call from QuickPascal.%@NL@%
- However, QuickPascal ignores any %@AB@%PUBLIC%@AE@% data declarations.%@NL@%
- %@NL@%
- ■ Do not initialize variables in the %@AB@%DATA%@AE@% segment. (Variables must be%@NL@%
- initialized with instructions.)%@NL@%
- %@NL@%
- ■ You can access data declared by the main program (or declared in an%@NL@%
- %@AB@%INTERFACE%@AE@% statement) by declaring it with the %@AB@%EXTRN%@AE@% directive. However,%@NL@%
- you cannot use the %@AB@%HIGH%@AE@% or %@AB@%LOW%@AE@% operators with external data. See%@NL@%
- Section 12.4%@BO: 5721f@%, "Internal Data Formats," for information on how to%@NL@%
- evaluate each data type.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC5300@%%@3@%%@AB@%12.5.3 Entering the Procedure%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC5301@%%@4@%The entry sequence for QuickPascal procedures is the same as that for other%@EH@%
- Microsoft languages. The first two instructions set up the BP register as
- the "framepointer," which points to the stack area of the current procedure.
- All parameters and local variables are available through BP:%@NL@%
- %@NL@%
- %@AS@% push bp%@NL@%
- %@AS@% mov bp, sp%@NL@%
- %@AS@% sub sp, local_size%@NL@%
- %@NL@%
- %@CR:MQPC5302@%%@4@%In the code above, %@AS@%local_size%@AE@% is a placeholder for the total size of local%@EH@%
- parameters you wish to use. This last step is entirely optional. Your
- procedure may be able to use registers to hold all temporary values. If not,
- you can use locations on the stack to hold data. (Specifically, these
- locations are below the address pointed to by BP, but no more than
- %@AS@%local_size%@AE@% bytes below this address.)%@NL@%
- %@NL@%
- %@CR:MQPC5303@%%@4@%Procedures called by QuickPascal must preserve the values of the BP, SP, SS,%@EH@%
- and DS registers. BP and SP are preserved by the standard entry and exit
- code. If you need to alter DS or SS, you must push their values onto the
- stack and pop them just before returning as shown below:%@NL@%
- %@NL@%
- %@AS@% push bp%@NL@%
- %@AS@% mov bp, sp%@NL@%
- %@AS@% sub sp, local_size%@NL@%
- %@AS@% push ds%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC5400@%%@3@%%@AB@%12.5.4 Accessing Parameters%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC5401@%%@4@%All parameters and local variables are accessed as indirect memory operands%@EH@%
- using the BP register. To determine the location of each parameter, you need
- to understand the QuickPascal calling conventions. This section summarizes
- those conventions and gives some examples with specific procedures.%@NL@%
- %@NL@%
- %@CR:MQPC5402@%%@4@%QuickPascal pushes each parameter onto the stack──in the order that the%@EH@%
- parameters appear in the source code──before making the actual call.
- Consequently, the first parameter is highest in memory. (Recall that the
- stack grows downward.) You can pass parameters by value or by reference. In
- Pascal, %@AB@%VAR%@AE@% parameters are passed by reference; other parameters are passed
- by value.%@NL@%
- %@NL@%
- %@CR:MQPC5403@%%@4@%When a parameter is passed by reference, QuickPascal pushes a four-byte%@EH@%
- pointer to the data. The offset portion of the pointer is always pushed
- first and is therefore higher in memory.%@NL@%
- %@NL@%
- %@CR:MQPC5404@%%@4@%When a parameter is passed by value, Pascal takes different actions%@EH@%
- depending on the data type:%@NL@%
- %@NL@%
- %@CR:MQPC5405@% ■ If the value parameter is %@AB@%Char%@AE@%, %@AB@%Boolean%@AE@%, any Pointer, any integer, or%@NL@%
- any floating-point type, QuickPascal pushes the parameter onto the%@NL@%
- stack.%@NL@%
- %@NL@%
- ■ If the parameter is a string or set type, QuickPascal passes a pointer%@NL@%
- to the data. This action is really the same as passing by reference. If%@NL@%
- you want to avoid any possibility of altering the data, make a%@NL@%
- temporary copy of the data, then work with the temporary copy.%@NL@%
- (QuickPascal procedures use this technique.)%@NL@%
- %@NL@%
- ■ If the parameter is an array or record type, QuickPascal pushes the%@NL@%
- variable directly onto the stack if it is no more than four bytes long.%@NL@%
- Otherwise, it pushes a pointer to the data.%@NL@%
- %@NL@%
- %@CR:MQPC5406@%%@4@%This calling convention for value parameters is not shared by other%@EH@%
- Microsoft high-level languages, which always push a value parameter directly
- onto the stack.%@NL@%
- %@NL@%
- %@CR:MQPC5407@%%@4@%Note that the %@AB@%PUSH%@AE@% instruction can push only one word of data at a time.%@EH@%
- QuickPascal always pushes the most-significant portion first, consistent
- with the 8086-processor convention that the most-significant portion is
- stored highest in memory.%@NL@%
- %@NL@%
- %@CR:MQPC5408@%%@4@%As noted in the next section, the QuickPascal code sometimes places an extra%@EH@%
- parameter on the stack for functions. (This extra parameter is a pointer to
- the location of the return value.)%@NL@%
- %@NL@%
- %@CR:MQPC5409@%%@4@%Finally, the QuickPascal code calls the procedure with a %@AB@%CALL%@AE@% instruction.%@EH@%
- Calls to external procedures are always far, so you should declare your
- assembly procedure with the %@AB@%FAR%@AE@% keyword.%@NL@%
- %@NL@%
- %@CR:MQPC540A@%%@4@%As an example, consider the following procedure call:%@EH@%%@NL@%
- %@NL@%
- %@AS@% PROCEDURE quad( VAR x : Real; a, b, c : Integer ); EXTERNAL;%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% quad( result, 2, 3, 4 );%@NL@%
- %@NL@%
- %@CR:MQPC540B@%%@4@%QuickPascal implements the call by placing the following items on the stack,%@EH@%
- and in this order:%@NL@%
- %@NL@%
- %@CR:MQPC540C@% 1. The segment address of result%@NL@%
- %@NL@%
- 2. The offset address of result%@NL@%
- %@NL@%
- 3. The value 2 (as a word)%@NL@%
- %@NL@%
- 4. The value 3%@NL@%
- %@NL@%
- 5. The value 4%@NL@%
- %@NL@%
- 6. The segment of the return address (the address to return to when done)%@NL@%
- %@NL@%
- 7. The offset of the return address%@NL@%
- %@NL@%
- %@CR:MQPC540D@%%@4@%A far %@AB@%CALL%@AE@% instruction places the last item, the return address, on the%@EH@%
- stack. After you perform the entry sequence, the BP register points to the
- location just below the return address. Each parameter can then be accessed
- with the following equates:%@NL@%
- %@NL@%
- %@AS@% result EQU <[BP + 12]>%@NL@%
- %@AS@% a EQU <[BP + 10]>%@NL@%
- %@AS@% b EQU <[BP + 8]>%@NL@%
- %@AS@% c EQU <[BP + 6]>%@NL@%
- %@NL@%
- %@CR:MQPC540E@%%@4@%As another example, consider the procedure call%@EH@%%@NL@%
- %@NL@%
- %@AS@% PROCEDURE repeat_it( num : LongInt;%@NL@%
- %@AS@% stuff : STRING ); EXTERNAL;%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% repeat_it( n, 'This is a message.' );%@NL@%
- %@NL@%
- %@CR:MQPC540F@%%@4@%With this procedure, QuickPascal implements the call by placing the%@EH@%
- following items on the stack:%@NL@%
- %@NL@%
- %@CR:MQPC540G@% 1. The most-significant word of the long integer %@AS@%n%@AE@%%@NL@%
- %@NL@%
- 2. The least-significant word of %@AS@%n%@AE@%%@NL@%
- %@NL@%
- 3. The segment address of the string data%@NL@%
- %@NL@%
- 4. The offset address of the string data%@NL@%
- %@NL@%
- 5. The segment of the return address%@NL@%
- %@NL@%
- 6. The offset of the return address%@NL@%
- %@NL@%
- %@CR:MQPC540H@%%@4@%A far %@AB@%CALL%@AE@% instruction places the last two items on the stack. After%@EH@%
- writing the entry sequence, you can access the parameters with the following
- equates:%@NL@%
- %@NL@%
- %@AS@% num EQU <[BP + 10]>%@NL@%
- %@AS@% stuff EQU <[BP + 6]>%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC5500@%%@3@%%@AB@%12.5.5 Returning a Value%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC5501@%%@4@%This section affects functions only. From the standpoint of assembly code,%@EH@%
- functions are just procedures that have a return value. To return a value to
- Quick-Pascal code, follow these conventions:%@NL@%
- %@NL@%
- %@CR:MQPC5502@% ■ For a six-byte %@AB@%Real%@AE@% type, place the result in DX:BX:AX, in which DX%@NL@%
- holds the most-significant word and AX the least.%@NL@%
- %@NL@%
- ■ For a string, %@AB@%CSTRING%@AE@%, %@AB@%Comp%@AE@%, or floating-point type other than %@AB@%Real%@AE@%,%@NL@%
- QuickPascal passes an additional parameter. This parameter is pushed%@NL@%
- first and is a pointer to a temporary storage location. Place the%@NL@%
- result of the function in this location.%@NL@%
- %@NL@%
- ■ For ordinal types (including %@AB@%Char%@AE@%, %@AB@%Boolean%@AE@%, and any integer), place the%@NL@%
- result in AL if one byte, AX if two bytes, and DX:AX if a double word%@NL@%
- (in which DX holds the most-significant byte).%@NL@%
- %@NL@%
- ■ QuickPascal does not support functions that return array or record%@NL@%
- types. (However, you can set the value of an array or record if%@NL@%
- QuickPascal passes it as a %@AB@%VAR%@AE@% parameter.)%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC5600@%%@3@%%@AB@%12.5.6 Exiting the Procedure%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC5601@%%@4@%To exit the procedure, first pop any registers you preserved on the stack.%@EH@%
- Then write the following instructions:%@NL@%
- %@NL@%
- %@AS@% mov sp,bp%@NL@%
- %@AS@% pop bp%@NL@%
- %@AS@% ret param_size%@NL@%
- %@NL@%
- %@CR:MQPC5602@%%@4@%In the code given above, %@AS@%param_size%@AE@% is a placeholder for the total size of%@EH@%
- parameters in your procedure. This last instruction is necessary to
- completely restore the stack.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPC5700@%%@3@%%@AB@%12.5.7 A Complete Example%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPC5701@%%@4@%The following example of linking QuickPascal programs to modules written in%@EH@%
- assembly language is simple, but complete. The Pascal source code contains
- the following statements:%@NL@%
- %@NL@%
- %@AS@% {$L SWITCH }%@NL@%
- %@AS@% PROCEDURE switch( VAR a, b : Word ); EXTERNAL;%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% switch( x, y );%@NL@%
- %@NL@%
- %@CR:MQPC5702@%%@4@%Since the parameters are %@AB@%VAR%@AE@% parameters, QuickPascal passes pointers to the%@EH@%
- parameters. Then, the assembly code must use indirect register operands to
- access the data. The following procedure exchanges the values of the two
- variables.%@NL@%
- %@NL@%
- %@AI@%; SWITCH.ASM%@AE@%%@NL@%
- %@AI@%;%@AE@%%@NL@%
- %@AS@% CODE SEGMENT WORD PUBLIC%@NL@%
- %@NL@%
- %@AS@% ASSUME CS:CODE%@NL@%
- %@NL@%
- %@AS@% PUBLIC switch%@AE@% %@AI@%; Make procedure public%@AE@%%@NL@%
- %@NL@%
- %@AS@% a EQU <[BP + 10]>%@AE@% %@AI@%; Parameters for switch%@AE@%%@NL@%
- %@AS@% b EQU <[BP + 6]> %@AE@% %@AI@%; procedure%@AE@%%@NL@%
- %@NL@%
- %@AS@% switch PROC FAR%@NL@%
- %@AS@% push bp %@AE@% %@AI@%; Entry sequence%@AE@%%@NL@%
- %@AS@% mov bp,sp%@NL@%
- %@AS@% push ds%@NL@%
- %@NL@%
- %@AS@% lds si, a %@AE@% %@AI@%; Load ptr into ds:si%@AE@%%@NL@%
- %@AS@% les di, b %@AE@% %@AI@%; Load ptr into es:di%@AE@%%@NL@%
- %@AS@% mov bx, es:[di]%@AE@% %@AI@%; temp = b%@AE@%%@NL@%
- %@AS@% xchg bx, [si] %@AE@% %@AI@%; Switch temp and a%@AE@%%@NL@%
- %@AS@% xchg bx, es:[di]%@AE@% %@AI@%; Switch temp and b%@AE@%%@NL@%
- %@NL@%
- %@AS@% pop ds%@NL@%
- %@AS@% mov sp,bp %@AE@% %@AI@%; Exit sequence%@AE@%%@NL@%
- %@AS@% pop bp%@NL@%
- %@AS@% ret 8 %@AE@% %@AI@%; Total of 8 bytes in%@AE@%%@NL@%
- %@AI@%; parameters%@AE@%%@NL@%
- %@AS@% switch ENDP%@NL@%
- %@NL@%
- %@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@CR:MQPP3000@%%@1@%%@AB@%Part 3 Graphics and Objects%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPP3003@%%@4@%Part 3 of %@AI@%Pascal by Example%@AE@% covers QuickPascal support of graphics, fonts,%@EH@%
- and object-oriented programming. Each of these topics requires a moderate
- degree of experience with Pascal. You need to be comfortable with all of the
- topics in Part 1 and may find familiarity with Part 2 helpful.%@NL@%
- %@NL@%
- %@CR:MQPP3004@%%@4@%The graphics and fonts chapters show you how to use the QuickPascal graphics%@EH@%
- unit to create colorful and informative screen displays. The chapter on
- object-oriented programming introduces the fundamental concepts of
- programming with objects and how to implement those concepts in QuickPascal.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD0000@%%@1@%%@AB@%Chapter 13 Using Graphics%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQPD0001@%%@4@%This chapter explains how to call graphics routines that set points, draw%@EH@%
- lines, change colors, and draw shapes such as rectangles and circles. The
- first section describes the general structure of any graphics program,
- defines important graphics terms, and works through an example program step
- by step, showing how to use the basic routines. Subsequent sections explain
- video modes, coordinate systems, and animation.%@NL@%
- %@NL@%
- %@CR:MQPD0002@%%@4@%To run any graphics programs, your computer must have graphics capability.%@EH@%
- The QuickPascal graphics facility supports the Color Graphics Adapter (CGA),
- the Enhanced Graphics Adapter (EGA), and the Video Graphics Adapter (VGA)
- video modes available on IBM(R) and IBM-compatible computers. The graphics
- facility also supports the Olivetti(R) (and AT&T(R)) enhanced video modes
- and the Hercules(R) monochrome graphics mode.%@NL@%
- %@NL@%
- %@CR:MQPD0003@%%@4@%This chapter discusses the techniques for writing graphics programs but does%@EH@%
- not cover every graphics procedure and function (there are more than 75).
- You can explore additional topics by using the QP Advisor and the example
- programs. Be sure to check the README.DOC file for any last-minute changes
- or additions.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD1000@%%@2@%%@AB@%13.1 Getting Started with Graphics%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD1001@%%@4@%The subject of graphics and color display on computers is fairly complex.%@EH@%
- This chapter and the next one, "Using Fonts," provide an introduction to
- graphics and fonts. The next sections cover common graphics terms and list
- sources for more information on graphics.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD1100@%%@3@%%@AB@%13.1.1 Graphics Terms%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD1101@%%@4@%There are several concepts you need to know before you can create graphics%@EH@%
- programs. The following list explains the most useful terms:%@NL@%
- %@NL@%
- %@CR:MQPD1102@% ■ The "%@AI@%x%@AE@% axis" determines the horizontal position on the screen. The%@NL@%
- "origin" (point 0, 0) is in the upper left corner. The maximum number%@NL@%
- of horizontal "pixels" (picture elements) varies from 320 to 640 to%@NL@%
- 720, depending on the graphics card installed and the graphics mode in%@NL@%
- effect.%@NL@%
- %@NL@%
- ■ The "%@AI@%y%@AE@% axis" is the vertical position on the screen. The origin is the%@NL@%
- upper left corner. The number of vertical pixels ranges from 200 to%@NL@%
- 480.%@NL@%
- %@NL@%
- ■ Each graphics mode offers a "palette" from which you may choose the%@NL@%
- colors to be displayed. You may have access to 2, 4, 8, 16, or 256%@NL@%
- "color indexes," depending on the graphics card in the computer and the%@NL@%
- graphics mode in effect. The color is the index to the palette of%@NL@%
- colors displayable by a particular graphics adapter.%@NL@%
- %@NL@%
- ■ The CGA modes offer four fixed palettes containing predefined colors%@NL@%
- that may not be changed. In EGA, MCGA, and VGA graphics modes, you may%@NL@%
- change any of the color indexes by providing a color value that%@NL@%
- describes the mix of colors you wish to use.%@NL@%
- %@NL@%
- ■ A color index is always a short integer. A color value is always a long%@NL@%
- integer. When you're calling graphics functions that require%@NL@%
- color-related parameters, you should be aware of the difference between%@NL@%
- color indexes and color values.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD1200@%%@3@%%@AB@%13.1.2 For More Information%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD1201@%%@4@%The following books cover a variety of graphics topics that you may find%@EH@%
- useful. They are listed only for your convenience. With the exception of its
- own publications, Microsoft does not endorse these books or recommend them
- over others on the same subject.%@NL@%
- %@NL@%
- %@CR:MQPD1202@% ■ Artwick, Bruce. %@AI@%Microcomputer Displays, Graphics and Animation%@AE@%.%@NL@%
- Englewood Cliffs, NJ: Prentice-Hall, Inc., 1985.%@NL@%
- %@NL@%
- Discussion of microcomputer graphics and animation from the%@NL@%
- creator of %@AI@%Microsoft Flight Simulator%@AE@%.%@NL@%
- %@NL@%
- ■ Kliewer, Bradley D. %@AI@%EGA/VGA: A Programmer's Reference%@AE@% %@AI@%Guide%@AE@%. New York,%@NL@%
- NY: Intertext Publications, Inc., 1988.%@NL@%
- %@NL@%
- A detailed discussion of the EGA and VGA video modes.%@NL@%
- %@NL@%
- ■ Norton, Peter, and Richard Wilton. %@AI@%The New Peter Norton%@AE@% %@AI@%Programmer's%@AE@%%@NL@%
- %@AI@%Guide to the IBM PC and PS/2%@AE@%. Redmond, WA: Microsoft Press, 1985.%@NL@%
- %@NL@%
- The standard guide to the inside of the IBM PC and PS/2 families%@NL@%
- of computers. Several chapters are devoted to video modes.%@NL@%
- %@NL@%
- ■ Wilton, Richard. %@AI@%Programmer's Guide to PC and PS/2%@AE@% %@AI@%Video Systems%@AE@%.%@NL@%
- Redmond, WA: Microsoft Press, 1987.%@NL@%
- %@NL@%
- An advanced guide to all the PC and PS/2 video modes.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD2000@%%@2@%%@AB@%13.2 Writing Your First Graphics Program%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD2001@%%@4@%In QuickPascal, all graphics programs must follow these six basic steps:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD2002@% 1. Use the %@AB@%MSGraph%@AE@% unit.%@NL@%
- %@NL@%
- 2. Set a video mode.%@NL@%
- %@NL@%
- 3. Determine the video parameters.%@NL@%
- %@NL@%
- 4. Set up a coordinate system.%@NL@%
- %@NL@%
- 5. Create and display graphics.%@NL@%
- %@NL@%
- 6. Restore initial video configuration and exit the program.%@NL@%
- %@NL@%
- %@CR:MQPD2003@%%@4@%A simple graphics program, 1STGRAPH.PAS, is shown below. In the next few%@EH@%
- pages, this program will be dissected into the six required elements of a
- graphics program.%@NL@%
- %@NL@%
- %@AS@% PROGRAM FirstGraphics;%@NL@%
- %@AS@% { 1STGRAPH.PAS: Demonstrates basic graphics program structure }%@NL@%
- %@NL@%
- %@AS@% USES%@NL@%
- %@AS@% MSGraph;%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% a, i : integer;%@NL@%
- %@AS@% vc : _VideoConfig;%@NL@%
- %@NL@%
- %@AS@% BEGIN { Begin main program. }%@NL@%
- %@NL@%
- %@AS@% _ClearScreen( _GClearScreen);%@NL@%
- %@NL@%
- %@AS@% { Set the highest resolution video mode and check for success }%@NL@%
- %@AS@% a := _SetVideoMode( _MaxResMode );%@NL@%
- %@NL@%
- %@AS@% IF ( a = 0 ) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'No valid graphics mode; hit RETURN to continue' );%@NL@%
- %@AS@% Readln;%@NL@%
- %@AS@% a := _SetVideoMode( _DefaultMode );%@NL@%
- %@AS@% Halt ( 0 );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% { Find out some screen characteristics. }%@NL@%
- %@AS@% _GetVideoConfig( vc );%@NL@%
- %@AS@% Writeln( 'mode: ',vc.Mode );%@NL@%
- %@AS@% Writeln( 'Horizontal resolution: ', vc.NumXPixels );%@NL@%
- %@AS@% Writeln( 'Vertical resolution: ', vc.NumYPixels );%@NL@%
- %@AS@% Writeln( 'Number of colors: ', vc.NumColors );%@NL@%
- %@NL@%
- %@AS@% { Draw a colored rectangle and ellipse in lower left quadrant. }%@NL@%
- %@AS@% _SetColor( 4 );%@NL@%
- %@AS@% _Rectangle( _GBorder, 0, vc.NumYPixels - 1,%@NL@%
- %@AS@% vc.NumXPixels DIV 4,%@NL@%
- %@AS@% vc.NumYPixels * 3 DIV 4 );%@NL@%
- %@AS@% _Ellipse( _GBorder, 0, vc.NumYPixels - 1,%@NL@%
- %@AS@% vc.NumXPixels DIV 4,%@NL@%
- %@AS@% vc.NumYPixels * 3 DIV 4 );%@NL@%
- %@NL@%
- %@AS@% { Draw a line from the corner of the rectangle to the screen center. }%@NL@%
- %@AS@% _SetColor( 3 );%@NL@%
- %@AS@% _MoveTo( vc.NumXPixels DIV 4, vc.NumYPixels * DIV 4 );%@NL@%
- %@AS@% _LineTo( vc.NumXPixels DIV 2, vc.NumYPixels DIV 2 );%@NL@%
- %@NL@%
- %@AS@% { Wait for RETURN key and then restore video mode. }%@NL@%
- %@AS@% Readln;%@NL@%
- %@AS@% _SetVideoMode(_DefaultMode);%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQPD2010@%%@4@%%@AB@%Using the MSGraph Unit%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD2011@%%@4@%The first step in creating 1STGRAPH.PAS is to use the %@AB@%MSGraph%@AE@% unit within%@EH@%
- your QuickPascal program. The %@AB@%MSGraph%@AE@% unit contains the constants, data
- types, procedures, and functions used in graphics programs. QuickPascal
- units are explained in Chapter 7%@BO: 31ac9@%, "Units." The %@AB@%MSGraph%@AE@% unit is the library
- of graphics features you need to access from your program.%@NL@%
- %@NL@%
- %@CR:MQPD2012@%%@4@%The %@AB@%USES%@AE@% section of your program calls %@AB@%MSGraph%@AE@%. This section appears%@EH@%
- immediately after the %@AB@%PROGRAM%@AE@% declaration line and looks like this:%@NL@%
- %@NL@%
- %@AS@% USES%@NL@%
- %@AS@% MSGraph;%@NL@%
- %@NL@%
- %@CR:MQPD2013@%%@4@%Note that some components of the %@AB@%MSGraph%@AE@% unit are incompatible with some%@EH@%
- functions within the %@AB@%Crt%@AE@% unit. Some of the %@AB@%Crt%@AE@% unit routines that deal with
- the display (such as %@AB@%HighVideo%@AE@% or %@AB@%DirectVideo%@AE@%) conflict with the graphics
- functions.%@NL@%
- %@NL@%
- %@CR:MQPD2014@%%@4@%The following %@AB@%Crt%@AE@% routines are safe to use with the %@AB@%MSGraph%@AE@% unit:%@EH@%%@NL@%
- %@NL@%
- %@AB@%AssignCRT NoSound WhereY%@AE@%%@NL@%
- %@AB@%Delay ReadKey Window%@AE@%%@NL@%
- %@AB@%GotoXY Sound%@AE@%%@NL@%
- %@AB@%KeyPressed WhereX%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPD2020@%%@4@%%@AB@%Setting the Video Mode%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD2021@%%@4@%Before you can start drawing pictures on the screen, your program must tell%@EH@%
- the graphics adapter to switch from text mode to graphics mode. Call
- %@AB@%_SetVideoMode%@AE@%, passing it a predefined constant that tells it which mode to
- display. The constants listed in Table 13.1%@BO: 60246@% are defined in the %@AB@%MSGraph%@AE@%
- unit. The dimensions are listed in columns for video text modes and in
- pixels for graphics mode.%@NL@%
- %@NL@%
- %@CR:MQPDT100@%%@4@%%@AB@%Table 13.1 Constants Set by _SetVideoMode%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Constant Video Mode Mode Type/Hardware%@AE@%%@NL@%
- %@NL@%
- %@AB@%_DefaultMode%@AE@% Restores to original mode Both/All%@NL@%
- %@AB@%_MaxResMode%@AE@% Highest resolution Graphics/All%@NL@%
- %@AB@%_MaxColorMode%@AE@% Maximum colors Graphics/All%@NL@%
- %@AB@%_TextBW40%@AE@% 40 column text, 16 gray Text/CGA%@NL@%
- %@AB@%_TextC40%@AE@% 40 column text, 16/8 color Text/CGA%@NL@%
- %@AB@%_TextBW80%@AE@% 80 column text, 16 gray Text/CGA%@NL@%
- %@AB@%_TextC80%@AE@% 80 column text, 16/8 color Text/CGA%@NL@%
- %@AB@%_MRes4Color%@AE@% 320 X 200, 4 color Graphics/CGA%@NL@%
- %@AB@%_MResNoColor%@AE@% 320 X 200, 4 gray Graphics/CGA%@NL@%
- %@AB@%_HResBW%@AE@% 640 X 200, BW Graphics/CGA%@NL@%
- %@AB@%_TextMono%@AE@% 80 column text, BW Text/MDPA%@NL@%
- %@AB@%_HercMono%@AE@% 720 X 348, BW for HGC Graphics/HGC%@NL@%
- %@AB@%_MRes16Color%@AE@% 320 X 200, 16 color Graphics/EGA%@NL@%
- %@AB@%_HRes16Color%@AE@% 640 X 200, 16 color Graphics/EGA%@NL@%
- %@AB@%_EResNoColor%@AE@% 640 X 350, BW Graphics/EGA%@NL@%
- %@AB@%_EResColor%@AE@% 640 X 350, 4 or 16 color Graphics/EGA%@NL@%
- %@AB@%_VRes2Color%@AE@% 640 X 480, BW Graphics/VGA/MCGA%@NL@%
- %@AB@%_VRes16Color%@AE@% 640 X 480, 16 color Graphics/VGA%@NL@%
- %@AB@%_MRes256Color%@AE@% 320 X 200, 256 color Graphics/VGA/MCGA%@NL@%
- %@AB@%_OResColor%@AE@% 640 X 400, 1 of 16 colors Graphics/Olivetti%@NL@%
- %@NL@%
- %@CR:MQPD2022@%%@4@%These video modes are described more fully in Section 13.3%@BO: 63072@%.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD2023@%%@4@%The special modes %@AB@%_MaxResMode%@AE@% and %@AB@%_MaxColorMode%@AE@% are used when you simply%@EH@%
- want QuickPascal to determine the highest resolution or maximum color mode
- available.%@NL@%
- %@NL@%
- %@CR:MQPD2024@%%@4@%If the %@AB@%_SetVideoMode%@AE@% function returns a 0, it means the hardware does not%@EH@%
- support the selected mode. You may continue to select alternate video modes
- until a nonzero value is returned. If the hardware configuration doesn't
- support any of the selected video modes, then exit the program.%@NL@%
- %@NL@%
- %@CR:MQPD2025@%%@4@%The segment of example program 1STGRAPH.PAS below sets the video mode for%@EH@%
- maximum resolution and then checks for success. If the function
- %@AB@%_SetVideoMode%@AE@% fails (and returns a 0), the program prints a message,
- restores the video mode, and halts.%@NL@%
- %@NL@%
- %@AS@% { Set the highest resolution mode and check for success }%@NL@%
- %@AS@% a := _SetVideoMode( _MaxResMode );%@NL@%
- %@AS@% IF ( a = 0 ) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'No valid graphics mode; hit RETURN to continue' );%@NL@%
- %@AS@% Readln;%@NL@%
- %@AS@% a := _SetVideoMode( _DefaultMode );%@NL@%
- %@AS@% Halt (0);%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQPD2030@%%@4@%%@AB@%Determining the Video Parameters%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD2031@%%@4@%After entering graphics mode, you can check the current video configuration.%@EH@%
- This is necessary when you have used the constant %@AB@%_MaxResMode%@AE@% or
- %@AB@%_MaxColorMode%@AE@%, since you do not know the specifics of the video mode
- selected.%@NL@%
- %@NL@%
- %@CR:MQPD2032@%%@4@%The video configuration requires a special structure called %@AB@%_VideoConfig%@AE@%,%@EH@%
- which is defined in the %@AB@%MSGraph%@AE@% unit. The %@AB@%_GetVideoConfig%@AE@% procedure finds
- the current video configuration information.%@NL@%
- %@NL@%
- %@CR:MQPD2033@%%@4@%The %@AB@%_VideoConfig%@AE@% structure contains the following elements:%@EH@%%@NL@%
- %@NL@%
- %@AS@% { Structure for GetVideoConfig }%@NL@%
- %@NL@%
- %@AS@% _VideoConfig = RECORD%@NL@%
- %@AS@% NumXPixels : Integer; { Horizontal resolution }%@NL@%
- %@AS@% NumYPixels : Integer; { Vertical resolution }%@NL@%
- %@AS@% NumTextCols : Integer; { Number of text columns available }%@NL@%
- %@AS@% NumTextRows : Integer; { Number of text rows available }%@NL@%
- %@AS@% NumColors : Integer; { Number of actual colors }%@NL@%
- %@AS@% BitsPerPixel : Integer; { Number of bits per pixel }%@NL@%
- %@AS@% NumVideoPages : Integer; { Number of available video pages }%@NL@%
- %@AS@% Mode : Integer; { Current video mode }%@NL@%
- %@AS@% Adapter : Integer; { Active display adapter }%@NL@%
- %@AS@% Monitor : Integer; { Active display monitor }%@NL@%
- %@AS@% Memory : Integer; { Adapter video memory in K bytes }%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQPD2034@%%@4@%The variables within the %@AB@%_VideoConfig%@AE@% structure are initialized when you%@EH@%
- call %@AB@%_GetVideoConfig%@AE@%. In the following example program, the video mode is
- set to %@AB@%_MaxResMode%@AE@%. The program then calls %@AB@%_GetVideoConfig%@AE@% to determine the
- screen dimensions (in pixels) and the maximum number of colors allowed.%@NL@%
- %@NL@%
- %@AS@% { Find out some screen characteristics. }%@NL@%
- %@AS@% _GetVideoConfig( ,vc );%@NL@%
- %@AS@% Writeln( 'mode: 'vc.Mode );%@NL@%
- %@AS@% Writeln( 'Horizontal resolution: ', vc.NumXPixels );%@NL@%
- %@AS@% Writeln( 'Vertical resolution: ', vc.NumYPixels );%@NL@%
- %@AS@% Writeln( 'Number of colors: ', vc.NumColors );%@NL@%
- %@NL@%
- %@CR:MQPD2040@%%@4@%%@AB@%Setting Up Coordinate Systems%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD2041@%%@4@%The third step in writing a QuickPascal graphics program is to establish the%@EH@%
- "coordinate system."%@NL@%
- %@NL@%
- %@CR:MQPD2042@%%@4@%A coordinate system is used to identify a pixel location relative to a%@EH@%
- horizontal and vertical axis. In a graphics mode, each pixel on the screen
- can be located by means of a unique pair of coordinates. The QuickPascal
- graphics unit supports the following coordinate systems:%@NL@%
- %@NL@%
- %@CR:MQPD2043@% ■ Text coordinates%@NL@%
- %@NL@%
- ■ Physical coordinates%@NL@%
- %@NL@%
- ■ Viewport coordinates%@NL@%
- %@NL@%
- ■ Window coordinates%@NL@%
- %@NL@%
- %@CR:MQPD2044@%%@4@%Since this example graphics program does not specify otherwise, the%@EH@%
- coordinate system used is that provided by the physical screen dimensions.
- This is known as the "physical-coordinate system."%@NL@%
- %@NL@%
- %@CR:MQPD2045@%%@4@%But how much screen is available to work with? There might be 720 X 348, 640%@EH@%
- X 480, 640 X 400, 640 X 350, or 640 X 200 pixels. The %@AB@%_VideoConfig%@AE@% structure
- elements %@AB@%NumXPixels%@AE@% and %@AB@%NumYPixels%@AE@% provide the screen dimensions. On a VGA
- card, a request for maximum resolution would set the screen to the
- %@AB@%_VRes16Color%@AE@% mode. The horizontal resolution is 640 pixels and vertical
- resolution is 480. The horizontal resolution might be 640, but the pixels
- are numbered 0-639.%@NL@%
- %@NL@%
- %@CR:MQPD2046@%%@4@%The physical-coordinate system places the origin (or the coordinate pair%@EH@%
- (0,0)) at the upper left corner of the screen. Increasing positive values of
- the %@AI@%x%@AE@% coordinate extend from left to right. Increasing positive values of
- the %@AI@%y%@AE@% coordinate extend from top to bottom.%@NL@%
- %@NL@%
- %@CR:MQPD2047@%%@4@%The physical-coordinate system is dependent on the hardware and display%@EH@%
- configuration and cannot be changed. The other coordinate systems and the
- procedures used to translate between them are described in Section 13.4%@BO: 6ac8a@%.%@NL@%
- %@NL@%
- %@CR:MQPD2050@%%@4@%%@AB@%Drawing Graphics%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD2051@%%@4@%The next few lines in this example program draw a rectangle and an ellipse%@EH@%
- and then a line to the center of the screen. Prior to drawing the rectangle
- or the line, the graphics color is set to two different values. The program
- segment that draws the rectangle and ellipse is shown below:%@NL@%
- %@NL@%
- %@AS@% { Draw a colored rectangle and ellipse in lower left quadrant. }%@NL@%
- %@AS@% _SetColor( 4 );%@NL@%
- %@AS@% _Rectangle( _GBorder, 0, vc.NumYPixels - 1,%@NL@%
- %@AS@% vc.NumXPixels DIV 4, vc.NumYPixels * 3 DIV 4 );%@NL@%
- %@AS@% _Ellipse( _GBorder, 0, vc.NumYPixels - 1,%@NL@%
- %@AS@% vc.NumXPixels DIV 4, vc.NumYPixels * 3 DIV 4 );%@NL@%
- %@NL@%
- %@CR:MQPD2052@%%@4@%The call to the%@AB@%_Rectangle%@AE@% procedure has five arguments. The first argument%@EH@%
- is the "fill flag," which may be either %@AB@%_GBorder%@AE@% or%@AB@%_GFillInterior%@AE@%. The fill
- flag determines whether the figure will be drawn with just the border or as
- a solid figure. Choose %@AB@%_GBorder%@AE@% if you want a rectangle of four lines (a
- border only, in the current line style). Or you can choose %@AB@%_GFillInterior%@AE@% if
- you want a solid rectangle (filled in with the current color and fill
- pattern).%@NL@%
- %@NL@%
- %@CR:MQPD2053@%%@4@%The second and third arguments are the %@AI@%x%@AE@% and %@AI@%y%@AE@% coordinates of one corner of%@EH@%
- the rectangle. The fourth and fifth arguments are the coordinates of the
- opposite corner. The coordinates for the two corners are defined in terms of
- the measurements obtained from %@AB@%_GetVideoConfig%@AE@%. As a result, this program
- draws the rectangle correctly in any graphics mode.%@NL@%
- %@NL@%
- %@CR:MQPD2054@%%@4@%The %@AB@%_Ellipse%@AE@% procedure draws an ellipse on the screen. Its parameters%@EH@%
- resemble the parameters for %@AB@%_Rectangle%@AE@%. Both procedures require a fill flag
- and two corners of a "bounding rectangle." When the ellipse is drawn, four
- points touch the edges of the bounding rectangle. A bounding rectangle
- defines the space in which a rounded figure is drawn. For a rounded figure,
- the center of the bounding rectangle defines the center of the rounded
- figure. A bounding rectangle is defined by the coordinates of the upper left
- corner and the lower right corner of the rectangle.%@NL@%
- %@NL@%
- %@CR:MQPD2055@%%@4@%When the program first enters a graphics mode or sets a viewport (as%@EH@%
- discussed in Section 13.4%@BO: 6ac8a@%), the drawing position is set to the center of
- the screen. Since the %@AB@%_Rectangle%@AE@% procedure takes the corners of the
- rectangle as parameters, there is no need to set the drawing position. But
- after the figures are drawn, the program moves the current drawing position
- (with the %@AB@%_MoveTo%@AE@% procedure) and draws a line from the new position to the
- center of the screen:%@NL@%
- %@NL@%
- %@AS@% { Draw a line from the corner of the rectangle to the screen center. }%@NL@%
- %@AS@% _SetColor( 3 );%@NL@%
- %@AS@% _MoveTo( vc.NumXPixels DIV 4, vc.NumYPixels * 3 DIV 4 );%@NL@%
- %@AS@% _LineTo( vc.NumXPixels DIV 2, vc.NumYPixels DIV 2 );%@NL@%
- %@NL@%
- %@CR:MQPD2056@%%@4@%Again, the coordinates are given in terms of %@AB@%NumXPixels%@AE@% and %@AB@%NumYPixels%@AE@% to%@EH@%
- ensure portability across video modes.%@NL@%
- %@NL@%
- %@CR:MQPD2060@%%@4@%%@AB@%Restoring Initial Video Configuration and Exiting%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD2061@%%@4@%The final step in any graphics program is to restore the default video mode.%@EH@%
- In the sample program, the %@AB@%Readln%@AE@% procedure waits for the RETURN key. The
- %@AB@%_SetVideoMode%@AE@% function restores the screen to the default mode, which sets
- the screen back to normal.%@NL@%
- %@NL@%
- %@AS@% { Wait for RETURN key and then restore the video mode. }%@NL@%
- %@AS@% Readln;%@NL@%
- %@AS@% a := _SetVideoMode(_DefaultMode);%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD3000@%%@2@%%@AB@%13.3 Using Video Modes%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD3001@%%@4@%The QuickPascal %@AB@%MSGraph%@AE@% unit provides support for the following video%@EH@%
- adapters and displays:%@NL@%
- %@NL@%
- %@CR:MQPD3002@% ■ Monochrome Display Printer Adapter (MDPA)%@NL@%
- ■ Hercules-compatible graphics adapters%@NL@%
- ■ CGA%@NL@%
- ■ EGA%@NL@%
- ■ VGA%@NL@%
- ■ MCGA%@NL@%
- ■ Olivetti-compatible graphics adapters (including AT&T 6300 series)%@NL@%
- %@NL@%
- %@CR:MQPD3003@%%@4@%The sections that follow explain how to select a video mode, then discuss%@EH@%
- the major CGA, EGA, and VGA graphics modes. A complete listing of the
- QuickPascal video modes that can be set by the %@AB@%_SetVideoMode%@AE@% function is
- shown in Table 13.1%@BO: 60246@%.%@NL@%
- %@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@AI@%NOTE%@AE@%%@NL@%
- If you use a Hercules graphics card, you must run the MSHERC.COM program%@NL@%
- before attempting to display any graphics in %@AB@%_HercMono%@AE@% mode. If your%@NL@%
- computer also has a color graphics card, you must run MSHERC.COM with the%@NL@%
- /H (/HALF) option to set the Hercules graphics card in HALF mode.%@NL@%
- Otherwise, the results will be unpredictable.%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQPD3004@%%@4@%The %@AB@%_VideoConfig%@AE@% structure, which is returned by %@AB@%_GetVideoConfig%@AE@%, includes%@EH@%
- fields that denote the type of graphics adapter and monitor in use. Table
- 13.2%@BO: 636da@% lists the constants for graphics adapters.%@NL@%
- %@NL@%
- %@CR:MQPDT200@%%@4@%%@AB@%Table 13.2 Constants for Graphics Adapters%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Constant Value Description%@AE@%%@NL@%
- %@NL@%
- %@AB@%_MDPA%@AE@% 0x0001 Monochrome Display Adapter%@NL@%
- %@AB@%_CGA%@AE@% 0x0002 Color Graphics Adapter%@NL@%
- %@AB@%_EGA%@AE@% 0x0004 Enhanced Graphics Adapter%@NL@%
- %@AB@%_VGA%@AE@% 0x0008 Video Graphics Array%@NL@%
- %@AB@%_MCGA%@AE@% 0x0010 MultiColor Graphics Array%@NL@%
- %@AB@%_HGC%@AE@% 0x0020 Hercules Graphics Card%@NL@%
- %@AB@%_OCGA%@AE@% 0x0042 Olivetti Color Graphics Adapter%@NL@%
- %@AB@%_OEGA%@AE@% 0x0044 Olivetti Enhanced Graphics Adapter%@NL@%
- %@AB@%_OVGA%@AE@% 0x0048 Olivetti Video Graphics Array%@NL@%
- %@NL@%
- %@CR:MQPD3005@%%@4@%Table 13.3%@BO: 63a63@% lists the constants for monitors.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPDT300@%%@4@%%@AB@%Table 13.3 Constants for Monitors%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Constant Value Description%@AE@%%@NL@%
- %@NL@%
- %@AB@%_Mono%@AE@% 0x0001 Monochrome%@NL@%
- %@AB@%_Color%@AE@% 0x0002 Color%@NL@%
- %@AB@%_ENHColor%@AE@% 0x0004 Enhanced Color%@NL@%
- %@AB@%_AnalogMono%@AE@% 0x0008 Analog Monochrome only%@NL@%
- %@AB@%_AnalogColor%@AE@% 0x0010 Analog Color only%@NL@%
- %@AB@%_Analog%@AE@% 0x0018 Analog Monochrome and Color modes%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD3100@%%@3@%%@AB@%13.3.1 Selecting a Video Mode%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD3101@%%@4@%Before you can display graphics, you must put the graphics adapter into a%@EH@%
- graphics mode. As shown in the example program, the %@AB@%_SetVideoMode%@AE@% function
- performs this task. Before calling %@AB@%_SetVideoMode%@AE@%, you must decide which
- graphics modes are acceptable for your purposes. There are several ways you
- can select an appropriate graphics mode:%@NL@%
- %@NL@%
- %@CR:MQPD3102@% ■ Set the mode to a specified value. If you want the program to work in a%@NL@%
- high-resolution EGA color mode, use %@AB@%_SetVideoMode%@AE@% to set the mode to%@NL@%
- %@AB@%_EResColor%@AE@%:%@NL@%
- %@NL@%
- %@AS@%a := _SetVideoMode( _EResColor );%@AE@%%@NL@%
- %@NL@%
- ■ Request either the highest resolution available using the %@AB@%_MaxResMode%@AE@%%@NL@%
- constant or the greatest color selection, %@AB@%_MaxColorMode%@AE@%, available with%@NL@%
- your monitor and adapter configuration:%@NL@%
- %@NL@%
- %@AS@% { Selects highest resolution }%@NL@%
- %@AS@%a := _SetVideoMode( _MaxResMode );%@AE@%%@NL@%
- %@AS@% { or, selects most colors }%@NL@%
- %@AS@%a := _SetVideoMode( _MaxColorMode );%@AE@%%@NL@%
- %@NL@%
- ■ Specify a specific resolution mode (such as 320 x 200 pixels) by first%@NL@%
- determining the video adapter type (from the %@AB@%_VideoConfig%@AE@% structure)%@NL@%
- and then setting the appropriate mode for the adapter. The program%@NL@%
- fragment below shows how this technique can be used to set a 320 x 200%@NL@%
- pixel resolution mode.%@NL@%
- %@NL@%
- %@NL@%
- %@AS@% _GetVideoConfig( vc ); { Find out adapter type }%@NL@%
- %@AS@% IF (vc.Monitor = _Mono) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'This program requires a color monitor.' );%@NL@%
- %@AS@% Halt( 0 );%@NL@%
- %@AS@% END%@NL@%
- %@AS@% ELSE%@NL@%
- %@AS@% CASE vc.Adapter OF%@NL@%
- %@AS@% _MDPA, _HGC :%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'This program requires a color graphics adapter.' );%@NL@%
- %@AS@% Halt( 0 );%@NL@%
- %@AS@% END;%@NL@%
- %@AS@% _CGA, _OCGA : a := _SetVideoMode( _MRes4Color );%@NL@%
- %@AS@% _EGA, _OEGA : a := _SetVideoMode( _MRes16Color );%@NL@%
- %@AS@% _MCGA, _VGA : a := _SetVideoMode( _MRes256Color );%@NL@%
- %@AS@% END;%@NL@%
- %@AS@% { To get video configuration after mode is set }%@NL@%
- %@AS@% _GetVideoConfig( vc );%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD3103@%%@4@%This program fragment begins by calling %@AB@%_GetVideoConfig%@AE@%, which determines%@EH@%
- the graphics configuration and tells the type of adapter currently in use.
- If the monitor is monochrome, the program displays a message and halts.
- Next, the %@AB@%CASE%@AE@% statement enters the appropriate graphics mode. Finally, the
- program segment calls %@AB@%_GetVideoConfig%@AE@% to get the new configuration values
- after the mode has been set.%@NL@%
- %@NL@%
- %@CR:MQPD3104@%%@4@%To view every possible graphics mode, you can run the example program%@EH@%
- GRAPHIC.PAS, shown below. Sections 13.3.2%@BO: 6586d@%-13.3.6 explain the various
- graphics modes.%@NL@%
- %@NL@%
- %@AS@% PROGRAM graphic; { Displays every graphic mode }%@NL@%
- %@NL@%
- %@AS@% USES%@NL@%
- %@AS@% Crt, MSGraph;%@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% modes : ARRAY [0..11] OF Integer =%@NL@%
- %@AS@% (_MRes4Color, _MResNoColor, _HResBW, _HercMono,%@NL@%
- %@AS@% _MRes16Color, _HRes16Color, _EResNoColor, _EResColor,%@NL@%
- %@AS@% _VRes2Color, _VRes16Color, _MRes256Color, _OResColor );%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% vc : _VideoConfig;%@NL@%
- %@AS@% ch, key : Char;%@NL@%
- %@AS@% which : Char;%@NL@%
- %@AS@% a : Integer;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE print_menu;%@NL@%
- %@AS@% { Prints a menu on the screen }%@NL@%
- %@AS@% BEGIN%@NL@%
- %@NL@%
- %@AS@% Writeln( 'Please choose a graphics mode' );%@NL@%
- %@AS@% Writeln( 'Type "x" to exit' );%@NL@%
- %@AS@% Writeln;%@NL@%
- %@AS@% Writeln( '0 _MRES4COLOR' );%@NL@%
- %@AS@% Writeln( '1 _MRESNOCOLOR' );%@NL@%
- %@AS@% Writeln( '2 _HRESBW' );%@NL@%
- %@AS@% Writeln( '3 _HERCMONO' );%@NL@%
- %@AS@% Writeln( '4 _MRES16COLOR' );%@NL@%
- %@AS@% Writeln( '5 _HRES16COLOR' );%@NL@%
- %@AS@% Writeln( '6 _ERESNOCOLOR' );%@NL@%
- %@AS@% Writeln( '7 _ERESCOLOR' );%@NL@%
- %@AS@% Writeln( '8 _VRES2COLOR' );%@NL@%
- %@AS@% Writeln( '9 _VRES16COLOR' );%@NL@%
- %@AS@% Writeln( 'a _MRES256COLOR' );%@NL@%
- %@AS@% Writeln( 'b _ORESCOLOR' );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@NL@%
- %@AS@% PROCEDURE show_mode( which : Char );%@NL@%
- %@AS@% { Shows the different video modes. }%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% nc, i : Integer;%@NL@%
- %@AS@% height : Integer;%@NL@%
- %@AS@% width : Integer;%@NL@%
- %@AS@% mode : STRING;%@NL@%
- %@AS@% r : Real;%@NL@%
- %@AS@% e,m : Integer;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% mode := which;%@NL@%
- %@AS@% IF (mode < '0') OR (mode > '9') THEN%@NL@%
- %@AS@% IF mode = 'a' THEN%@NL@%
- %@AS@% mode := '10'%@NL@%
- %@AS@% ELSE IF mode = 'b' THEN%@NL@%
- %@AS@% mode := '11'%@NL@%
- %@AS@% ELSE Halt; { Exit procedure }%@NL@%
- %@AS@% Val( mode, r, e );%@NL@%
- %@AS@% m := Trunc( r );%@NL@%
- %@AS@% a := _SetVideoMode( modes[m] );%@NL@%
- %@AS@% IF (a <> 0) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _GetVideoConfig( vc );%@NL@%
- %@AS@% nc := vc.NumColors;%@NL@%
- %@AS@% width := vc.NumXPixels DIV nc;%@NL@%
- %@AS@% height := vc.NumYPixels DIV 2;%@NL@%
- %@AS@% FOR i := 1 TO ( nc - 1 ) DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _SetColor( i );%@NL@%
- %@AS@% _Rectangle( _GFillInterior, i * width,%@NL@%
- %@AS@% 0, ( i + 1 ) * width, height );%@NL@%
- %@AS@% END;%@NL@%
- %@AS@% END { IF a not equal to 0 }%@NL@%
- %@AS@% ELSE%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'Video mode ', which, ' is not available.' );%@NL@%
- %@AS@% Writeln( 'Please press ENTER.' );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% Readln; { Wait for ENTER to be pressed }%@NL@%
- %@AS@% a := _SetVideoMode( _DefaultMode );%@NL@%
- %@AS@% print_menu;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@NL@%
- %@AS@% BEGIN { Begin main program }%@NL@%
- %@NL@%
- %@AS@% key := ' ';%@NL@%
- %@AS@% _ClearScreen( _GClearScreen );%@NL@%
- %@AS@% print_menu;%@NL@%
- %@AS@% WHILE ( key <> 'x' ) DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% key := ReadKey;%@NL@%
- %@AS@% show_mode( key );%@NL@%
- %@AS@% END;%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD3200@%%@3@%%@AB@%13.3.2 CGA Color Graphics Modes%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD3201@%%@4@%The CGA color graphics modes %@AB@%_MRes4Color%@AE@% and %@AB@%_MResNoColor%@AE@% display four%@EH@%
- colors selected from one of several predefined palettes of colors. They
- display these foreground colors against a background color that can be any
- one of the 16 available colors. With the CGA hardware, the palette of
- foreground colors is predefined and cannot be changed. Each palette number
- is an integer as shown in Table 13.4%@BO: 65aa1@%.%@NL@%
- %@NL@%
- %@CR:MQPDT400@%%@4@%%@AB@%Table 13.4 Available CGA Colors%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Palette%@AE@% ┌────────────────%@AB@%Color Index%@AE@%────────────┐%@NL@%
- %@AB@%Number 1 2 3%@AE@%%@NL@%
- %@NL@%
- 0 Green Red Brown%@NL@%
- 1 Cyan Magenta Light Gray%@NL@%
- 2 Light Green Light Red Yellow%@NL@%
- 3 Light Cyan Light Magenta White%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD3202@%%@4@%The %@AB@%_MResNoColor%@AE@% graphics mode produces palettes containing various shades%@EH@%
- of gray on black-and-white monitors. The %@AB@%_MResNoColor%@AE@% mode displays colors
- when used with a color display. However, only two palettes are available
- with a color display. You can use the %@AB@%_SelectPalette%@AE@% function to select one
- of these predefined palettes. Table 13.5%@BO: 65e9f@% shows the correspondence between
- the color indexes and the palettes.%@NL@%
- %@NL@%
- %@CR:MQPDT500@%%@4@%%@AB@%Table 13.5 CGA Colors: _MResNoColor Mode%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Palette%@AE@% ┌────────────────%@AB@%Color Index%@AE@%────────────┐%@NL@%
- %@AB@%Number 1 2 3%@AE@%%@NL@%
- %@NL@%
- 0 Blue Red Light Gray%@NL@%
- 1 Light Blue Light Red White%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD3203@%%@4@%You may use the %@AB@%_SelectPalette%@AE@% function in conjunction with the %@AB@%_MRes4Color%@AE@%,%@EH@%
- %@AB@%_MResNoColor%@AE@%, and %@AB@%_OResColor%@AE@% graphics modes. To change palettes in other
- graphics modes, use the %@AB@%_RemapPalette%@AE@% or %@AB@%_RemapAllPalette%@AE@% routines.%@NL@%
- %@NL@%
- %@CR:MQPD3204@%%@4@%In %@AB@%_OResColor%@AE@% mode, you can choose one of 16 foreground colors by passing a%@EH@%
- value in the range 0-15 to the %@AB@%_SelectPalette%@AE@% function. The background color
- is always black.%@NL@%
- %@NL@%
- %@CR:MQPD3205@%%@4@%The following program sets the video mode to %@AB@%_MRes4Color%@AE@% and then cycles%@EH@%
- through background colors and palette combinations. It works on computers
- equipped with CGA, EGA, MCGA, or VGA cards. A color monitor is required.%@NL@%
- %@NL@%
- %@AS@% PROGRAM cga;%@NL@%
- %@AS@% { Demonstrates CGA colors }%@NL@%
- %@NL@%
- %@AS@% USES%@NL@%
- %@AS@% MSGraph;%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% bkcolor : ARRAY [0..7] OF LongInt = (_Black, _Blue, _Green, _Cyan,%@NL@%
- %@AS@% _Red, _Magenta, _Brown, _White);%@NL@%
- %@NL@%
- %@AS@% bkcolor_name : ARRAY [0..7] OF STRING = ('BLACK ', 'BLUE ',%@NL@%
- %@AS@% 'GREEN ', 'CYAN ', 'RED ', 'MAGENTA',%@NL@%
- %@AS@% 'BROWN ', 'WHITE ');%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% a, i, j, k : Integer;%@NL@%
- %@NL@%
- %@AS@% BEGIN { Begin main program }%@NL@%
- %@AS@% a := _SetVideoMode( _MRes4Color );%@NL@%
- %@AS@% FOR i := 0 TO 3 DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% a := _SelectPalette( i );%@NL@%
- %@AS@% FOR k := 0 TO 7 DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _SetBkColor( bkcolor[k] );%@NL@%
- %@AS@% FOR j := 0 TO 3 DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _SetTextPosition( 1, 1 );%@NL@%
- %@AS@% Writeln( 'Background color: ', bkcolor_name[k] );%@NL@%
- %@AS@% Writeln( ' Palette: ', i );%@NL@%
- %@AS@% Writeln( ' Number: ', j );%@NL@%
- %@AS@% _SetColor( j );%@NL@%
- %@AS@% _Rectangle( _GFillInterior, 160, 100, 320, 200 );%@NL@%
- %@AS@% Readln; { Wait for ENTER to be pressed }%@NL@%
- %@AS@% END; { for j }%@NL@%
- %@AS@% END; { for k }%@NL@%
- %@AS@% END; { for i }%@NL@%
- %@NL@%
- %@AS@% a := _SetVideoMode( _DefaultMode ); { restore original palette }%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD3300@%%@3@%%@AB@%13.3.3 EGA, MCGA, and VGA Palettes%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD3301@%%@4@%The beginning of this chapter mentioned the difference between color indexes%@EH@%
- and color values. An analogy might make things clearer. Imagine a painter
- who owns 64 tubes of paint and a painter's palette that has room for only 16
- globs of paint at any one time. A painting created under these constraints
- could contain only 16 colors (selected from a total of 64). The EGA graphics
- modes (such as %@AB@%_EResColor%@AE@%) are similar: they have 16 color indexes chosen
- from a total of 64 color values.%@NL@%
- %@NL@%
- %@CR:MQPD3302@%%@4@%The color values available in the EGA, MCGA, and VGA palettes are not%@EH@%
- predetermined like the CGA palettes. Instead, the color values available in
- EGA, MCGA, and VGA palettes are created by a process of "color mixing" of
- red, green, and blue elements. The next two sections describe color mixing.%@NL@%
- %@NL@%
- %@CR:MQPD3310@%%@4@%%@AB@%VGA Color Mixing%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD3311@%%@4@%VGA offers the widest variety of color values: 262,144 (256K). Depending on%@EH@%
- the graphics mode, the VGA palette size may be 2, 16, or 256. When you
- select a color value, you specify a level of intensity ranging from 0-63 for
- each of the red, green, and blue color values. The long integer that defines
- a color value consists of four bytes (32 bits):%@NL@%
- %@NL@%
- MSB LSB%@NL@%
- zzzzzzzz zzBBBBBB zzGGGGGG zzRRRRRR%@NL@%
- %@NL@%
- %@CR:MQPD3312@%%@4@%The most-significant byte must contain all zeros. The two high bits in the%@EH@%
- remaining three bytes must also be 0. To mix a light red (pink), turn red
- all the way up, and mix in some green and blue:%@NL@%
- %@NL@%
- 00000000 00100000 00100000 00111111%@NL@%
- %@NL@%
- %@CR:MQPD3313@%%@4@%To represent this value in hexadecimal, use the number %@AS@%$0020203F%@AE@%.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD3314@%%@4@%For white, turn all the elements on; for black, set all elements to 0.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD3320@%%@4@%%@AB@%EGA Color Mixing%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD3321@%%@4@%Mixing colors in EGA modes is similar to the mixing described above, but%@EH@%
- there are fewer intensities for the red, green, and blue components. In the
- modes that offer 64 colors, the R, G, and B values cover 2 bits and can
- range from 0-3. The long integer that defines an RGB color looks like this:%@NL@%
- %@NL@%
- MSB LSB%@NL@%
- zzzzzzzz zzBB???? zzGG???? zzRR????%@NL@%
- %@NL@%
- %@CR:MQPD3322@%%@4@%The bits marked %@AS@%z%@AE@% must be zeros and the bits marked with question marks can%@EH@%
- be any value. This format is used for compatibility with VGA color mixing.
- To form a pure red color value, you would use the constant %@AS@%$00000030%@AE@%. For
- cyan (blue plus green), use %@AS@%$00303000%@AE@%.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD3400@%%@3@%%@AB@%13.3.4 EGA Color Graphics Modes%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD3401@%%@4@%If you have an EGA adapter, you should use the video mode %@AB@%_MRes16Color%@AE@%,%@EH@%
- %@AB@%_HRes16Color%@AE@%, or %@AB@%_EResColor%@AE@% for the best color-graphics results. The CGA
- modes also display on the EGA but with the lower CGA resolution and
- decreased color options.%@NL@%
- %@NL@%
- %@CR:MQPD3402@%%@4@%The %@AB@%_RemapPalette%@AE@% function assigns a new color value to a color index. For%@EH@%
- example, when you first enter an EGA graphics mode, color index 1 equals the
- color value blue. To reassign the pure red color value to color index 1, you
- could use this line:%@NL@%
- %@NL@%
- %@AS@% a := _RemapPalette( 1, $000030 );%@NL@%
- %@NL@%
- %@CR:MQPD3403@%%@4@%Or, use the symbolic constant %@AB@%_Red%@AE@%, which is defined using the %@AB@%MSGraph%@AE@% unit:%@EH@%%@NL@%
- %@NL@%
- %@AS@% a := _RemapPalette( 1, _Red );%@NL@%
- %@NL@%
- %@CR:MQPD3404@%%@4@%After this function call, any object currently drawn in color index 1%@EH@%
- instantly switches from blue to red.%@NL@%
- %@NL@%
- %@CR:MQPD3405@%%@4@%The first value is an %@AB@%Integer%@AE@% in the range 0-15 and the second value is a%@EH@%
- %@AB@%LongInt%@AE@% defined as a mixture of red, green, and blue (you may also use
- symbolic constants such as %@AB@%_Red%@AE@%).%@NL@%
- %@NL@%
- %@CR:MQPD3406@%%@4@%The %@AB@%_RemapAllPalette%@AE@% procedure changes all of the color indexes%@EH@%
- simultaneously. You pass it an array of color values. The first color value
- in the list becomes the new color associated with the color index 0.%@NL@%
- %@NL@%
- %@CR:MQPD3407@%%@4@%The number in a function call that sets the color (such as %@AB@%_SetColor%@AE@%) is an%@EH@%
- index into the palette of available colors. In the default text palette, an
- index of 1 refers to blue but the palette could be remapped to change index
- 1 to any other available color. As a result, the color produced by that
- pixel value also changes. The number of color indexes depends on the number
- of colors supported by the current video mode.%@NL@%
- %@NL@%
- %@CR:MQPD3408@%%@4@%The %@AB@%_RemapPalette%@AE@% and %@AB@%_RemapAllPalette%@AE@% routines work in all modes but only%@EH@%
- with the EGA, MCGA, or VGA hardware. The %@AB@%_RemapPalette%@AE@% fails, returning a
- value of -1 when you attempt to remap a palette without the EGA, MCGA, or
- VGA hardware.%@NL@%
- %@NL@%
- %@CR:MQPD3409@%%@4@%The following program draws a rectangle with a red interior. In the default%@EH@%
- EGA palette, the color index 4 is red. This color index is changed to %@AB@%_Blue%@AE@%
- in this program.%@NL@%
- %@NL@%
- %@AS@% PROGRAM ega;%@NL@%
- %@AS@% { Demonstrates EGA/VGA palettes }%@NL@%
- %@NL@%
- %@AS@% USES%@NL@%
- %@AS@% MSGraph;%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% crlf = #13 + #10;%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% a : LongInt;%@NL@%
- %@AS@% m : Integer;%@NL@%
- %@NL@%
- %@AS@% BEGIN { Begin main program }%@NL@%
- %@NL@%
- %@AS@% m := _SetVideoMode( _MaxColorMode );%@NL@%
- %@AS@% _SetColor( 4 );%@NL@%
- %@AS@% _Rectangle( _GFillInterior, 50, 50, 150, 150 );%@NL@%
- %@NL@%
- %@AS@% _SetTextPosition( 1, 1 );%@NL@%
- %@AS@% _OutText( 'Normal palette' + crlf );%@NL@%
- %@AS@% _OutText( 'Press ENTER' );%@NL@%
- %@AS@% Readln;%@NL@%
- %@NL@%
- %@AS@% a := _RemapPalette( 4, _Blue );%@NL@%
- %@NL@%
- %@AS@% _SetTextPosition( 1, 1 );%@NL@%
- %@AS@% _OutText( 'Remapped palette' + crlf );%@NL@%
- %@AS@% _OutText( 'Press ENTER' );%@NL@%
- %@AS@% Readln;%@NL@%
- %@NL@%
- %@AS@% a := _RemapPalette( 4, _Red );%@NL@%
- %@NL@%
- %@AS@% _SetTextPosition( 1, 1 );%@NL@%
- %@AS@% _OutText( 'Restored palette' + crlf );%@NL@%
- %@AS@% _OutText( 'Press ENTER to clear the screen' );%@NL@%
- %@AS@% Readln;%@NL@%
- %@NL@%
- %@AS@% _ClearScreen( _GClearScreen );%@NL@%
- %@AS@% m := _SetVideoMode( _DefaultMode );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD3500@%%@3@%%@AB@%13.3.5 VGA Color Graphics Modes%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD3501@%%@4@%The VGA card adds graphics modes %@AB@%_VRes2Color%@AE@%, %@AB@%_VRes16Color%@AE@%, and%@EH@%
- %@AB@%_MRes256Color%@AE@% to your repertoire. EGA and CGA modes can also be used with
- the VGA hardware, but with either lower resolution or fewer color choices.%@NL@%
- %@NL@%
- %@CR:MQPD3502@%%@4@%The VGA color graphics modes operate with a range of 262,144 (256K) color%@EH@%
- values. The %@AB@%_VRes2Color%@AE@% graphics mode displays two colors, the %@AB@%_VRes16Color%@AE@%
- graphics mode displays 16 colors, and the %@AB@%_MRes256Color%@AE@% graphics mode
- displays 256 colors from the available VGA colors.%@NL@%
- %@NL@%
- %@CR:MQPD3503@%%@4@%The %@AB@%_RemapPalette%@AE@% function changes a color index to a specified color value.%@EH@%
- The function below remaps the color index 1 to the color value given by the
- symbolic constant %@AB@%_Red%@AE@% (which represents red). After this statement is
- executed, whatever was displayed as blue now appears as red:%@NL@%
- %@NL@%
- %@AS@% { reassign color index 1 to VGA red }%@NL@%
- %@AS@% a := _RemapPalette( 1, _Red );%@NL@%
- %@NL@%
- %@CR:MQPD3504@%%@4@%Use the %@AB@%_RemapAllPalette%@AE@% procedure to remap all of the available color%@EH@%
- indexes simultaneously. The procedure's argument references an array of
- color values that reflects the remapping. The first color number in the list
- becomes the new color associated with color index 0.%@NL@%
- %@NL@%
- %@CR:MQPD3505@%%@4@%Symbolic constants for the default color numbers are supplied so that the%@EH@%
- remapping of VGA colors is compatible with EGA practice. The names of these
- constants are self-explanatory. For example, the color numbers for black,
- red, and light yellow are represented by the symbolic constants %@AB@%_Black%@AE@%,
- %@AB@%_Red%@AE@%, and %@AB@%_Yellow%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQPD3506@%%@4@%All of the VGA display modes operate with any VGA video monitor. Colors are%@EH@%
- displayed as shades of gray when a monochrome analog display is connected.%@NL@%
- %@NL@%
- %@CR:MQPD3507@%%@4@%The program HORIZON.PAS illustrates what can be done with the range of 256%@EH@%
- colors if you have a VGA card:%@NL@%
- %@NL@%
- %@AS@% PROGRAM horizon; { Demonstrates VGA graphics with cycling of 256 colors}%@NL@%
- %@NL@%
- %@AS@% USES%@NL@%
- %@AS@% Crt, MSGraph;%@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% Red = $00002a;%@NL@%
- %@AS@% GRN = $002a00;%@NL@%
- %@AS@% BLU = $2a0000;%@NL@%
- %@AS@% WHT = $2a2a2a;%@NL@%
- %@AS@% step = 21;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% vc : _VideoConfig;%@NL@%
- %@AS@% rainbow : ARRAY [1..512] OF LongInt;%@NL@%
- %@AS@% i, a : Integer;%@NL@%
- %@AS@% col, gray : LongInt;%@NL@%
- %@AS@% rec : _XYCoord;%@NL@%
- %@NL@%
- %@AS@% BEGIN { Begin main program }%@NL@%
- %@AS@% a := _SetVideoMode( _MRes256Color );%@NL@%
- %@AS@% IF (a = 0) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'This program requires a VGA or MCGA card' );%@NL@%
- %@AS@% Halt( 0 );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% FOR col := 0 TO 63 DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% gray := col OR (col SHL 8) OR (col SHL 16);%@NL@%
- %@AS@% rainbow[col] := BLU AND gray;%@NL@%
- %@AS@% rainbow[col + 256] := BLU AND gray;%@NL@%
- %@AS@% rainbow[col + 64] := BLU OR gray;%@NL@%
- %@AS@% rainbow[col + 64 + 256] := BLU OR gray;%@NL@%
- %@AS@% rainbow[col + 128] := Red OR (WHT AND NOT gray);%@NL@%
- %@AS@% rainbow[col + 128 + 256] := Red OR (WHT AND NOT gray);%@NL@%
- %@AS@% rainbow[col + 192] := Red OR NOT gray;%@NL@%
- %@AS@% rainbow[col + 192 + 256] := Red OR NOT gray;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% _SetViewOrg( 160, 85, rec );%@NL@%
- %@NL@%
- %@AS@% FOR i := 0 TO 254 DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _SetColor( 255 - i );%@NL@%
- %@AS@% _MoveTo( i, i - 255 );%@NL@%
- %@AS@% _LineTo( -i, 255 - i );%@NL@%
- %@AS@% _MoveTo( -i, i - 255 );%@NL@%
- %@AS@% _LineTo( i, 255 - i );%@NL@%
- %@AS@% _Ellipse( _GBorder, -i, -i DIV 2, i, i DIV 2 );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% i := 0;%@NL@%
- %@AS@% WHILE NOT KeyPressed DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _RemapAllPalette( rainbow[i] );%@NL@%
- %@AS@% i := i + step;%@NL@%
- %@AS@% IF (i >= 256) THEN i := 0;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% a := _SetVideoMode( _DefaultMode );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD3600@%%@3@%%@AB@%13.3.6 Using the Color Video Text Modes%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD3601@%%@4@%All video adapters offer support for video text modes (%@AB@%_TextC40%@AE@%,%@EH@%
- %@AB@%_TextC80%@AE@%, %@AB@%_TextBW40%@AE@%, %@AB@%_TextBW80%@AE@%, %@AB@%_TextMono%@AE@% ). Using the video text modes, you
- can display color text without having to enter a graphics mode. On a color
- monitor, you can display normal or blinking text in any of 16 foreground
- colors with any of 8 background colors. On a monochrome monitor, you can
- specify text "colors" in exactly the same way, although the color values are
- interpreted differently by the hardware.%@NL@%
- %@NL@%
- %@CR:MQPD3602@%%@4@%The text procedures and functions described in this section can be used in%@EH@%
- the video text modes as well as in all of the graphics modes.%@NL@%
- %@NL@%
- %@CR:MQPD3610@%%@4@%%@AB@%Selecting Text Colors%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD3611@%%@4@%In a video text mode, each displayed character requires two bytes of video%@EH@%
- memory. The first byte contains the ASCII code representing the character
- and the second byte contains the display attribute. In the CGA color video
- text modes, the attribute byte determines the color and whether it will
- blink. Sixteen colors are available: the CGA indexes, and the default EGA
- and VGA indexes. Since the EGA and VGA palettes can be remapped, these
- values can be made to correspond to any set of 16 colors with the
- appropriate palette mapping.%@NL@%
- %@NL@%
- %@CR:MQPD3620@%%@4@%%@AB@%Using Text Colors%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD3621@%%@4@%Use the %@AB@%_GetTextColor%@AE@% and %@AB@%_GetBkColor%@AE@% functions to find foreground and%@EH@%
- background colors of the current text.%@NL@%
- %@NL@%
- %@CR:MQPD3622@%%@4@%Values in the range 0-15 are interpreted as normal color. Values in the%@EH@%
- range 16-31 are the same colors as those in the range 0-15 but with blinking
- text.%@NL@%
- %@NL@%
- %@CR:MQPD3623@%%@4@%Set the foreground and background colors in a video text mode with the%@EH@%
- %@AB@%_SetTextColor%@AE@% and %@AB@%_SetBkColor%@AE@% functions. These functions use a single
- argument that specifies the index to be used for text displayed with the
- %@AB@%_OutText%@AE@% procedure. The color indexes for color video text modes are defined
- in Table 13.6%@BO: 6a0ff@%.%@NL@%
- %@NL@%
- %@CR:MQPDT600@%%@4@%%@AB@%Table 13.6 Text Colors%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Number Color Number Color%@AE@%%@NL@%
- %@NL@%
- 0 Black 8 Gray%@NL@%
- 1 Blue 9 Light Blue%@NL@%
- 2 Green 10 Light Green%@NL@%
- 3 Cyan 11 Light Cyan%@NL@%
- 4 Red 12 Light Red%@NL@%
- 5 Magenta 13 Light Magenta%@NL@%
- 6 Brown 14 Yellow%@NL@%
- 7 White 15 Light White%@NL@%
- %@NL@%
- %@CR:MQPD3624@%%@4@%On monochrome displays, you can select text attributes in the same way as%@EH@%
- for color displays. For underlined text, use Blue or Light Blue. For
- highlighted text, use any color from Light Green to White. For blinking
- text, add 16 to the color constant.%@NL@%
- %@NL@%
- %@CR:MQPD3630@%%@4@%%@AB@%Displaying Text Colors%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD3631@%%@4@%The %@AB@%_SetTextPosition%@AE@% procedure moves the cursor to a row and column for%@EH@%
- displaying color text. The %@AB@%_OutText%@AE@% procedure displays the text.%@NL@%
- %@NL@%
- %@CR:MQPD3632@%%@4@%The following program displays a chart showing all possible combinations of%@EH@%
- text and background colors:%@NL@%
- %@NL@%
- %@AS@% PROGRAM coltext; { Displays text in color }%@NL@%
- %@NL@%
- %@AS@% USES%@NL@%
- %@AS@% Crt, MSGraph;%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% message1, s, t : STRING;%@NL@%
- %@AS@% blink, fgd, bgd : Integer;%@NL@%
- %@AS@% a : Integer;%@NL@%
- %@NL@%
- %@AS@% BEGIN { Begin main program }%@NL@%
- %@NL@%
- %@AS@% _ClearScreen( _GClearScreen );%@NL@%
- %@AS@% _OutText( 'Color text attributes:' );%@NL@%
- %@NL@%
- %@AS@% FOR blink := 0 TO 1 DO%@NL@%
- %@AS@% FOR bgd := 0 TO 6 DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _SetBkColor( bgd );%@NL@%
- %@AS@% _SetTextPosition( bgd + (blink * 9) + 3, 1 );%@NL@%
- %@AS@% _SetTextColor( 7 );%@NL@%
- %@AS@% Str( bgd, s );%@NL@%
- %@AS@% message1 := 'Bgd: ';%@NL@%
- %@AS@% _OutText( message1 );%@NL@%
- %@AS@% _OutText( s );%@NL@%
- %@AS@% s := s + ' ';%@NL@%
- %@AS@% message1 := ' Fgd: ';%@NL@%
- %@AS@% _OutText( message1 );%@NL@%
- %@AS@% FOR fgd := 0 TO 15 DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _SetTextColor( fgd + (blink*16) );%@NL@%
- %@AS@% a := fgd + (blink*16);%@NL@%
- %@AS@% Str( a, s );%@NL@%
- %@AS@% s := s + ' ';%@NL@%
- %@AS@% _OutText( s );%@NL@%
- %@AS@% END;%@NL@%
- %@AS@% END; { FOR loops }%@NL@%
- %@NL@%
- %@AS@% REPEAT UNTIL KeyPressed;%@NL@%
- %@AS@% a := _SetVideoMode( _DefaultMode );%@NL@%
- %@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD4000@%%@2@%%@AB@%13.4 Understanding Coordinate Systems%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4001@%%@4@%Before you can write a program to print a word or to display graphics on the%@EH@%
- screen, you need a system that describes exactly where to print or display
- the item.%@NL@%
- %@NL@%
- %@CR:MQPD4002@%%@4@%QuickPascal provides several coordinate systems. The physical coordinate%@EH@%
- system has already been used in the program 1STGRAPH.PAS. This section
- discusses the four coordinate systems supported by QuickPascal and shows how
- to translate between systems.%@NL@%
- %@NL@%
- %@CR:MQPD4003@%%@4@%The coordinate systems supported by QuickPascal are:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4004@% ■ Text coordinates%@NL@%
- %@NL@%
- ■ Physical coordinates%@NL@%
- %@NL@%
- ■ Viewport coordinates%@NL@%
- %@NL@%
- ■ Real coordinates in a window%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD4100@%%@3@%%@AB@%13.4.1 Text Coordinates%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4101@%%@4@%QuickPascal divides the text screen into rows and columns. See Figure 13.1%@EH@%%@FN@%
- Figure 13.1 is found on page 193 in the printed version of this book.%@EF@%.%@NL@%
- %@NL@%
- %@CR:MQPD4102@%%@4@%Two important conventions to keep in mind about video text mode are:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4103@% 1. Numbering starts at 1, not 0. An 80-column screen contains columns%@NL@%
- 1-80.%@NL@%
- %@NL@%
- 2. The row is always listed before the column.%@NL@%
- %@NL@%
- %@CR:MQPD4104@%%@4@%If the screen is in a video text mode that displays 25 rows and 80 columns%@EH@%
- (as in Figure 13.1%@FN@%
- Figure 13.1 is found on page 193 in the printed version of this book.%@EF@%), the rows are numbered 1-25 and the columns are
- numbered 1-80. In routines such as %@AB@%_SetTextPosition%@AE@%, which is called in the
- next example program, the parameters you pass are row and column (in that
- order). Some monitors (such as the EGA or VGA) support more than 25 text
- rows. For these monitors, use the %@AB@%_SetVideoModeRows%@AE@% or %@AB@%_SetTextRows%@AE@%
- functions to specify the number of rows to display.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD4200@%%@3@%%@AB@%13.4.2 Physical Screen Coordinates%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4201@%%@4@%Suppose you write a program that calls %@AB@%_SetVideoMode%@AE@% and puts the screen%@EH@%
- into the VGA graphics mode %@AB@%_VRes16Color%@AE@%. This gives you a screen containing
- 640 horizontal pixels and 480 vertical pixels. The individual pixels are
- named by their location relative to the %@AI@%x%@AE@% axis and %@AI@%y%@AE@% axis, as shown in
- Figure 13.2%@FN@%
- Figure 13.2 is found on page 194 in the printed version of this book.%@EF@%. Two important differences between text coordinates and graphics
- coordinates are:%@NL@%
- %@NL@%
- %@CR:MQPD4202@% 1. Numbering starts at 0, not 1. If there are 640 pixels, they're%@NL@%
- numbered 0-639.%@NL@%
- %@NL@%
- 2. The %@AI@%x%@AE@% coordinate is listed before the %@AI@%y%@AE@% coordinate.%@NL@%
- %@NL@%
- %@CR:MQPD4203@%%@4@%The upper left corner is called the "origin." The %@AI@%x%@AE@% and %@AI@%y%@AE@% coordinates for%@EH@%
- the origin are always (0, 0). If you use variables to refer to pixel
- locations, declare them as integers. The "viewport" is the region where
- graphics will be displayed.%@NL@%
- %@NL@%
- %@CR:MQPD4210@%%@4@%%@AB@%Changing the Origin with _SetViewOrg%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4211@%%@4@%The %@AB@%_SetViewOrg%@AE@% procedure changes the location of the viewport's origin. You%@EH@%
- pass two integers, which represent the %@AI@%x%@AE@% and %@AI@%y%@AE@% coordinates of a physical
- screen location. For example, the following line would move the origin to
- the physical screen location (50, 100):%@NL@%
- %@NL@%
- %@AS@% _SetViewOrg( 50, 100, xyorg );%@NL@%
- %@NL@%
- %@CR:MQPD4212@%%@4@%The effect on the screen is illustrated in Figure 13.3%@EH@%%@FN@%
- Figure 13.3 is found on page 195 in the printed version of this book.%@EF@%.%@NL@%
- %@NL@%
- %@CR:MQPD4213@%%@4@%The number of pixels hasn't changed, but the names given to the points have%@EH@%
- changed. The %@AI@%x%@AE@% axis now ranges from -50 to +589 instead of 0 to 639. The %@AI@%y%@AE@%
- axis now covers the values -100 to +379. (If you own an adapter other than
- the VGA, the numbers are different but the effect is the same.) All standard
- graphics functions and procedures are affected by the new origin, including
- %@AB@%_MoveTo%@AE@%, %@AB@%_LineTo%@AE@%, %@AB@%_Rectangle%@AE@%, %@AB@%_Ellipse%@AE@%, %@AB@%_Arc%@AE@%, and %@AB@%_Pie%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQPD4214@%%@4@%For example, if you call the %@AB@%_Rectangle%@AE@% procedure after relocating the%@EH@%
- viewport origin, and pass it the coordinate values (0, 0) and (40, 40), the
- rectangle would be drawn 50 pixels from the left edge of the screen and 100
- pixels from the top. It would not appear in the upper left corner.%@NL@%
- %@NL@%
- %@CR:MQPD4215@%%@4@%The values passed to %@AB@%_SetViewOrg%@AE@% are always physical screen locations.%@EH@%
- Suppose you called the same procedure twice:%@NL@%
- %@NL@%
- %@AS@% _SetViewOrg( 50, 100, xyorg );%@NL@%
- %@AS@% _SetViewOrg( 50, 100, xyorg );%@NL@%
- %@NL@%
- %@CR:MQPD4216@%%@4@%The viewport origin would %@AI@%not%@AE@% move to (100, 200). It would remain at the%@EH@%
- physical screen location (50, 100).%@NL@%
- %@NL@%
- %@CR:MQPD4220@%%@4@%%@AB@%Defining a Clipping Region with _SetClipRgn%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4221@%%@4@%The %@AB@%_SetClipRgn%@AE@% procedure creates an invisible rectangular area on the%@EH@%
- screen called a "clipping region." Attempts to draw inside the clipping
- region are successful, while attempts to draw outside the region are not.%@NL@%
- %@NL@%
- %@CR:MQPD4222@%%@4@%When you first enter a graphics mode, the default clipping region is the%@EH@%
- entire screen. QuickPascal ignores any attempts to draw outside the clipping
- region.%@NL@%
- %@NL@%
- %@CR:MQPD4223@%%@4@%Changing the clipping region requires one call to %@AB@%_SetClipRgn%@AE@%. Suppose%@EH@%
- you've entered the CGA graphics mode %@AB@%_MRes4Color%@AE@%, which has a screen
- resolution of 320 x 200. If you draw a diagonal line from the top left to
- the bottom right corner, the screen looks like Figure 13.4%@FN@%
- Figure 13.4 is found on page 196 in the printed version of this book.%@EF@%. You could
- create a clipping region with the following:%@NL@%
- %@NL@%
- %@AS@% _SetClipRgn( 10, 10, 309, 189 );%@NL@%
- %@NL@%
- %@CR:MQPD4224@%%@4@%Then draw a line with the statement:%@EH@%%@NL@%
- %@NL@%
- %@AS@% _LineTo( 0, 0, 319, 199 );%@NL@%
- %@NL@%
- %@CR:MQPD4225@%%@4@%With the clipping region in effect, the same %@AB@%_LineTo%@AE@% command given above%@EH@%
- would put the line shown in Figure 13.5%@FN@%
- Figure 13.5 is found on page 197 in the printed version of this book.%@EF@% on the screen.%@NL@%
- %@NL@%
- %@CR:MQPD4226@%%@4@%The broken lines don't actually appear on the screen. They indicate the%@EH@%
- outer bounds of the clipping region.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD4300@%%@3@%%@AB@%13.4.3 Viewport Coordinates%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4301@%%@4@%Viewport coordinates are yet another coordinate system supported by%@EH@%
- QuickPascal. You can establish a new viewport within the boundaries of the
- physical screen by using the %@AB@%_SetViewport%@AE@% procedure. A standard viewport has
- two distinguishing features:%@NL@%
- %@NL@%
- %@CR:MQPD4302@% 1. The origin of a viewport is in the upper left corner.%@NL@%
- %@NL@%
- 2. The clipping region matches the outer boundaries of the viewport.%@NL@%
- %@NL@%
- %@CR:MQPD4303@%%@4@%The %@AB@%_SetViewport%@AE@% procedure does the same thing as calling %@AB@%_SetViewOrg%@AE@% and%@EH@%
- %@AB@%_SetClipRgn%@AE@% together.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD4400@%%@3@%%@AB@%13.4.4 Real Coordinates in a Window%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4401@%%@4@%QuickPascal supports a system of real coordinates for use in a window. This%@EH@%
- system lets you use floating-point values in graphics.%@NL@%
- %@NL@%
- %@CR:MQPD4402@%%@4@%Functions and procedures that refer to coordinates on the physical screen%@EH@%
- and within the viewport require integer values. However, in real-life
- graphing applications, you might wish to use floating-point values──stock
- prices, the price of wheat, average rainfall, and so on.%@NL@%
- %@NL@%
- %@CR:MQPD4410@%%@4@%%@AB@%Setting Window Coordinates%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4411@%%@4@%The %@AB@%_SetWindow%@AE@% procedure allows you to scale the screen to almost any size.%@EH@%
- In addition, the window-related functions and procedures take
- double-precision floating-point values instead of integers.%@NL@%
- %@NL@%
- %@CR:MQPD4412@%%@4@%If, for example, you wanted to graph 12 months of average temperatures that%@EH@%
- range from -40 to +100, you could add the following line to your program:%@NL@%
- %@NL@%
- %@AS@%_SetWindow( TRUE, 1.0, -40.0, 12.0, 100.0 );%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPD4413@%%@4@%The first argument is the invert flag, which puts the lowest %@AI@%y%@AE@% value in the%@EH@%
- bottom left corner. The minimum and maximum Cartesian coordinates follow
- (the decimal point marks them as floating-point values). The new
- organization of the screen is shown in Figure 13.6%@FN@%
- Figure 13.6 is found on page 198 in the printed version of this book.%@EF@%.%@NL@%
- %@NL@%
- %@CR:MQPD4414@%%@4@%This procedure makes the temperatures for January and December appear on the%@EH@%
- left and right edges of the screen. In an application like this, it might be
- better to number the %@AI@%x%@AE@% axis from 0.0 to 13.0, to provide some extra space.%@NL@%
- %@NL@%
- %@CR:MQPD4415@%%@4@%If you plot a point with %@AB@%_SetPixel_w%@AE@% or draw a line with %@AB@%_LineTo_w%@AE@%, the%@EH@%
- values are automatically scaled to the established window. You can also find
- the position of the graphics cursor at any time with
- %@AB@%_GetCurrentPosition_wxy%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQPD4420@%%@4@%%@AB@%Programming Real-Coordinate Graphics%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4421@%%@4@%The four steps to using real-coordinate graphics are:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4422@% 1. Enter a graphics mode with %@AB@%_SetVideoMode%@AE@%.%@NL@%
- %@NL@%
- 2. Use %@AB@%_SetViewPort%@AE@% to create a viewport area. This step is optional if%@NL@%
- you plan to use the entire screen.%@NL@%
- %@NL@%
- 3. Create a real-coordinate window with %@AB@%_SetWindow%@AE@%, passing a Boolean%@NL@%
- invert flag and four %@AB@%Double%@AE@% %@AI@%x%@AE@% and %@AI@%y%@AE@% coordinates for the minimum and%@NL@%
- maximum values.%@NL@%
- %@NL@%
- 4. Draw graphics shapes with %@AB@%_Rectangle_w%@AE@% and other procedures. Do not%@NL@%
- confuse %@AB@%_Rectangle%@AE@% (the viewport procedure) with %@AB@%_Rectangle_w%@AE@% (the%@NL@%
- window procedure for drawing rectangles). All window procedures end%@NL@%
- with an underscore and a letter %@AB@%w%@AE@% or an underscore and %@AB@%wxy%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQPD4423@%%@4@%Real-coordinate graphics can give you a lot of flexibility. For example, you%@EH@%
- can fit either axis into a small range (such as 151.25 to 151.45) or into a
- large range (-50,000 to +80,000), depending on the type of data you're
- graphing. In addition, by changing the window coordinates, you can create
- the effects of zooming in or panning across a figure.%@NL@%
- %@NL@%
- %@CR:MQPD4430@%%@4@%%@AB@%An Example of Real-Coordinate Graphics%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4431@%%@4@%The program below illustrates how to use the real-coordinate window%@EH@%
- routines.%@NL@%
- %@NL@%
- %@AS@% PROGRAM realg; { Example of real-coordinate graphics }%@NL@%
- %@AS@% USES%@NL@%
- %@AS@% MsGraph, Crt;%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% bananas : ARRAY[0..20] OF Single =%@NL@%
- %@AS@% (%@NL@%
- %@AS@% -0.3, -0.2, -0.224, -0.1, -0.5, +0.21, +2.9,%@NL@%
- %@AS@% +0.3, +0.2, 0.0, -0.885, -1.1, -0.3, -0.2,%@NL@%
- %@AS@% 0.001, 0.005, 0.14, 0.0, -0.9, -0.13, +0.3%@NL@%
- %@AS@% );%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% halfx, halfy,%@NL@%
- %@AS@% a : Integer;%@NL@%
- %@AS@% vc : _VideoConfig;%@NL@%
- %@AS@% ch : Char;%@NL@%
- %@NL@%
- %@AS@% FUNCTION four_colors : Boolean;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% four_colors := False;%@NL@%
- %@AS@% IF (_SetVideoMode( _MaxColorMode ) > 0) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _GetVideoConfig( vc );%@NL@%
- %@AS@% IF (vc.NumColors >= 4) THEN%@NL@%
- %@AS@% four_colors := True;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE grid_shape;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% i, x1, y1, x2, y2 : Integer;%@NL@%
- %@AS@% x, y : Real;%@NL@%
- %@AS@% s : STRING[80];%@NL@%
- %@AS@% BEGIN%@NL@%
- %@NL@%
- %@AS@% FOR i := 1 TO vc.NumColors DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _SetTextPosition( i, 2 );%@NL@%
- %@AS@% _SetTextColor( i );%@NL@%
- %@AS@% Str( i, s );%@NL@%
- %@AS@% _OutText( 'Color ' + s );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% _SetColor( 1 );%@NL@%
- %@AS@% _Rectangle_w( _GBorder, -1.0, -1.0, 1.0, 1.0 );%@NL@%
- %@AS@% _Rectangle_w( _GBorder, -1.02, -1.02, 1.02, 1.02 );%@NL@%
- %@NL@%
- %@AS@% x := -0.9;%@NL@%
- %@AS@% i := 0;%@NL@%
- %@AS@% WHILE x < 0.9 DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _SetColor( 2 );%@NL@%
- %@AS@% _MoveTo_w( x, -1.0 ); _LineTo_w( x, 1.0 );%@NL@%
- %@AS@% _MoveTo_w( -1.0, x ); _LineTo_w( 1.0, x );%@NL@%
- %@AS@% _SetColor( 3 );%@NL@%
- %@AS@% _MoveTo_w( x - 0.1, bananas[i] );%@NL@%
- %@AS@% Inc( i );%@NL@%
- %@AS@% _LineTo_w( x, bananas[i] );%@NL@%
- %@AS@% x := x + 0.1;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% _MoveTo_w( 0.9, bananas[i] );%@NL@%
- %@AS@% Inc(i);%@NL@%
- %@AS@% _LineTo_w( 1.0, bananas[i] );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE three_graphs;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% upleft, botright : _WXYCoord;%@NL@%
- %@AS@% xwidth, yheight, cols, rows : Integer;%@NL@%
- %@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _ClearScreen( _GClearScreen );%@NL@%
- %@AS@% xwidth := vc.NumXPixels;%@NL@%
- %@AS@% yheight := vc.NumYPixels;%@NL@%
- %@AS@% halfx := xwidth DIV 2;%@NL@%
- %@AS@% halfy := yheight DIV 2;%@NL@%
- %@AS@% cols := vc.NumTextCols;%@NL@%
- %@AS@% rows := vc.NumTextRows;%@NL@%
- %@NL@%
- %@AS@% { first window }%@NL@%
- %@AS@% _SetViewport( 0, 0, halfx-1, halfy-1 );%@NL@%
- %@AS@% _SetTextWindow( 1, 1, rows DIV 2, cols DIV 2 );%@NL@%
- %@AS@% _SetWindow( False, -2.0, -2.0, 2.0, 2.0 );%@NL@%
- %@AS@% grid_shape;%@NL@%
- %@AS@% _Rectangle( _GBorder, 0, 0, halfx-1, halfy-1 );%@NL@%
- %@NL@%
- %@AS@% { second window }%@NL@%
- %@AS@% _SetViewport( halfx, 0, xwidth-1, halfy-1 );%@NL@%
- %@AS@% _SetTextWindow( 1, cols DIV 2+1, rows DIV 2, cols );%@NL@%
- %@AS@% _SetWindow( False, -3.0, -3.0, 3.0, 3.0 );%@NL@%
- %@AS@% grid_shape;%@NL@%
- %@AS@% _Rectangle_w( _GBorder, -3.0, -3.0, 3.0, 3.0 );%@NL@%
- %@NL@%
- %@AS@% { third window }%@NL@%
- %@AS@% _SetViewport( 0, halfy, xwidth-1, yheight-1 );%@NL@%
- %@AS@% _SetTextWindow( rows DIV 2+2, 1, rows, cols );%@NL@%
- %@AS@% _SetWindow( True, -3.0, -1.5, 1.5, 1.5 );%@NL@%
- %@AS@% grid_shape;%@NL@%
- %@AS@% upleft.wx := -3.0;%@NL@%
- %@AS@% upleft.wy := -1.5;%@NL@%
- %@AS@% botright.wx := 1.5;%@NL@%
- %@AS@% botright.wy := 1.5;%@NL@%
- %@AS@% _Rectangle_wxy( _GBorder, upleft, botright);%@NL@%
- %@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% BEGIN { main program }%@NL@%
- %@NL@%
- %@AS@% IF four_colors THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _OutText( 'This program requires a CGA, EGA, or VGA graphics card' );%@NL@%
- %@AS@% three_graphs;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% ch := ReadKey;%@NL@%
- %@AS@% a := _SetVideoMode( _DefaultMode );%@NL@%
- %@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQPD4432@%%@4@%The main body of the program is short. It calls the %@AS@%four_colors%@AE@% function%@EH@%
- (defined below), which attempts to enter a graphics mode in which at least
- four colors are available. If it succeeds, the %@AS@%three_graphs%@AE@% function is
- called. This function uses the numbers in the %@AS@%bananas%@AE@% array to draw three
- graphs. The REALG.PAS screen output is shown in Figure 13.7%@FN@%
- Figure 13.7 is found on page 202 in the printed version of this book.%@EF@%.%@NL@%
- %@NL@%
- %@CR:MQPD4433@%%@4@%It's worth noting that the graphs are all drawn using the same numbers.%@EH@%
- However, the program uses three different real-coordinate windows. The two
- windows in the top half are the same size in physical coordinates, but they
- have different window sizes. In all three cases, the grid is two units wide.
- In the upper left corner, the window is four units wide; in the upper right,
- the window is six units wide, which makes the graph appear smaller.%@NL@%
- %@NL@%
- %@CR:MQPD4434@%%@4@%In two of the three graphs, one of the lines goes off the edge, outside the%@EH@%
- clipping region. The lines do not intrude into the other windows, since
- defining a window creates a clipping region.%@NL@%
- %@NL@%
- %@CR:MQPD4435@%%@4@%Finally, note that the graph on the bottom of the screen seems to be upside%@EH@%
- down with respect to the two graphs above it. This is the result of setting
- the invert flag to %@AB@%True%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQPD4440@%%@4@%%@AB@%Entering a Graphics Mode%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4441@%%@4@%The first step in any graphics program is to enter a graphics mode. The%@EH@%
- function %@AS@%four_colors%@AE@% performs this step:%@NL@%
- %@NL@%
- %@AS@% FUNCTION four_colors : Boolean;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% four_colors := False;%@NL@%
- %@AS@% IF (_SetVideoMode( _MaxColorMode ) > 0) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _GetVideoConfig( vc );%@NL@%
- %@AS@% IF (vc.NumColors >= 4) THEN%@NL@%
- %@AS@% four_colors := True;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD4442@%%@4@%The %@AB@%_GetVideoConfig%@AE@% procedure places some information into the structure%@EH@%
- %@AB@%_VideoConfig%@AE@% called %@AS@%screen%@AE@%. Then you use the member %@AS@%screen.adapter%@AE@% of the
- %@AB@%_VideoConfig%@AE@% structure in a %@AB@%CASE%@AE@% statement construct to turn on the matching
- graphics mode. The symbolic constants %@AB@%_CGA%@AE@% and the rest are defined in the
- %@AB@%MSGraph%@AE@% unit. The modes containing the letter "O" are Olivetti modes.%@NL@%
- %@NL@%
- %@CR:MQPD4443@%%@4@%If the computer is equipped with a color card, this function returns a %@AB@%True%@AE@%.%@EH@%
- If it is not, it returns a %@AB@%False%@AE@%, which causes the program to skip the
- function %@AS@%three_graphs%@AE@% and to end the program.%@NL@%
- %@NL@%
- %@CR:MQPD4444@%%@4@%If the %@AS@%four_colors%@AE@% function works properly, the program calls the function%@EH@%
- below, which prints the three graphs.%@NL@%
- %@NL@%
- %@AS@% PROCEDURE three_graphs;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% upleft, botright : _WXYCoord;%@NL@%
- %@AS@% xwidth, yheight, cols, rows : Integer;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _ClearScreen( _GClearScreen );%@NL@%
- %@AS@% xwidth := vc.NumXPixels;%@NL@%
- %@AS@% yheight := vc.NumYPixels;%@NL@%
- %@AS@% halfx := xwidth DIV 2;%@NL@%
- %@AS@% halfy := yheight DIV 2;%@NL@%
- %@AS@% cols := vc.NumTextCols;%@NL@%
- %@AS@% rows := vc.NumTextRows;%@NL@%
- %@NL@%
- %@NL@%
- %@AS@% { first window }%@NL@%
- %@AS@% _SetViewport( 0, 0, halfx-1, halfy-1 );%@NL@%
- %@AS@% _SetTextWindow( 1, 1, rows DIV 2, cols DIV 2 );%@NL@%
- %@AS@% _SetWindow( False, -2.0, -2.0, 2.0, 2.0 );%@NL@%
- %@AS@% grid_shape;%@NL@%
- %@AS@% _Rectangle( _GBorder, 0, 0, halfx-1, halfy-1 );%@NL@%
- %@NL@%
- %@AS@% { second window }%@NL@%
- %@AS@% _SetViewport( halfx, 0, xwidth-1, halfy-1 );%@NL@%
- %@AS@% _SetTextWindow( 1, cols DIV 2+1, rows DIV 2, cols );%@NL@%
- %@AS@% _SetWindow( False, -3.0, -3.0, 3.0, 3.0 );%@NL@%
- %@AS@% grid_shape;%@NL@%
- %@AS@% _Rectangle_w( _GBorder, -3.0, -3.0, 3.0, 3.0 );%@NL@%
- %@NL@%
- %@AS@% { third window }%@NL@%
- %@AS@% _SetViewport( 0, halfy, xwidth-1, yheight-1 );%@NL@%
- %@AS@% _SetTextWindow( rows DIV 2+2, 1, rows, cols );%@NL@%
- %@AS@% _SetWindow( True, -3.0, -1.5, 1.5, 1.5 );%@NL@%
- %@AS@% grid_shape;%@NL@%
- %@AS@% upleft.wx := -3.0;%@NL@%
- %@AS@% upleft.wy := -1.5;%@NL@%
- %@AS@% botright.wx := 1.5;%@NL@%
- %@AS@% botright.wy := 1.5;%@NL@%
- %@AS@% _Rectangle_wxy( _GBorder, upleft, botright);%@NL@%
- %@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQPD4450@%%@4@%%@AB@%Working with Windows%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4451@%%@4@%Although entering a graphics mode automatically clears the screen, it%@EH@%
- doesn't hurt to be sure, so %@AS@%three_graphs%@AE@% calls the %@AB@%_ClearScreen%@AE@% procedure:%@NL@%
- %@NL@%
- %@AS@% _ClearScreen( _GClearScreen );%@NL@%
- %@NL@%
- %@CR:MQPD4452@%%@4@%The %@AB@%_GClearScreen%@AE@% constant causes the entire physical screen to clear.%@EH@%
- Other options include %@AB@%_GViewport%@AE@% and %@AB@%_GWindow%@AE@%, which clear the current
- viewport and the current text window, respectively.%@NL@%
- %@NL@%
- %@4@%%@AB@%The First Window%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@4@%After assigning values to some variables, the procedure %@AS@%three_graphs%@AE@%%@EH@%
- creates the first window:%@NL@%
- %@NL@%
- %@AS@% _SetViewPort( 0, 0, halfx - 1, halfy - 1 );%@NL@%
- %@AS@% _SetTextWindow( 1, 1, rows / 2, cols / 2 );%@NL@%
- %@AS@% _SetWindow( False, -2.0, -2.0, 2.0, 2.0 );%@NL@%
- %@NL@%
- %@4@%First a viewport is defined to cover the upper left quarter of the screen.%@EH@%
- Next, a text window is defined within the boundaries of that border. (Note
- the numbering starts at 1 and the row location precedes the column.)
- Finally, a window is defined. The %@AB@%False%@AE@% constant forces the %@AI@%y%@AE@% axis to
- increase from top to bottom. The corners of the window are (-2.0, -2.0) in
- the upper left and (2.0, 2.0) in the bottom right corner.%@NL@%
- %@NL@%
- %@CR:MQPD4453@%%@4@%Next, the function %@AS@%grid_shape%@AE@% is called, and a border is added to the%@EH@%
- window:%@NL@%
- %@NL@%
- %@AS@% grid_shape;%@NL@%
- %@AS@% _Rectangle( _GBorder, 0, 0, halfx-1, halfy-1 );%@NL@%
- %@NL@%
- %@CR:MQPD4454@%%@4@%Note that this is the standard %@AB@%_Rectangle%@AE@% procedure, which takes coordinates%@EH@%
- relative to the viewport (%@AI@%not%@AE@% window coordinates).%@NL@%
- %@NL@%
- %@CR:MQPD4455@%%@4@%%@AB@%Two More Windows%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4456@%%@4@%The two other windows are similar to the first. All three call %@AS@%grid_shape%@AE@%%@EH@%
- (defined below), which draws a grid from location (-1.0, -1.0) to (+1.0,
- +1.0). The grid appears in different sizes because the coordinates in the
- windows vary. The second window ranges from (-3.0, -3.0) to (+3.0, +3.0),
- so the width of the grid is one-third the width of the second window, while
- it is one-half the width of the first.%@NL@%
- %@NL@%
- %@CR:MQPD4457@%%@4@%Note also that the third window contains %@AB@%True%@AE@% as the first argument. This%@EH@%
- causes the %@AI@%y%@AE@% axis to increase from bottom to top, instead of top to bottom.
- As a result, this graph appears to be upside down in relation to the other
- two.%@NL@%
- %@NL@%
- %@CR:MQPD4458@%%@4@%After calling %@AS@%grid_shape%@AE@%, the program frames each window with one of the%@EH@%
- following procedures:%@NL@%
- %@NL@%
- %@AS@% _Rectangle( _GBorder, 0, 0, halfx -1, halfy -1 );%@NL@%
- %@AS@% _Rectangle_w( _GBorder, -3.0, -3.0, 3.0, 3.0 );%@NL@%
- %@AS@% _Rectangle_wxy( _GBorder, upleft, botright );%@NL@%
- %@NL@%
- %@CR:MQPD4459@%%@4@%All three procedures contain a fill flag as the first argument. The%@EH@%
- procedure %@AB@%_Rectangle%@AE@% takes integer arguments that refer to the viewport
- screen coordinates. The procedure %@AB@%_Rectangle_w%@AE@% takes four double-precision,
- floating-point values referring to window coordinates: upper left %@AI@%x%@AE@%, upper
- left %@AI@%y%@AE@%, lower right %@AI@%x%@AE@%, and lower right %@AI@%y%@AE@%. The procedure %@AB@%_Rectangle_wxy%@AE@%
- takes two arguments: the addresses of structures of type %@AB@%_WXYCoord%@AE@%, which
- contains two %@AB@%Double%@AE@% types named %@AB@%wx%@AE@% and %@AB@%wy%@AE@%. The structure is defined in the
- %@AB@%MSGraph%@AE@% unit. The values are assigned just before %@AB@%_Rectangle_wxy%@AE@% is called.%@NL@%
- %@NL@%
- %@CR:MQPD4460@%%@4@%%@AB@%Drawing Graphics%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD4461@%%@4@%The %@AS@%grid_shape%@AE@% procedure is shown here:%@EH@%%@NL@%
- %@NL@%
- %@AS@% PROCEDURE grid_shape;%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% i, x1, y1, x2, y2 : Integer;%@NL@%
- %@AS@% x, y : Real;%@NL@%
- %@AS@% s : STRING[80];%@NL@%
- %@AS@% BEGIN%@NL@%
- %@NL@%
- %@AS@% FOR i := 1 TO vc.NumColors DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _SetTextPosition( i, 2 );%@NL@%
- %@AS@% _SetTextColor( i );%@NL@%
- %@AS@% Str( i, s );%@NL@%
- %@AS@% _OutText( 'Color ' + s );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% _SetColor( 1 );%@NL@%
- %@AS@% _Rectangle_w( _GBorder, -1.0, -1.0, 1.0, 1.0 );%@NL@%
- %@AS@% _Rectangle_w( _GBorder, -1.02, -1.02, 1.02, 1.02 );%@NL@%
- %@NL@%
- %@AS@% x := -0.9;%@NL@%
- %@AS@% i := 0;%@NL@%
- %@AS@% WHILE x 0.9 DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _SetColor( 2 );%@NL@%
- %@AS@% _MoveTo_w( x, -1.0 ); _LineTo_w( x, 1.0 );%@NL@%
- %@AS@% _MoveTo_w( -1.0, x ); _LineTo_w( 1.0, x );%@NL@%
- %@AS@% _SetColor( 3 );%@NL@%
- %@AS@% _MoveTo_w( x - 0.1, bananas[i] );%@NL@%
- %@AS@% Inc( i );%@NL@%
- %@AS@% _LineTo_w( x, bananas[i] );%@NL@%
- %@AS@% x := x + 0.1;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% _MoveTo_w( 0.9, bananas[i] );%@NL@%
- %@AS@% Inc(i);%@NL@%
- %@AS@% _LineTo_w( 1.0, bananas[i] );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQPD4462@%%@4@%First, the number of available color indexes is assigned to the %@AS@%numc%@AE@%%@EH@%
- variable and a loop displays all of the available colors:%@NL@%
- %@NL@%
- %@AS@% FOR i := 1 TO numc DO%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _SetTextPosition( i, 2 );%@NL@%
- %@AS@% _SetTextColor( i );%@NL@%
- %@AS@% Str(i, s);%@NL@%
- %@AS@% _OutText( 'Color ' + s );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQPD4463@%%@4@%The names of the procedures are self- explanatory. The advantage of using%@EH@%
- %@AB@%_OutText%@AE@% in graphics mode is that you can control the text color and limit
- output to the currently defined text window.%@NL@%
- %@NL@%
- %@CR:MQPD4464@%%@4@%The procedure and function names that end with %@AB@%_w%@AE@% work the same as their%@EH@%
- viewport equivalents, except you pass double-precision, floating-point
- values instead of integers. For example, you pass integers to %@AB@%_LineTo%@AE@% but
- floating-point values to %@AB@%_LineTo_w.%@AE@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD5000@%%@2@%%@AB@%13.5 Animation%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD5001@%%@4@%The QuickPascal %@AB@%MSGraph%@AE@% unit provides several functions that can be used to%@EH@%
- animate your graphics programs. These functions provide two means of
- animation:%@NL@%
- %@NL@%
- %@CR:MQPD5002@% 1. Video-page animation (also used in text modes)%@NL@%
- %@NL@%
- 2. Bit-mapped animation%@NL@%
- %@NL@%
- %@CR:MQPD5003@%%@4@%"Video-page animation" takes advantage of the fact that the EGA, VGA, and%@EH@%
- Hercules video cards have enough memory to store more than one video
- display page. You can animate by switching between the pages. "Bit-mapped
- animation" captures bit-mapped images of the screen and then stores them in
- a memory buffer. These images can be redisplayed at a new location to
- perform animation.%@NL@%
- %@NL@%
- %@CR:MQPD5004@%%@4@%This section discusses these two animation techniques and shows two sample%@EH@%
- programs that bring your graphics to life.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD5100@%%@3@%%@AB@%13.5.1 Video-Page Animation%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD5101@%%@4@%Most video adapters contain enough memory so that more than one display page%@EH@%
- can be stored at a time. The %@AB@%MSGraph%@AE@% unit provides several functions that
- allow you to manipulate these video pages. Two terms are used to describe
- these pages──the "active page" is the page where text and graphics commands
- operate; the "visual page" is the page that you see displayed.%@NL@%
- %@NL@%
- %@CR:MQPD5102@%%@4@%The number of video pages available in an adapter depends on the amount of%@EH@%
- video memory on the adapter and the mode in which the adapter is used. For
- example, the CGA adapter with 16K of video memory supports four video pages
- in the text mode %@AB@%_TextC80%@AE@%. An EGA adapter with a full 256K of video memory
- has room for two video pages even in the high resolution %@AB@%_EResColor%@AE@% mode.
- Virtually all adapters provide for multiple pages in text modes; only the
- EGA and VGA adapters with 256K of video memory support two video pages in
- the high-resolution graphics modes. The Hercules graphics mode (%@AB@%_HercMono%@AE@%)
- can support two pages, but only if it is the only graphics adapter present
- and only when MSHERC.COM is started without the /H option.%@NL@%
- %@NL@%
- %@CR:MQPD5103@%%@4@%Use the procedure %@AB@%_GetVideoConfig%@AE@% to obtain information about the video%@EH@%
- configuration. After calling %@AB@%_GetVideoConfig%@AE@%, use the %@AB@%NumVideoPages%@AE@% element
- of the %@AB@%_VideoConfig%@AE@% structure to determine the number of video pages
- supported.%@NL@%
- %@NL@%
- %@CR:MQPD5104@%%@4@%A simple use of video pages is to draw graphics offscreen (on the active%@EH@%
- page) and then make this active page the visual page. In this way, you do
- not see the process of creating the graphics; you only see the final result.
- This process of drawing offscreen and then switching can be extended to
- provide animation.%@NL@%
- %@NL@%
- %@CR:MQPD5105@%%@4@%The procedure %@AB@%_SetVisualPage%@AE@% changes the page that you see. The procedure %@EH@%
- %@AB@%_SetActivePage%@AE@% changes the page where drawing takes place. The first page in
- any graphics system is number 0, the second is number 1, and so on. A
- corresponding set of functions %@AB@%_GetActivePage%@AE@% and %@AB@%_GetVisualPage%@AE@% return the
- value of the current active or visual page, respectively.%@NL@%
- %@NL@%
- %@CR:MQPD5106@%%@4@%To animate any sequence of screens using video-page animation, use the%@EH@%
- following steps:%@NL@%
- %@NL@%
- %@CR:MQPD5107@% 1. Perform regular graphics initialization (select video mode, check for%@NL@%
- error, and so on).%@NL@%
- %@NL@%
- 2. Draw on the active page.%@NL@%
- %@NL@%
- 3. Swap the visual and active pages.%@NL@%
- %@NL@%
- 4. Repeat steps 2 and 3 until finished with animation.%@NL@%
- %@NL@%
- 5. Restore the screen and exit the program.%@NL@%
- %@NL@%
- %@CR:MQPD5108@%%@4@%The example program PAGES.PAS uses four video pages to animate a simple set%@EH@%
- of character images in text mode.%@NL@%
- %@NL@%
- %@AS@% PROGRAM page_animation;%@NL@%
- %@AS@% { PAGES.PAS: Use video pages to animate screens }%@NL@%
- %@NL@%
- %@AS@% USES%@NL@%
- %@AS@% MSGraph, Crt;%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% jumper : ARRAY[0..3] OF STRING =%@NL@%
- %@AS@% ('/O\', '-O-', '\O/', 'WOW');%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% a, i : Integer;%@NL@%
- %@AS@% oldvpage : Integer;%@NL@%
- %@AS@% oldapage : Integer;%@NL@%
- %@AS@% vc : _VideoConfig;%@NL@%
- %@AS@% oldcursor : Boolean;%@NL@%
- %@NL@%
- %@AS@% BEGIN { Begin main program }%@NL@%
- %@NL@%
- %@AS@% _ClearScreen( _GClearScreen);%@NL@%
- %@NL@%
- %@AS@% oldapage := _GetActivePage;%@NL@%
- %@AS@% oldvpage := _GetVisualPage;%@NL@%
- %@NL@%
- %@AS@% { Set the video mode for a large text size }%@NL@%
- %@AS@% a := _SetVideoModeRows( _TextBW40, 25 );%@NL@%
- %@AS@% _GetVideoConfig( vc );%@NL@%
- %@NL@%
- %@AS@% IF ((a = 0) OR (vc.NumVideoPages < 4)) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( '_TEXTBW40 mode not available; hit Return to continue');%@NL@%
- %@AS@% Readln;%@NL@%
- %@AS@% a := _SetVideoMode( _DefaultMode );%@NL@%
- %@AS@% Halt( 0 );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% { Turn off flashing cursor. }%@NL@%
- %@AS@% oldcursor := _DisplayCursor( False );%@NL@%
- %@NL@%
- %@AS@% { Draw image on each page. }%@NL@%
- %@AS@% FOR i := 0 TO 3 DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _SetActivePage( i );%@NL@%
- %@AS@% _SetTextPosition( 12, 20 );%@NL@%
- %@AS@% _OutText( jumper[i] );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% { Cycle through pages 0 to 3. }%@NL@%
- %@AS@% REPEAT%@NL@%
- %@AS@% FOR i := 0 TO 3 DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _SetVisualPage( i );%@NL@%
- %@AS@% Delay( 500 );%@NL@%
- %@AS@% END;%@NL@%
- %@AS@% UNTIL KeyPressed;%@NL@%
- %@NL@%
- %@AS@% { Restore everything before ending the program. }%@NL@%
- %@AS@% a := _SetVideoMode( _DefaultMode );%@NL@%
- %@AS@% _SetActivePage( oldapage );%@NL@%
- %@AS@% _SetVisualPage( oldvpage );%@NL@%
- %@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQPD5109@%%@4@%The program PAGES.PAS begins with a call to %@AB@%_ClearScreen%@AE@% and then sets the%@EH@%
- video mode using the %@AB@%_SetVideoModeRows%@AE@% function. The cursor is turned off
- with the %@AB@%_DisplayCursor%@AE@% function.%@NL@%
- %@NL@%
- %@CR:MQPD510A@%%@4@%The %@AB@%FOR%@AE@% loop draws a graphics image on each of four pages. The loop goes to%@EH@%
- each of the video pages and outputs the graphics image using the %@AB@%_OutText%@AE@%
- procedure. When you run this program, notice that you don't see any of this
- activity. Since the drawing is taking place on the active pages, it is not
- visible on the screen (the visual page).%@NL@%
- %@NL@%
- %@CR:MQPD510B@%%@4@%Once the pages have been drawn, the %@AB@%REPEAT%@AE@% loop cycles through each page and%@EH@%
- makes it the visual page (so you can see it) and then delays 500
- milliseconds between calls to %@AB@%_SetVisualPage%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQPD510C@%%@4@%Finally, when a key is pressed, the program ends by restoring the video mode%@EH@%
- to %@AB@%_DefaultMode%@AE@% using the %@AB@%_SetVideoMode%@AE@% function.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPD5200@%%@3@%%@AB@%13.5.2 Bit-Mapped Animation%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD5201@%%@4@%Bit-mapped animation gives you the ability to draw graphics figures and%@EH@%
- store them in memory for later use in animation. The %@AB@%_ImageSize%@AE@% function
- determines the amount of memory required to store a specified bit-mapped
- image. The image is specified in terms of a bounding rectangle. The
- %@AB@%_GetImage%@AE@% procedure copies the bit map of pixels inside a specified
- rectangle to a buffer area in memory. The %@AB@%_PutImage%@AE@% procedure copies a
- bit-mapped image from a memory buffer to the screen at a location specified
- by the program.%@NL@%
- %@NL@%
- %@CR:MQPD5202@%%@4@%The %@AB@%_PutImage%@AE@% procedure uses a %@AI@%CopyMode%@AE@% argument to control how the stored%@EH@%
- image interacts with what is already on the screen. The %@AI@%CopyMode%@AE@% argument
- specifies one of the following screen display operations:%@NL@%
- %@NL@%
- %@CR:MQPD5203@%%@AB@%Constant Action %@AE@%%@NL@%
- %@NL@%
- %@AB@%_Gand%@AE@% Logical AND of the transfer image and screen%@NL@%
- image%@NL@%
- %@NL@%
- %@AB@%_Gor%@AE@% Superimposition of the transfer image onto the%@NL@%
- existing screen image%@NL@%
- %@NL@%
- %@AB@%_GPReset%@AE@% Direct transfer from memory to screen; color%@NL@%
- inverted%@NL@%
- %@NL@%
- %@AB@%_GPSet%@AE@% Direct transfer from memory to screen%@NL@%
- %@NL@%
- %@AB@%_Gxor%@AE@% Screen inversion only where a point exists in%@NL@%
- the transfer image%@NL@%
- %@NL@%
- %@CR:MQPD5204@%%@4@%The two %@AI@%CopyMode%@AE@% arguments best suited for animation are %@AB@%_Gxor%@AE@% and %@AB@%_GPSet%@AE@%.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD5205@%%@4@%Animation done using %@AB@%_GPSet%@AE@% is faster, but erases the screen background. In%@EH@%
- contrast, %@AB@%_Gxor%@AE@% is slower, but preserves the screen background.%@NL@%
- %@NL@%
- %@CR:MQPD5206@%%@4@%Animation with %@AB@%_Gxor%@AE@% is done with the following four steps:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD5207@% 1. Put the object on the screen with %@AB@%_Gxor%@AE@%.%@NL@%
- %@NL@%
- 2. Calculate the new position of the object.%@NL@%
- %@NL@%
- 3. Put the object on the screen a second time at the old location, using%@NL@%
- %@AB@%_Gxor%@AE@% again──this time to remove the old image.%@NL@%
- %@NL@%
- 4. Go to step 1, but this time put the object at the new location.%@NL@%
- %@NL@%
- %@CR:MQPD5208@%%@4@%Movement done with these four steps leaves the background unchanged after%@EH@%
- step 3. Flicker can be reduced by minimizing the time between steps 4 and 1,
- and by making sure that there is enough time delay between steps 1 and 3. If
- more than one object is being animated, every object should be processed at
- once, one step at a time.%@NL@%
- %@NL@%
- %@CR:MQPD5209@%%@4@%If it is not important to preserve the background, animation can be%@EH@%
- performed using the %@AB@%_GPSet%@AE@% option. If the border of the bounding rectangle
- around the image is as large as or larger than the maximum distance the
- object will move, then each time the image is put in a new location, the
- border will erase all traces of the image in the old location.%@NL@%
- %@NL@%
- %@CR:MQPD5210@%%@4@%%@AB@%Using Bit-Mapped Images%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD5211@%%@4@%The process of animating using bit-mapped images follows these eight steps:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD5212@% 1. Perform regular graphics initialization (select graphics mode, check%@NL@%
- for error, and so on).%@NL@%
- %@NL@%
- 2. Draw the graphics image using the %@AB@%MSGraph%@AE@% unit procedures and%@NL@%
- functions.%@NL@%
- %@NL@%
- 3. Use the %@AB@%_ImageSize%@AE@% function to determine the amount of memory required%@NL@%
- to store the image.%@NL@%
- %@NL@%
- 4. Use the %@AB@%GetMem%@AE@% procedure to allocate the amount of memory needed (as%@NL@%
- found in step 2).%@NL@%
- %@NL@%
- 5. Call %@AB@%_GetImage%@AE@% to copy the bit map of pixels from the screen to the%@NL@%
- memory buffer created in step 3.%@NL@%
- %@NL@%
- 6. Call %@AB@%_PutImage%@AE@% to display the image stored in memory. This display can%@NL@%
- be at any location on the screen.%@NL@%
- %@NL@%
- 7. Repeat steps 3 through 6 (possibly with different images) until%@NL@%
- finished with animation.%@NL@%
- %@NL@%
- 8. Restore the screen and exit the program.%@NL@%
- %@NL@%
- %@CR:MQPD5220@%%@4@%%@AB@%An Example of Bit-Mapped Animation%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD5221@%%@4@%The program ANIMATE.PAS demonstrates this process, drawing a rectangle and%@EH@%
- then redisplaying it at random locations on the screen.%@NL@%
- %@NL@%
- %@AS@% PROGRAM Animate;%@NL@%
- %@AS@% { ANIMATE.PAS: Demonstrates animation using image buffers }%@NL@%
- %@NL@%
- %@AS@% USES%@NL@%
- %@AS@% MSGraph, Crt;%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% max_buffer = 65520;%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% q : Integer;%@NL@%
- %@AS@% vc : _VideoConfig;%@NL@%
- %@AS@% buffer : POINTER;%@NL@%
- %@AS@% imsize : LongInt;%@NL@%
- %@AS@% x0, y0 : Integer;%@NL@%
- %@AS@% x, y : Integer;%@NL@%
- %@NL@%
- %@AS@% BEGIN { Begin main program. }%@NL@%
- %@NL@%
- %@AS@% _ClearScreen( _GClearScreen);%@NL@%
- %@NL@%
- %@AS@% { Set the video mode and check for success }%@NL@%
- %@AS@% q := _SetVideoMode( _MaxResMode );%@NL@%
- %@AS@% IF (q = 0) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'Graphics mode unavailable; hit Return to continue' );%@NL@%
- %@AS@% Readln;%@NL@%
- %@AS@% q := _SetVideoMode( _DefaultMode );%@NL@%
- %@AS@% Halt( 0 );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% { Find out some screen characteristics. }%@NL@%
- %@AS@% _GetVideoConfig( vc );%@NL@%
- %@NL@%
- %@AS@% { Draw and store a simple figure. }%@NL@%
- %@AS@% _SetColor( 3 );%@NL@%
- %@AS@% x := vc.NumXPixels DIV 4;%@NL@%
- %@AS@% y := vc.NumYPixels DIV 4;%@NL@%
- %@NL@%
- %@AS@% _Rectangle( _GFillInterior, 0, 0, x, y );%@NL@%
- %@AS@% imsize := _ImageSize( 0, 0, x, y );%@NL@%
- %@AS@% IF (imsize > max_buffer) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'Image too big.' );%@NL@%
- %@AS@% Readln;%@NL@%
- %@AS@% Halt( 0 );%@NL@%
- %@AS@% END%@NL@%
- %@AS@% ELSE%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% GetMem( buffer, imsize );%@NL@%
- %@AS@% IF (buffer = NIL) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'Not enough heap memory.' );%@NL@%
- %@AS@% Readln;%@NL@%
- %@AS@% Halt( 0 );%@NL@%
- %@AS@% END;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% _GetImage( 0, 0, x, y, buffer^ );%@NL@%
- %@AS@% _ClearScreen( _GClearScreen );%@NL@%
- %@NL@%
- %@AS@% { Draw axes centered on the screen }%@NL@%
- %@AS@% _SetColor (2);%@NL@%
- %@AS@% x0 := vc.NumXPixels DIV 2 -1;%@NL@%
- %@AS@% y0 := vc.NumYPixels DIV 2 -1;%@NL@%
- %@AS@% _MoveTo ( x0 ,0);%@NL@%
- %@AS@% _LineTo( x0, vc.NumYPixels );%@NL@%
- %@AS@% _MoveTo( 0, y0 );%@NL@%
- %@AS@% _LineTo( vc.NumXPixels, y0 );%@NL@%
- %@NL@%
- %@AS@% _SetTextPosition(1,1);%@NL@%
- %@AS@% _OutText( '_Gxor');%@NL@%
- %@AS@% WHILE NOT KeyPressed DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _PutImage( Random( vc.NumXPixels - x ),%@NL@%
- %@AS@% Random( vc.NumYPixels - y ), buffer^, _Gxor );%@NL@%
- %@AS@% Delay( 500 );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% _ClearScreen( _GClearScreen );%@NL@%
- %@AS@% q := _SetVideoMode( _DefaultMode );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@CR:MQPD5230@%%@4@%%@AB@%Initializing Graphics and Drawing the Image%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPD5231@%%@4@%The ANIMATE.PAS program begins by clearing the screen, initializing the%@EH@%
- random-number generator, and setting the video mode to the highest
- resolution possible.%@NL@%
- %@NL@%
- %@CR:MQPD5232@%%@4@%The following code fragment draws and stores a simple image:%@EH@%%@NL@%
- %@NL@%
- %@AS@% { Draw and store a simple figure. }%@NL@%
- %@AS@% _SetColor( 3 );%@NL@%
- %@AS@% x := vc.NumXPixels DIV 4;%@NL@%
- %@AS@% y := vc.NumYPixels DIV 4;%@NL@%
- %@NL@%
- %@AS@% _Rectangle( _GFillInterior, 0, 0, x, y );%@NL@%
- %@AS@% imsize := _ImageSize( 0, 0, x, y );%@NL@%
- %@AS@% IF (imsize > max_buffer) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'Image too big.' );%@NL@%
- %@AS@% Readln;%@NL@%
- %@AS@% Halt( 0 );%@NL@%
- %@AS@% END%@NL@%
- %@AS@% ELSE%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% GetMem( buffer, imsize );%@NL@%
- %@AS@% IF (buffer = NIL) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'Not enough heap memory.' );%@NL@%
- %@AS@% Readln;%@NL@%
- %@AS@% Halt( 0 );%@NL@%
- %@AS@% END;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% _GetImage( 0, 0, x, y, buffer^ );%@NL@%
- %@AS@% _ClearScreen( _GClearScreen );%@NL@%
- %@NL@%
- %@4@%%@AB@%Allocating Memory%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@4@%The %@AB@%_Rectangle%@AE@% procedure draws a rectangle that is about one-sixteenth the%@EH@%
- size of the screen. The %@AB@%_ImageSize%@AE@% function uses the same bounding rectangle
- measurements to determine the amount of memory required to hold this figure.
- The %@AB@%GetMem%@AE@% procedure then allocates the necessary memory space for the
- image. Because %@AB@%GetMem%@AE@% can allocate at most 65,520 bytes (64K-16), you must
- check the image size before requesting the buffer. If the image is larger
- than 65,520 bytes, you will need to allocate additional buffers and copy
- part of the image to each buffer.%@NL@%
- %@NL@%
- %@CR:MQPD5222@%%@4@%The %@AB@%_GetImage%@AE@% procedure copies the image from the screen and stores it into%@EH@%
- the memory area specified by %@AS@%buffer%@AE@%. Finally, the %@AB@%_ClearScreen%@AE@% procedure
- clears this image off the screen. A more complex program could make use of
- the active and visual pages discussed in the previous section so that the
- image is drawn on the active page and the %@AB@%_ClearScreen%@AE@% procedure is not
- needed.%@NL@%
- %@NL@%
- %@CR:MQPD5223@%%@4@%Next, the program draws a coordinate axis centered on the screen. This will%@EH@%
- clarify later how the stored image interacts with images already displayed
- on the screen.%@NL@%
- %@NL@%
- %@4@%%@AB@%Displaying the Image%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@4@%The program then repeatedly calls %@AB@%_PutImage%@AE@% to display the stored image at%@EH@%
- random locations on the screen. The process ends when a key is pressed. Once
- a key is pressed, the program ends with a call to restore the video mode.%@NL@%
- %@NL@%
- %@AS@% WHILE NOT KeyPressed DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _PutImage( Random( vc.NumXPixels - x ),%@NL@%
- %@AS@% Random( vc.NumYPixels - y ), buffer^, _Gxor );%@NL@%
- %@AS@% Delay( 500 );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% _ClearScreen( _GClearScreen );%@NL@%
- %@AS@% q := _SetVideoMode( _DefaultMode );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@4@%The %@AB@%_PutImage%@AE@% procedure takes four arguments. The first two specify the %@AI@%x%@AE@%%@EH@%
- and %@AI@%y%@AE@% coordinates of the upper left corner where the image is to be
- displayed from the memory buffer. The third argument specifies the memory
- buffer created by %@AB@%GetMem%@AE@% and used by %@AB@%_GetImage%@AE@% to store the bit map.
- Finally, the last argument specifies the interaction between the stored
- image and the currently displayed image. Notice that in this case (using the
- %@AB@%_Gxor%@AE@% argument) that the image is inverted when it overlaps a currently
- displayed figure (like the axes or another rectangle).%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPE0000@%%@1@%%@AB@%Chapter 14 Using Fonts%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQPE0001@%%@4@%You can write QuickPascal programs that generate graphics and display text.%@EH@%
- In any graphics image, QuickPascal can display various styles and sizes of
- type. These collections of stylized text characters are called "fonts."
- Fonts are simple to learn and easy to use. Yet they can add a touch of
- polish to your program.%@NL@%
- %@NL@%
- %@CR:MQPE0002@%%@4@%This chapter explains how to use fonts. It assumes you have already read%@EH@%
- Chapter 13%@BO: 5dac7@%, "Using Graphics." You should understand such terms as "graphics
- mode" and "text mode," and be familiar with such procedures as %@AB@%_SetVideoMode%@AE@%
- and %@AB@%_MoveTo%@AE@%.%@NL@%
- %@NL@%
- %@CR:MQPE0003@%%@4@%Note that the QuickPascal fonts can be used only in graphics modes. Fonts%@EH@%
- cannot be used in text modes.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPE1000@%%@2@%%@AB@%14.1 Overview of QuickPascal Fonts%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPE1001@%%@4@%Each font in QuickPascal consists of a typeface and several type sizes.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPE1002@%%@4@%"Typeface" is a printer's term that refers to the style of the displayed%@EH@%
- text── Courier, for example, or Roman. The list on the following page shows
- six of the typefaces available with the QuickPascal font functions.%@NL@%
- %@NL@%
- %@CR:MQPE1003@%%@4@%"Type size" measures the screen area occupied by individual characters. This%@EH@%
- term is also borrowed from the printer's lexicon, but for our purposes, it
- is specified in units of screen pixels. For example, "Courier 169" denotes
- text of Courier typeface, with each character occupying a screen area of 16
- vertical pixels by 9 horizontal pixels.%@NL@%
- %@NL@%
- %@CR:MQPE1004@%%@4@%The QuickPascal font functions use two methods to create fonts. The first%@EH@%
- technique generates the typefaces Courier, Helv, and Tms Rmn through a
- "bit-mapping" technique. Bit mapping defines character images with binary
- data. Each bit in the map corresponds to a screen pixel. If a bit is 1, its
- associated pixel is set to the current screen color. A bit value of 0 clears
- the pixel. Video adapters use this same technique to display text in
- graphics mode.%@NL@%
- %@NL@%
- %@CR:MQPE1005@%%@4@%The second method creates the remaining three type styles──Modern, Script,%@EH@%
- and Roman──as "vector mapped" fonts. Vector mapping represents each
- character in terms of lines and arcs. In a literal sense, vector-mapped
- characters are drawn on the screen. You might think of bit-mapped characters
- as being stenciled.%@NL@%
- %@NL@%
- %@CR:MQPE1006@%%@4@%Each method of creating fonted text has advantages and disadvantages.%@EH@%
- Bit-mapped characters are formed more completely since the pixel mapping is
- predetermined. However, they cannot be scaled to arbitrary sizes.
- Vector-mapped text can be scaled to any size, but the characters lack the
- solid appearance of the bit-mapped characters.%@NL@%
- %@NL@%
- %@CR:MQPE1007@%%@4@%Any function or procedure affecting the current graphics position (such as%@EH@%
- the %@AB@%_MoveTo%@AE@% procedure or the %@AB@%_LineTo%@AE@% procedure) will also affect the font
- display when %@AB@%_OutGText%@AE@% is called. Other routines (such as %@AB@%_SetColor%@AE@% or
- %@AB@%_RemapPalette%@AE@%) that affect drawing characteristics also affect font text
- output.%@NL@%
- %@NL@%
- %@CR:MQPE1008@%%@4@%The QuickPascal fonts appear on your screen as shown on page 216 in the%@EH@%
- printed version of this book.%@NL@%
- %@NL@%
- %@CR:MQPE1009@%%@4@%Table 14.1%@BO: 7735c@% describes the characteristics of each font. Notice that%@EH@%
- bit-mapped fonts come in preset sizes as measured in pixels. The exact size
- of any font character depends on the screen resolution and display type.%@NL@%
- %@NL@%
- %@CR:MQPET100@%%@4@%%@AB@%Table 14.1 Typefaces and Type Sizes in QuickPascal%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Typeface Mapping Size (in Pixels) Spacing%@AE@%%@NL@%
- %@NL@%
- Courier Bit 138, 169, 2012 Fixed%@NL@%
- %@NL@%
- Helv Bit 135, 167, 208 Proportional%@NL@%
- 1315, 166, 198%@NL@%
- %@NL@%
- Tms Rmn Bit 105, 126, 158 Proportional%@NL@%
- 169, 2012, 2616%@NL@%
- %@NL@%
- Modern Vector Scaled Proportional%@NL@%
- %@NL@%
- Script Vector Scaled Proportional%@NL@%
- %@NL@%
- Roman Vector Scaled Proportional%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPE2000@%%@2@%%@AB@%14.2 Using Fonts in QuickPascal%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPE2001@%%@4@%Data for both bit-mapped and vector-mapped fonts reside in files on disk. A%@EH@%
- .FON extension identifies the files. The names of the .FON files indicate
- their content. For example, the MODERN.FON, ROMAN.FON, and SCRIPT.FON files
- hold data for the three vector-mapped fonts.%@NL@%
- %@NL@%
- %@CR:MQPE2002@%%@4@%The QuickPascal .FON files are identical to the font files supplied with%@EH@%
- Microsoft QuickC(R), Version 2.0, as well as being identical to the .FON
- files used in the Microsoft Windows operating environment. Consequently, you
- can use any of the Windows .FON files with the QuickPascal font functions.
- The Windows .FON files are also available for purchase separately. In
- addition, several vendors offer software that create or modify .FON files,
- allowing you to design your own fonts.%@NL@%
- %@NL@%
- %@CR:MQPE2003@%%@4@%Your programs should follow these four steps to display fonted text:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPE2004@% 1. Set a graphics video mode%@NL@%
- %@NL@%
- 2. Register fonts%@NL@%
- %@NL@%
- 3. Set the current font from the register%@NL@%
- %@NL@%
- 4. Display text using the current font%@NL@%
- %@NL@%
- %@CR:MQPE2005@%%@4@%Sections 14.2.1%@BO: 77ccb@%-14.2.3 describe each of the font-specific steps in detail.%@EH@%
- The procedure for using video modes for graphics is discussed in Section
- 13.3%@BO: 63072@%. An example program in the final section of this chapter demonstrates
- how to display the various fonts available in the QuickPascal .FON files.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPE2100@%%@3@%%@AB@%14.2.1 Registering Fonts%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPE2101@%%@4@%The fonts you plan to use must be organized into a list in memory, a process%@EH@%
- called "registering." The register list contains information about the
- available .FON files. You register fonts by calling the function
- %@AB@%_RegisterFonts%@AE@%. This function reads header information from the specified
- .FON files. It builds a list of file information but does not read mapping
- data from the files.%@NL@%
- %@NL@%
- %@CR:MQPE2102@%%@4@%The %@AB@%MSGraph%@AE@% unit defines the %@AB@%_RegisterFonts%@AE@% function as%@EH@%%@NL@%
- %@NL@%
- %@AI@%Function%@AE@% %@AB@%_RegisterFonts( %@AE@%%@AI@%PathName%@AE@% %@AB@%: CSTRING ) : %@AE@%%@AI@%Integer%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPE2103@%%@4@%The argument %@AI@%PathName%@AE@% is a string containing a file name. The file name is%@EH@%
- the name of the .FON file for the desired font. The file name can include
- wild cards, allowing you to register several fonts with one call to
- %@AB@%_RegisterFonts%@AE@%. For example, the function call below registers all of the
- .FON files in the current directory and checks for a successful
- registration:%@NL@%
- %@NL@%
- %@AS@% result := _RegisterFonts( '*.FON' );%@NL@%
- %@AS@% IF (result < 0) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'Unable to register fonts');%@NL@%
- %@AS@% Halt( 0 );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% { the rest of your fonts program goes here }%@NL@%
- %@NL@%
- %@CR:MQPE2104@%%@4@%As illustrated above, the %@AB@%_RegisterFonts%@AE@% function returns a negative number%@EH@%
- if it is unable to register any fonts or if the .FON file is corrupt. If it
- successfully reads one or more .FON files, %@AB@%_RegisterFonts%@AE@% returns the number
- of fonts registered.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPE2200@%%@3@%%@AB@%14.2.2 Setting the Current Font%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPE2201@%%@4@%To set a font as the current font, call the function %@AB@%_SetFont%@AE@%. This%@EH@%
- function checks to see if the requested font is registered, then reads the
- mapping data from the appropriate .FON file. A font must be registered and
- marked current before your program can display text using that font.%@NL@%
- %@NL@%
- %@CR:MQPE2202@%%@4@%The %@AB@%MSGraph%@AE@% unit defines the %@AB@%_SetFont%@AE@% function as%@EH@%%@NL@%
- %@NL@%
- %@AI@%Function%@AE@% %@AB@%_SetFont( %@AE@%%@AI@%Options%@AE@% %@AB@%: CSTRING ) :%@AE@%%@AI@%Integer%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPE2203@%%@4@%The %@AI@%Options%@AE@% argument is a string that describes the desired characteristics%@EH@%
- of the font. The string uses letter codes that describe the desired font, as
- outlined here:%@NL@%
- %@NL@%
- %@CR:MQPE2204@%%@AB@%Option Code Meaning%@AE@%%@NL@%
- %@NL@%
- %@AB@%t'%@AE@%%@AI@%FontName%@AE@%%@AB@%'%@AE@% Typeface of the font in single quotes. The%@NL@%
- %@AI@%FontName%@AE@% string is one of the following:%@NL@%
- %@NL@%
- courier modern
- helv script
- tms rmn roman%@NL@%
- %@NL@%
- Notice that the %@AI@%FontName%@AE@% string is surrounded by%@NL@%
- a pair of two single quotes. This is necessary%@NL@%
- to embed the %@AI@%FontName%@AE@% string within the %@AI@%Options%@AE@%%@NL@%
- string, and Pascal uses single quotes to specify%@NL@%
- a string. Notice the space in "tms rmn."%@NL@%
- %@NL@%
- Other products' font files use other names for %@AI@%%@AE@%%@NL@%
- %@AI@%FontName%@AE@%. Refer to the vendor's documentation%@NL@%
- for these names.%@NL@%
- %@NL@%
- %@AB@%h%@AE@%%@AI@%y%@AE@% Character height, where %@AI@%y%@AE@% is the height in%@NL@%
- pixels.%@NL@%
- %@NL@%
- %@AB@%w%@AE@%%@AI@%x%@AE@% Character width, where %@AI@%x%@AE@% is the width in pixels.%@NL@%
- %@NL@%
- %@AB@%f%@AE@% Select only a fixed-spaced font.%@NL@%
- %@NL@%
- %@AB@%p%@AE@% Select only a proportional-spaced font.%@NL@%
- %@NL@%
- %@AB@%v%@AE@% Select only a vector-mapped font.%@NL@%
- %@NL@%
- %@AB@%r%@AE@% Select only a bit-mapped font.%@NL@%
- %@NL@%
- %@AB@%b%@AE@% Select the best fit from the registered fonts.%@NL@%
- This option instructs %@AB@%_SetFont%@AE@% to accept the%@NL@%
- closest-fitting font if a font of the specified%@NL@%
- size is not registered.%@NL@%
- %@NL@%
- If at least one font is registered, the %@AB@%b%@AE@% option%@NL@%
- always guarantees that %@AB@%_SetFont%@AE@% will be able to%@NL@%
- set a current font. If you do not specify the %@AB@%b%@AE@%%@NL@%
- option and an exact matching font is not%@NL@%
- registered, %@AB@%_SetFont%@AE@% will fail. In this case,%@NL@%
- any existing current font remains current.%@NL@%
- %@NL@%
- The %@AB@%_SetFont%@AE@% function uses four criteria for%@NL@%
- selecting the best fit. In descending order of%@NL@%
- precedence the four criteria are pixel height,%@NL@%
- typeface, pixel width, and spacing (fixed or%@NL@%
- proportional). If you request a vector-mapped%@NL@%
- font, %@AB@%_SetFont%@AE@% sizes the font to correspond with%@NL@%
- the specified pixel height and width. If you%@NL@%
- request a bit-mapped font, %@AB@%_SetFont%@AE@% chooses the%@NL@%
- closest available size. If the requested type%@NL@%
- size for a bit-mapped font fits exactly between%@NL@%
- two registered fonts, the smaller size takes%@NL@%
- precedence.%@NL@%
- %@NL@%
- %@AB@%n%@AE@%%@AI@%x%@AE@% Select font number %@AI@%x%@AE@%, where %@AI@%x%@AE@% is less than or%@NL@%
- equal to the value returned by %@AB@%_RegisterFonts%@AE@%.%@NL@%
- For example, the option %@AB@%n3%@AE@% makes the third%@NL@%
- registered font current, assuming that three or%@NL@%
- more fonts are registered.%@NL@%
- %@NL@%
- This option is primarily useful for cycling%@NL@%
- through all registered fonts in a loop. Because%@NL@%
- .FON files often contain several fonts, and the%@NL@%
- files are loaded into memory in reverse order%@NL@%
- from which they are registered, it is difficult%@NL@%
- to know which font will be number 3.%@NL@%
- %@NL@%
- %@CR:MQPE2205@%%@4@%Option codes are not case-sensitive and can be listed in any order. You can%@EH@%
- separate codes with spaces or any other character that is not a valid option
- code. The %@AB@%_SetFont%@AE@% function ignores all invalid codes.%@NL@%
- %@NL@%
- %@CR:MQPE2206@%%@4@%For example, the function call below specifies that the font should be a%@EH@%
- "script" typeface with a character height of 30 pixels and a character width
- of 24 pixels. If the function is unable to do this, a "best fit" font is
- requested. The multiple single quotes around %@AS@%script%@AE@% are required since the
- entire argument used by %@AB@%_SetFont%@AE@% is a string. The double single quote
- specifies to QuickPascal that the string contains a single quote.%@NL@%
- %@NL@%
- %@AS@% result := _SetFont( 't''script''h30w24b' );%@NL@%
- %@AS@% IF (result = -1) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln( 'Unable to set requested font');%@NL@%
- %@AS@% Halt( 0 );%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% Writeln( 'Font set' );%@NL@%
- %@AS@% { the rest of your font program goes here }%@NL@%
- %@NL@%
- %@CR:MQPE2207@%%@4@%As illustrated above, the %@AB@%_SetFont%@AE@% function returns a %@AS@%-1%@AE@% if it is unable to%@EH@%
- set the requested font. If it successfully sets a current font, the value %@AS@%0%@AE@%
- is returned.%@NL@%
- %@NL@%
- %@CR:MQPE2208@%%@4@%Once a font is set as the current font, the %@AB@%_SetFont%@AE@% function updates a data%@EH@%
- area with the parameters of the current font. The data area is in the form
- of a %@AB@%_FontInfo%@AE@% record, defined in the %@AB@%MSGraph%@AE@% unit as%@NL@%
- %@NL@%
- %@AS@% { structure for GetFontInfo }%@NL@%
- %@NL@%
- %@AS@% _FontInfo = RECORD%@NL@%
- %@AS@% fonttype : Integer; { b0 set = vector,clear = bit map }%@NL@%
- %@AS@% ascent : Integer; { pix dist from top to baseline }%@NL@%
- %@AS@% pixwidth : Integer; { character width in pixels, 0 = prop }%@NL@%
- %@AS@% pixheight : Integer; { character height in pixels }%@NL@%
- %@AS@% avgwidth : Integer; { average character width in pixels }%@NL@%
- %@AS@% filename : CSTRING[81]; { file name including path }%@NL@%
- %@AS@% facename : CSTRING[32]; { font name }%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQPE2209@%%@4@%If you wish to retrieve the parameters of the current font, call the%@EH@%
- function %@AB@%_GetFontInfo%@AE@%, which is defined in the %@AB@%MSGraph%@AE@% unit as%@NL@%
- %@NL@%
- %@AI@%Function%@AE@% %@AB@%_GetFontInfo( VAR %@AE@%%@AI@%FInfo%@AE@% %@AB@%: _FontInfo ) : %@AE@%%@AI@%Integer%@AE@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPE2300@%%@3@%%@AB@%14.2.3 Displaying Text Using the Current Font%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPE2301@%%@4@%Now you can display the font-based text. This step consists of two parts:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPE2302@% 1. Select a screen position for the text with the graphics procedure%@NL@%
- %@AB@%_MoveTo%@AE@%. Note that all of the font-based text is displayed using%@NL@%
- graphics functions. Consequently, the %@AB@%_MoveTo%@AE@% procedure (rather than%@NL@%
- the text procedure %@AB@%_SetTextPosition%@AE@%) positions the text. The %@AB@%_MoveTo%@AE@%%@NL@%
- procedure takes pixel coordinates as arguments. The coordinates specify%@NL@%
- the upper left point of the first character in the text string.%@NL@%
- Optionally, you can use the procedure %@AB@%_SetGTextVector%@AE@% to change the%@NL@%
- orientation of the text on the screen.%@NL@%
- %@NL@%
- 2. Display the font-based text at that position with the procedure%@NL@%
- %@AB@%_OutGText%@AE@%.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPE3000@%%@2@%%@AB@%14.3 A Few Hints on Using Fonts%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPE3001@%%@4@%Fonted text is simply another form of graphics, and using fonts effectively%@EH@%
- requires little programming effort. Still, there are a few things to watch:%@NL@%
- %@NL@%
- %@CR:MQPE3002@% ■ Remember that the video mode should be set only once to establish a%@NL@%
- graphics mode. If you generate an image (as with the %@AB@%_Rectangle%@AE@%%@NL@%
- procedure) and wish to incorporate fonted text above it as a title,%@NL@%
- don't reset the video mode prior to calling the font routines. Doing so%@NL@%
- will blank the screen, destroying the original image.%@NL@%
- %@NL@%
- ■ The %@AB@%_SetFont%@AE@% function reads specified .FON files to obtain mapping data%@NL@%
- for the current font. Each call to %@AB@%_SetFont%@AE@% causes a disk access and%@NL@%
- overwrites the old font data in memory. If you wish to show text of%@NL@%
- different styles on the same screen, display all of the text of one%@NL@%
- font before moving on to the others. By minimizing the number of calls%@NL@%
- to %@AB@%_SetFont%@AE@%, you'll save time spent in disk I/O and memory reloads.%@NL@%
- %@NL@%
- ■ When your program finishes with the fonts, you might want to free the%@NL@%
- memory occupied by the register list. Call the %@AB@%_UnRegisterFonts%@AE@%%@NL@%
- procedure to do this. As its name implies, this procedure frees the%@NL@%
- memory previously allocated by %@AB@%_RegisterFonts%@AE@%. The register information%@NL@%
- for each type size of each font takes up approximately 140 bytes of%@NL@%
- memory. Thus the amount of memory returned by %@AB@%_UnRegisterFonts%@AE@% is%@NL@%
- significant only if you have many fonts registered.%@NL@%
- %@NL@%
- ■ As for screen aesthetics, the same suggestions for the printed page%@NL@%
- apply to fonted screen text. Typefaces are more effective when they are%@NL@%
- not competing with each other for attention. Restricting the number of%@NL@%
- styles per screen to one or two generally results in a more pleasing,%@NL@%
- less cluttered image.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPE4000@%%@2@%%@AB@%14.4 Example Program%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPE4001@%%@4@%The QuickPascal font functions shine when they are used in conjunction with%@EH@%
- your other graphics functions. They allow you to dress up any image on the
- screen, yet they can make a visual impression when used by themselves, as
- the example program SAMPLER.PAS illustrates. This program displays sample
- text in all of the available fonts, then exits when a key is pressed. Make
- sure the .FON files are in the current directory before running the program.%@NL@%
- %@NL@%
- %@CR:MQPE4002@%%@4@%Notice that SAMPLER.PAS calls the graphics procedure %@AB@%_MoveTo%@AE@% to establish%@EH@%
- the starting position for each text string. Section 13.4%@BO: 6ac8a@% "Understanding
- Coordinate Systems," describes the %@AB@%_MoveTo%@AE@% procedure. The function %@AB@%_SetFont%@AE@%
- takes a character string as an argument. The string is an options list that
- specifies typeface and the best fit for a character height of 30 pixels and
- a width of 24 pixels.%@NL@%
- %@NL@%
- %@AS@% PROGRAM sampler; { Demonstrates using different fonts }%@NL@%
- %@NL@%
- %@AS@% USES%@NL@%
- %@AS@% Crt, MSGraph;%@NL@%
- %@NL@%
- %@AS@% CONST%@NL@%
- %@AS@% CRLF = #13 + #10;%@NL@%
- %@AS@% nfonts = 6;%@NL@%
- %@NL@%
- %@AS@% texttypes : ARRAY[ 1..2, 1..nfonts ] OF CSTRING[8] =%@NL@%
- %@AS@% (%@NL@%
- %@AS@% ( 'roman', 'courier', 'helv', 'tms rmn', 'modern', 'script' ),%@NL@%
- %@AS@% ( 'ROMAN', 'COURIER', 'HELV', 'TMS RMN', 'MODERN', 'SCRIPT' )%@NL@%
- %@AS@% );%@NL@%
- %@NL@%
- %@AS@% faces : ARRAY[ 1..nfonts ] OF CSTRING[12] =%@NL@%
- %@AS@% (%@NL@%
- %@AS@% ' t''roman''',%@NL@%
- %@AS@% ' t''cour''',%@NL@%
- %@AS@% ' t''helv''',%@NL@%
- %@AS@% ' t''tms rmn''',%@NL@%
- %@AS@% ' t''modern''',%@NL@%
- %@AS@% ' t''script'''%@NL@%
- %@AS@% );%@NL@%
- %@AS@% fontpath : CSTRING = '*.FON';%@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% list : CSTRING;%@NL@%
- %@AS@% vc : _VideoConfig;%@NL@%
- %@AS@% i, a : Integer;%@NL@%
- %@AS@% stra : STRING[3];%@NL@%
- %@AS@% ch : Char;%@NL@%
- %@NL@%
- %@NL@%
- %@AS@% BEGIN { Begin main program }%@NL@%
- %@NL@%
- %@AS@% { Read header information from all .FON files in%@NL@%
- %@AS@% the current directory%@NL@%
- %@AS@% }%@NL@%
- %@AS@% a := _RegisterFonts( fontpath );%@NL@%
- %@AS@% IF a < 0 THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _OutText('Error: Cannot register fonts.' + CRLF);%@NL@%
- %@AS@% Halt(1);%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% { Set the highest available video mode }%@NL@%
- %@AS@% a := _SetVideoMode( _MaxResMode );%@NL@%
- %@AS@% Str( a, stra );%@NL@%
- %@AS@% _OutText( 'MaxresMode = ' + stra );%@NL@%
- %@NL@%
- %@AS@% { Copy video configuration into structure vc }%@NL@%
- %@AS@% _GetVideoConfig(vc);%@NL@%
- %@NL@%
- %@AS@% { Display six lines of sample text }%@NL@%
- %@AS@% FOR i := 1 TO nfonts DO%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% list := faces[i] + 'bh24w24' ;%@NL@%
- %@AS@% a:= _SetFont( list );%@NL@%
- %@NL@%
- %@AS@% IF ( a <> -1) THEN%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% _SetColor( i + 1);%@NL@%
- %@AS@% _MoveTo( 0, i * 30 );%@NL@%
- %@AS@% _OutGText( texttypes[2,i] );%@NL@%
- %@AS@% _MoveTo( vc.NumXPixels DIV 2, i * 30 );%@NL@%
- %@AS@% _OutGText( texttypes[1,i]+CRLF );%@NL@%
- %@AS@% END%@NL@%
- %@AS@% ELSE%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% a := _SetVideoMode(_DefaultMode);%@NL@%
- %@AS@% _OutText('Error: Cannot set font.');%@NL@%
- %@AS@% Halt(1);%@NL@%
- %@AS@% END;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% ch := ReadKey;%@NL@%
- %@NL@%
- %@AS@% a := _SetVideoMode(_DefaultMode);%@NL@%
- %@NL@%
- %@AS@% _UnRegisterFonts; { Returns memory used by fonts }%@NL@%
- %@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF0000@%%@1@%%@AB@%Chapter 15 Object-Oriented Programming%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQPF0001@%%@4@%Object-oriented programming is widely hailed as the programming style of the%@EH@%
- future. QuickPascal offers you object-oriented programming today, through
- its object extensions to standard Pascal. Although they make only a few
- syntactic additions to the language, the QuickPascal object extensions
- provide a powerful and efficient framework for creating programs.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF1000@%%@2@%%@AB@%15.1 Overview%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF1001@%%@4@%Standard Pascal programs, along with programs written in other procedural%@EH@%
- languages, are organized around a set of data structures, with separate
- procedures and functions manipulating the data. An example is a graphics
- program that declares each shape as a unique %@AB@%TYPE%@AE@%. Various routines draw,
- erase, and move the shapes, likely using a %@AB@%CASE%@AE@% statement to differentiate
- between them.%@NL@%
- %@NL@%
- %@CR:MQPF1002@%%@4@%Object-oriented programs operate differently. Instead of being organized%@EH@%
- around data, they are organized around a set of "objects." An object is a
- structure that combines both data and routines into one type. It is similar
- to a Pascal %@AB@%RECORD%@AE@% type, but can store both functions and procedures as well
- as data.%@NL@%
- %@NL@%
- %@CR:MQPF1003@%%@4@%Objects have a property called "inheritance." Once an object has been%@EH@%
- declared, another object can be derived that inherits all of the data and
- routines associated with the parent type. New data and routines can be
- added, or existing inherited routines modified.%@NL@%
- %@NL@%
- %@CR:MQPF1004@%%@4@%A graphics program that was written with object extensions to QuickPascal%@EH@%
- would declare an initial "generic shape" object. The generic shape would
- define all of the data and routines──such as draw, erase, and size──that
- were common to every shape. New shapes would be derived from the generic
- shape, and then these new shapes would declare additional data fields,
- override existing routines, and add new ones.%@NL@%
- %@NL@%
- %@CR:MQPF1005@%%@4@%One of the primary benefits of object-oriented programming is the ease with%@EH@%
- which programs can be changed and portions reused. In the hypothetical
- standard Pascal graphics application, to add an octagon shape to the
- program, you would need to declare an entire new type as well as modify each
- routine that dealt with the shapes. With object extensions to QuickPascal,
- you would define an octagon object, already derived from the generic shape
- object, and add or modify any data or routines the octagon exclusively used.
- The old routines would still operate the same way on old types of objects.
- Instead of making changes throughout the entire program, all of the changes
- would occur in one localized area and apply only to that object or its
- descendants.%@NL@%
- %@NL@%
- %@CR:MQPF1006@%%@4@%The example in Section 15.5%@BO: 8198a@% demonstrates basic object-oriented programming%@EH@%
- techniques.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF2000@%%@2@%%@AB@%15.2 Object Programming Concepts%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF2001@%%@4@%Object-oriented extensions are based on four concepts: classes, objects,%@EH@%
- methods, and inheritance. A "class" is similar to a Pascal %@AB@%RECORD%@AE@%. It
- describes an overall structure for any number of types based upon it. The
- main difference between a class and a record is that a class combines data
- fields (called "instance variables") and procedures and functions (called
- "methods") that act upon the data. Instance variables can include standard
- Pascal data types as well as objects.%@NL@%
- %@NL@%
- %@CR:MQPF2002@%%@4@%An "object" is a variable of a class (often called a class instance). Like a%@EH@%
- class, an object is declared as a %@AB@%TYPE%@AE@%. All objects derived from a class are
- considered members of that class and share similar characteristics of the
- superclass.%@NL@%
- %@NL@%
- %@CR:MQPF2003@%%@4@%"Methods" are procedures and functions encapsulated in a class or object.%@EH@%
- Calling a method is referred to as "passing a message to an object." The
- object extensions to QuickPascal create programs that do most of their work
- by sending messages to objects, and by instructing objects to send messages
- to each other. Methods are stored in an object-type method table and do not
- occupy memory when an object is declared as a variable.%@NL@%
- %@NL@%
- %@CR:MQPF2004@%%@4@%Members of the same class exhibit similar behavior through inheritance. This%@EH@%
- means the variable instances and methods found in a superclass are also
- present in objects derived from the superclass. Additionally, objects have
- their own space for storing data and methods local to the object. If
- necessary, an object can also override a parent class's method, replacing
- the inherited method's instructions with its own. If it does, only the
- descendant object's methods are altered, while the parent's remain
- unchanged.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF3000@%%@2@%%@AB@%15.3 Using Objects%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF3001@%%@4@%As mentioned before, the object extensions to QuickPascal add only a few new%@EH@%
- keywords and types. All of the standard Pascal identifiers, constructs, and
- routines are available when programming with objects. The differences in
- using object extensions are in the areas of declaring class and object data
- structures and of calling procedures and functions through methods.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF3100@%%@3@%%@AB@%15.3.1 Setting the Method Compiler Directive%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF3101@%%@4@%The first step in using object extensions is to enable the Method compiler%@EH@%
- directive. The %@AB@%{$M+}%@AE@% directive should appear at the beginning of any source
- file that uses objects. (The %@AB@%{$M+}%@AE@% directive is enabled by default.) This
- directive instructs the compiler to check whether or not memory for an
- object has been allocated before the object's method is executed. See
- Appendix B%@BO: 857d9@%, "Compiler Directives," for more information.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF3200@%%@3@%%@AB@%15.3.2 Creating Classes%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF3201@%%@4@%Since all objects are derived from classes, classes are created first. A%@EH@%
- class should incorporate all data and methods that descendant objects will
- have in common.%@NL@%
- %@NL@%
- %@CR:MQPF3202@%%@4@%You use the following syntax to declare an object class:%@EH@%%@NL@%
- %@NL@%
- %@AB@%TYPE%@AE@%%@NL@%
- %@AI@%ClassName%@AE@% %@AB@%= OBJECT%@AE@%%@NL@%
- %@AI@%DataFields%@AE@%%@NL@%
- %@AB@%{PROCEDURE|FUNCTION}%@AE@%«%@AI@%Methods%@AE@%»%@NL@%
- %@AB@%END;%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPF3203@%%@4@%The parts of the syntax are defined below:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF3204@%%@AB@%Argument Discription %@AE@%%@NL@%
- %@NL@%
- %@AI@%ClassName%@AE@% A unique name that identifies the class.%@NL@%
- %@NL@%
- %@AB@%OBJECT%@AE@% A QuickPascal keyword that instructs the%@NL@%
- compiler to treat the structure as an object.%@NL@%
- %@NL@%
- %@AI@%DataFields%@AE@% The declaration of one or more data structures.%@NL@%
- The syntax is the same as that used for%@NL@%
- declaring the fields of a record.%@NL@%
- %@NL@%
- %@AI@%Methods%@AE@% A list of method declarations. Each method%@NL@%
- declaration is like a procedure or function%@NL@%
- heading, except that the name may be qualified%@NL@%
- with the name of the class:%@NL@%
- %@AI@%ClassName.MethodName%@AE@%. Although not required,%@NL@%
- such a qualification is good programming style.%@NL@%
- Methods are declared immediately following the%@NL@%
- class and object type declarations.%@NL@%
- %@NL@%
- %@CR:MQPF3205@%%@4@%For example, the following code fragment creates a generic shape for a%@EH@%
- graphics program:%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% shape = OBJECT%@NL@%
- %@AS@% color: colors;%@NL@%
- %@AS@% height, width: Integer;%@NL@%
- %@AS@% PROCEDURE shape.init;%@NL@%
- %@AS@% PROCEDURE shape.draw;%@NL@%
- %@AS@% PROCEDURE shape.move(hoz, vert: Integer);%@NL@%
- %@AS@% FUNCTION shape.area: Integer;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE shape.init%@NL@%
- %@AS@% BEGIN { code for init method here }%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE shape.draw;%@NL@%
- %@AS@% BEGIN { code for draw method here }%@NL@%
- %@AS@% . { remainder of methods }%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF3300@%%@3@%%@AB@%15.3.3 Creating Subclasses%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF3301@%%@4@%Once a class has been created, subclasses can be defined. The syntax for%@EH@%
- creating a subclass is similar to that of a class:%@NL@%
- %@NL@%
- %@AB@%TYPE%@AE@%%@NL@%
- %@AI@%ObjectName%@AE@%%@AB@% = OBJECT( %@AE@%%@AI@%ParentClass%@AE@% %@AB@%)%@AE@%%@NL@%
- %@AI@%DataFields%@AE@%%@NL@%
- %@AB@%{PROCEDURE|FUNCTION}%@AE@%«%@AI@%Methods%@AE@%» «%@AB@%; OVERRIDE%@AE@% »%@NL@%
- %@AB@%END;%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPF3302@%%@4@%The two special aspects of declaring objects are the use of parent class and%@EH@%
- of overriding inherited methods. The argument %@AI@%ParentClass%@AE@% is the name of a
- parent class. Since the subclass is derived from a class, you would enclose
- the name of the class in parentheses.%@NL@%
- %@NL@%
- %@CR:MQPF3303@%%@4@%If the subclass redefines a method from the parent class, the %@AB@%OVERRIDE%@AE@%%@EH@%
- statement should appear after the method header.%@NL@%
- %@NL@%
- %@CR:MQPF3304@%%@4@%For example, the following code fragment declares a descendant of the %@AS@%shape%@AE@%%@EH@%
- class:%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@AS@% circle = OBJECT(shape)%@NL@%
- %@AS@% radius: Integer;%@NL@%
- %@AS@% PROCEDURE circle.init; OVERRIDE;%@NL@%
- %@AS@% PROCEDURE circle.draw; OVERRIDE;%@NL@%
- %@AS@% FUNCTION circle.area: Integer; OVERRIDE;%@NL@%
- %@AS@% PROCEDURE circle.changeradius(new_radius: Integer);%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQPF3305@%%@4@%Because the circle type is being derived from the %@AS@%shape%@AE@% class, there is no%@EH@%
- need to declare all of the instance variables and methods from %@AS@%shape%@AE@%. The
- only variables and methods that need declaring are those that are new and
- exclusive to the %@AS@%circle%@AE@% object. In this case, the new items are the %@AS@%radius%@AE@%
- field and the %@AS@%changeradius%@AE@% method. A %@AS@%circle%@AE@% object will have color, height,
- width, and radius fields.%@NL@%
- %@NL@%
- %@CR:MQPF3306@%%@4@%Since the %@AS@%init%@AE@%, %@AS@%draw%@AE@%, and %@AS@%area%@AE@% methods will be different for %@AS@%circle%@AE@% than%@EH@%
- they were for %@AS@%shape%@AE@%, the %@AB@%OVERRIDE%@AE@% keyword instructs the compiler to use the
- method local to %@AS@%circle%@AE@% when one of these messages is passed to the object.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF3400@%%@3@%%@AB@%15.3.4 Defining Methods%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF3401@%%@4@%After a method has been associated with an object, it must be defined.%@EH@%
- Methods are defined with the %@AB@%PROCEDURE%@AE@% or %@AB@%FUNCTION%@AE@% keywords. The actual
- statements that compose the method are defined after all classes and
- subclasses have been created. Either the %@AB@%PROCEDURE%@AE@% or %@AB@%FUNCTION%@AE@% keyword
- precedes the object name, followed by a period (.) and the method name.
- Methods that are overridden follow the same syntax. (See the example at the
- end of the chapter%@BO: 8198a@%.)%@NL@%
- %@NL@%
- %@CR:MQPF3402@%%@4@%The first method you should define is one that initializes all of the%@EH@%
- object's data fields, allocates memory, or performs any other actions the
- object may need before being used. This method should be called immediately
- after space has been allocated for the object.%@NL@%
- %@NL@%
- %@CR:MQPF3403@%%@4@%Instance variables that belong to the object can be accessed from within a%@EH@%
- method by using their identifier preceded by the pseudovariable %@AB@%Self%@AE@%, as
- shown below:%@NL@%
- %@NL@%
- %@AS@% PROCEDURE circle.init;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Self.color := blue;%@NL@%
- %@AS@% Self.height := 20;%@NL@%
- %@AS@% Self.width := 20;%@NL@%
- %@AS@% Self.radius := 0;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQPF3404@%%@4@%%@AB@%Self%@AE@% simply instructs the object to operate on itself.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF3405@%%@4@%An object's data may be accessed by a program directly, as if the object%@EH@%
- were a record:%@NL@%
- %@NL@%
- %@AS@% the_radius := circle.radius;%@NL@%
- %@NL@%
- %@CR:MQPF3406@%%@4@%Also, to call a method belonging to the object from within a different%@EH@%
- method, you may precede it with the %@AB@%Self%@AE@% variable. In the code fragment
- below, %@AS@%Self.draw%@AE@% is equivalent to %@AS@%circle.draw%@AE@%.%@NL@%
- %@NL@%
- %@AS@% PROCEDURE circle.move(hoz, vert: Integer);%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% .%@NL@%
- %@AS@% Self.draw;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQPF3407@%%@4@%Note that you are not restricted solely to using methods when you use object%@EH@%
- extensions to QuickPascal. Methods are only used with objects. Standard
- Pascal procedures and functions can be implemented to manipulate other forms
- of data.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF3500@%%@3@%%@AB@%15.3.5 Using INHERITED%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF3501@%%@4@%The %@AB@%INHERITED%@AE@% keyword negates an override of an inherited method. If the%@EH@%
- class of method performs only a portion of what an object needs to have
- done, the parent method can be called from the descendant method.%@NL@%
- %@NL@%
- %@CR:MQPF3502@%%@4@%For example, suppose that in the %@AS@%shape%@AE@% initialization method, you set the%@EH@%
- following values:%@NL@%
- %@NL@%
- %@AS@% PROCEDURE shape.init;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% color := blue;%@NL@%
- %@AS@% height := 20;%@NL@%
- %@AS@% width := 20;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@CR:MQPF3503@%%@4@%If the %@AS@%circle%@AE@% object used these values, but overrode the method to%@EH@%
- initialize its own data field, %@AB@%INHERITED%@AE@% could be used to call the ancestor
- method. This would initialize the common fields without needing to
- initialize them in the descendant method.%@NL@%
- %@NL@%
- %@AS@% PROCEDURE circle.init;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% radius := 0;%@NL@%
- %@AS@% INHERITED Self.init;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF3600@%%@3@%%@AB@%15.3.6 Declaring Objects%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF3601@%%@4@%Declaring an object is similar to declaring a dynamic variable. The syntax%@EH@%
- is%@NL@%
- %@NL@%
- %@AB@%VAR%@AE@%%@NL@%
- %@AI@%ObjectIdentifier%@AE@% %@AB@%:%@AE@% %@AI@%Class%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPF3602@%%@4@%%@AI@%ObjectIdentifier%@AE@% is the QuickPascal identifier for the object, and %@AI@%Class%@AE@% is%@EH@%
- the type of the object.%@NL@%
- %@NL@%
- %@CR:MQPF3603@%%@4@%For example, this code declares an object of the class %@AS@%circle%@AE@%:%@EH@%%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@AS@% my_circle: circle;%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF3700@%%@3@%%@AB@%15.3.7 Allocating Memory%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF3701@%%@4@%Before an object can be used in a program, memory space must be allocated%@EH@%
- for it. This is done with the Pascal %@AB@%New%@AE@% procedure:%@NL@%
- %@NL@%
- %@AS@% New( my_circle );%@NL@%
- %@NL@%
- %@CR:MQPF3702@%%@4@%A common mistake in object-oriented programming is forgetting to allocate%@EH@%
- memory for an object and then trying to access it. Allocating memory for
- objects should be one of the first actions of the program body.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF3800@%%@3@%%@AB@%15.3.8 Calling Methods%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF3801@%%@4@%After classes and objects have been declared, and memory has been allocated%@EH@%
- for the object, you can call a method (that is, send a message to the
- object) from within the main body of the program to manipulate the object's
- instance variables. Sending a message is similar to calling a procedure or
- function in standard Pascal. The only difference is that you specify both
- the object and the method.%@NL@%
- %@NL@%
- %@CR:MQPF3802@%%@4@%For example, different methods for %@AS@%my_circle%@AE@% are executed by%@EH@%%@NL@%
- %@NL@%
- %@AS@% my_circle.draw;%@NL@%
- %@AS@% my_circle.move( 30, 30 );%@NL@%
- %@AS@% circle_area := my_circle.area;%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF3900@%%@3@%%@AB@%15.3.9 Testing Membership%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF3901@%%@4@%The %@AB@%Member%@AE@% function tests if a particular object is in a class, as shown%@EH@%
- below:%@NL@%
- %@NL@%
- %@AS@% IF Member( a_circle, shape ) THEN%@NL@%
- %@AS@% num_shapes := num_shapes + 1;%@NL@%
- %@NL@%
- %@CR:MQPF3902@%%@4@%The function is passed the object and the class. It returns %@AB@%True%@AE@% if the%@EH@%
- object is an instance of, or a decendant of, the class.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF3A00@%%@3@%%@AB@%15.3.10 Disposing of Objects%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF3A01@%%@4@%When you are finished using an object, the memory allocated for it should be%@EH@%
- freed. This is done with the %@AB@%Dispose%@AE@% procedure:%@NL@%
- %@NL@%
- %@AS@% Dispose( my_circle );%@NL@%
- %@NL@%
- %@CR:MQPF3A02@%%@4@%Before disposing of an object, be sure it will not be used further in the%@EH@%
- program.%@NL@%
- %@NL@%
- %@CR:MQPF3A03@%%@4@%Often, a free method is declared to reallocate data-structure memory, close%@EH@%
- files, and perform other housecleaning. Such a method should be called
- before using %@AB@%Dispose%@AE@%.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF4000@%%@2@%%@AB@%15.4 Object Programming Strategies%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF4001@%%@4@%The greatest difficulty facing programmers who are learning object%@EH@%
- extensions to QuickPascal is the need to plan and write their programs in an
- object-oriented manner. All too often, a programmer's first object-oriented
- programs exhibit a procedural style with objects sprinkled in haphazardly.
- Programming in this fashion reduces the value of object extensions for
- producing efficient and reusable code. Sections 15.4.1%@BO: 80b96@%-15.4.5 discuss
- several issues you should keep in mind as you create object-oriented
- programs.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF4100@%%@3@%%@AB@%15.4.1 Object Style Conventions%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF4101@%%@4@%Although style conventions for programs are often a matter of personal%@EH@%
- preference, adoption of certain style conventions for object programming can
- make your source code easier to read. For example, since both a Pascal
- record and an object use a period (%@AB@%.%@AE@%) to access their data fields and
- methods, it can be difficult to distinguish objects from records. This is
- made more complicated by the difficulty telling whether an identifier
- following an object is an instance variable or a method.%@NL@%
- %@NL@%
- %@CR:MQPF4102@%%@4@%Here are some style conventions for object programming:%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF4103@% ■ Classes and objects are preceded with an uppercase "T." This identifies%@NL@%
- the variable as an object type, as shown below:%@NL@%
- %@NL@%
- %@AS@%Tcircle = OBJECT(Tshape)%@AE@%%@NL@%
- %@NL@%
- ■ Object instance variables are preceded with a lowercase "f." The "f"%@NL@%
- indicates at a glance that the identifier is a field. Identifiers%@NL@%
- without the "f" are methods, as in the following example:%@NL@%
- %@NL@%
- %@AS@%the_radius := Tcircle.fradius;%@AE@%%@NL@%
- %@AS@%Tcircle.draw;%@AE@%%@NL@%
- %@NL@%
- ■ Global variables are preceded with a lowercase "g." This is helpful in%@NL@%
- identifying objects that can be passed messages from objects outside%@NL@%
- their own class (see below):%@NL@%
- %@NL@%
- %@AS@%gTtemp_circle.color := blue;%@AE@%%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF4200@%%@3@%%@AB@%15.4.2 Object Reusability%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF4201@%%@4@%The essence of object-oriented programming is reusability. When you create%@EH@%
- objects, you should give some thought to their future use, both in terms of
- the current program and for later ones. It's best to create classes from
- which other objects can be derived. Inheriting methods is generally more
- important than inheriting data. On a larger scale, class libraries are
- useful for dealing with common tasks. A set of related classes can reside in
- a %@AB@%UNIT%@AE@% and be called at any time.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF4300@%%@3@%%@AB@%15.4.3 Modularity%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF4301@%%@4@%Object extensions to QuickPascal lend themselves to modularized programs. A%@EH@%
- class's methods can easily be kept together, instead of being strung out
- through the source code. A properly constructed object program should
- require only a few localized modifications to add and alter methods.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF4400@%%@3@%%@AB@%15.4.4 Methods%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF4401@%%@4@%Methods should be treated as replaceable components of the object building%@EH@%
- blocks of QuickPascal. Methods are designed to serve a single purpose; a
- method that is multipurpose is more difficult to modify because it performs
- a variety of tasks. Whenever you want to perform an action, create a method
- to do it. Methods should be short, at most several dozen statements in
- length.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF4500@%%@3@%%@AB@%15.4.5 Data Fields%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF4501@%%@4@%It isn't necessary to declare an instance variable for each data item an%@EH@%
- object may use. If more than one object method uses a specific data item,
- the data should be incorporated as an instance variable. If only a single
- method accesses the data, it can be passed as a parameter to the method. You
- should use object instance variables in place of global variables to promote
- modularity.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPF5000@%%@2@%%@AB@%15.5 Example Program%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPF5001@%%@4@%This example shows how a typical object-oriented program works. A class is%@EH@%
- declared (%@AS@%geo_shape%@AE@%), with two subclasses ( %@AS@%rectangle%@AE@% and %@AS@%circle%@AE@%). Both the
- subclasses demonstrate how to add instance variables and methods and how to
- override existing parent methods. The body of the OBJECTDE.PAS program has
- examples of defining methods, accessing instance variables, and declaring
- and disposing of objects.%@NL@%
- %@NL@%
- %@AS@% Program objectdemo;%@NL@%
- %@AS@% { Demonstrates object techniques with geometric shapes }%@NL@%
- %@NL@%
- %@AS@% {M+}%@NL@%
- %@NL@%
- %@AS@% TYPE%@NL@%
- %@NL@%
- %@AS@% geo_shape = OBJECT%@NL@%
- %@AS@% area: Real;%@NL@%
- %@AS@% height: Real;%@NL@%
- %@AS@% what: STRING;%@NL@%
- %@AS@% PROCEDURE geo_shape.init;%@NL@%
- %@AS@% PROCEDURE geo_shape.say_what;%@NL@%
- %@AS@% FUNCTION geo_shape.get_area : Real;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% rectangle = OBJECT(geo_shape)%@NL@%
- %@AS@% len: Real;%@NL@%
- %@AS@% FUNCTION rectangle.is_square : Boolean;%@NL@%
- %@AS@% PROCEDURE rectangle.init; OVERRIDE;%@NL@%
- %@AS@% FUNCTION rectangle.get_area : Real; OVERRIDE;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% circle = OBJECT(geo_shape)%@NL@%
- %@AS@% radius: Real;%@NL@%
- %@AS@% PROCEDURE circle.init; OVERRIDE;%@NL@%
- %@AS@% FUNCTION circle.get_area : Real; OVERRIDE;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE geo_shape.init;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Self.area := 0;%@NL@%
- %@AS@% Self.height := 0;%@NL@%
- %@AS@% Self.what := 'Geometric shape';%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE geo_shape.say_what;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Writeln(Self.what);%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% FUNCTION geo_shape.get_area : Real;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Self.area := Self.height * Self.height;%@NL@%
- %@AS@% get_area := Self.height;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE circle.init;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% INHERITED Self.init;%@NL@%
- %@AS@% Self.radius := 4;%@NL@%
- %@AS@% Self.what := 'circle';%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% FUNCTION circle.get_area: Real;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Self.area := ( Pi * Sqr( Self.radius ) );%@NL@%
- %@AS@% get_area := Self.area;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% PROCEDURE rectangle.init;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% INHERITED Self.init;%@NL@%
- %@AS@% Self.height := 5;%@NL@%
- %@AS@% Self.len := 5;%@NL@%
- %@AS@% Self.what := 'Rectangle';%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% FUNCTION rectangle.is_square: Boolean;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% is_square := False;%@NL@%
- %@AS@% IF Self.len = Self.height THEN%@NL@%
- %@AS@% is_square := True;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% FUNCTION rectangle.get_area: Real;%@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% Self.area := ( Self.len * Self.height );%@NL@%
- %@AS@% get_area := Self.area;%@NL@%
- %@AS@% END;%@NL@%
- %@NL@%
- %@AS@% VAR%@NL@%
- %@NL@%
- %@AS@% the_circle : circle;%@NL@%
- %@AS@% the_rect : rectangle;%@NL@%
- %@NL@%
- %@AS@% BEGIN%@NL@%
- %@AS@% New( the_circle );%@NL@%
- %@AS@% the_circle.init;%@NL@%
- %@AS@% New( the_rect );%@NL@%
- %@AS@% the_rect.init;%@NL@%
- %@NL@%
- %@AS@% the_circle.say_what;%@NL@%
- %@AS@% Writeln( 'area: ', the_circle.get_area );%@NL@%
- %@NL@%
- %@AS@% Writeln;%@NL@%
- %@NL@%
- %@AS@% the_rect.say_what;%@NL@%
- %@AS@% Writeln( 'area: ', the_rect.get_area );%@NL@%
- %@NL@%
- %@AS@% Dispose( the_circle );%@NL@%
- %@AS@% Dispose( the_rect );%@NL@%
- %@AS@% END.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPa0000@%%@1@%%@AB@%Appendix A ASCII Character Codes and Extended Key Codes%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPa1000@%%@2@%%@AB@%A.1 ASCII Character Codes%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPa1001@%%@4@%The ASCII character codes for printable and control characters are listed on%@EH@%
- the following two pages. The value of each character is its ordinal value
- within the type %@AB@%Char%@AE@%. For example, Ord ( 'P' ) returns the decimal value
- 80.%@NL@%
- %@NL@%
- %@AB@%Ctl%@AE@%%@FN@%
- Control Code%@EF@% %@AB@%D%@AE@%%@FN@%
- Decimal%@EF@% %@AB@%H%@AE@%%@FN@%
- Hexidecimal%@EF@% %@AB@%O%@AE@%%@FN@%
- Octal%@EF@% %@AB@%C%@AE@%%@FN@%
- Character%@EF@% %@AB@%Code%@AE@% %@AB@%D%@AE@%%@FN@%
- Decimal%@EF@% %@AB@%H%@AE@%%@FN@%
- Hexidecimal%@EF@% %@AB@%O%@AE@%%@FN@%
- Octal%@EF@% %@AB@%C%@AE@%%@FN@%
- Character%@EF@% %@AB@%D%@AE@%%@FN@%
- Decimal%@EF@% %@AB@%H%@AE@%%@FN@%
- Hexideciaml%@EF@% %@AB@%O%@AE@%%@FN@%
- Octal%@EF@% %@AB@%C%@AE@%%@FN@%
- Character%@EF@% %@AB@%D%@AE@%%@FN@%
- Decimal%@EF@% %@AB@%H%@AE@%%@FN@%
- Hexidecimal%@EF@% %@AB@%O%@AE@%%@FN@%
- Octal%@EF@% %@AB@%C%@AE@%%@FN@%
- Character%@EF@%%@NL@%
- %@NL@%
- ^@ 0 00 000 NUL│ 32 20 040 │ 64 40 100 @ │ 96 60 140 `%@NL@%
- ^A 1 01 001 SOH│ 33 21 041 ! │ 65 41 101 A │ 97 61 141 a%@NL@%
- ^B 2 02 002 STX│ 34 22 042 " │ 66 42 102 B │ 98 62 142 b%@NL@%
- ^C 3 03 003 ETX│ 35 23 043 # │ 67 43 103 C │ 99 63 143 c%@NL@%
- ^D 4 04 004 EOT│ 36 24 044 $ │ 68 44 104 D │ 100 64 144 d%@NL@%
- ^E 5 05 005 ENQ│ 37 25 045 % │ 69 45 105 E │ 101 65 145 e%@NL@%
- ^F 6 06 006 ACK│ 38 26 046 & │ 70 46 106 F │ 102 66 146 f%@NL@%
- ^G 7 07 007 BEL│ 39 27 047 ' │ 71 47 107 G │ 103 67 147 g%@NL@%
- ^H 8 08 010 BS │ 40 28 050 ( │ 72 48 110 H │ 104 68 150 h%@NL@%
- ^I 9 09 011 HT │ 41 29 051 ) │ 73 49 111 I │ 105 69 151 i%@NL@%
- ^J 10 0A 012 LF │ 42 2A 052 * │ 74 4A 112 J │ 106 6A 152 j%@NL@%
- ^K 11 0B 013 VT │ 43 2B 053 + │ 75 4B 113 K │ 107 6B 153 k%@NL@%
- ^L 12 0C 014 FF │ 44 2C 054 , │ 76 4C 114 L │ 108 6C 154 l%@NL@%
- ^M 13 0D 015 CR │ 45 2D 055 - │ 77 4D 115 M │ 109 6D 155 m%@NL@%
- ^N 14 0E 016 SO │ 46 2E 056 . │ 78 4E 116 N │ 110 6E 156 n%@NL@%
- ^O 15 0F 017 SI │ 47 2F 057 / │ 79 4F 117 O │ 111 6F 157 o%@NL@%
- ^P 16 10 020 DLE│ 48 30 060 0 │ 80 50 120 P │ 112 70 160 p%@NL@%
- ^Q 17 11 021 DC1│ 49 31 061 1 │ 81 51 121 Q │ 113 71 161 q%@NL@%
- ^R 18 12 022 DC2│ 50 32 062 2 │ 82 52 122 R │ 114 72 162 r%@NL@%
- ^S 19 13 023 DC3│ 51 33 063 3 │ 83 53 123 S │ 115 73 163 s%@NL@%
- ^T 20 14 024 DC4│ 52 34 064 4 │ 84 54 124 T │ 116 74 164 t%@NL@%
- ^U 21 15 025 NAK│ 53 35 065 5 │ 85 55 125 U │ 117 75 165 u%@NL@%
- ^V 22 16 026 SYN│ 54 36 066 6 │ 86 56 126 V │ 118 76 166 v%@NL@%
- ^W 23 17 027 ETB│ 55 37 067 7 │ 87 57 127 W │ 119 77 167 w%@NL@%
- ^X 24 18 030 CAN│ 56 38 070 8 │ 88 58 130 X │ 120 78 170 x%@NL@%
- ^Y 25 19 031 EM │ 57 39 071 9 │ 89 59 131 Y │ 121 79 171 y%@NL@%
- ^Z 26 1A 032 SUB│ 58 3A 072 : │ 90 5A 132 Z │ 122 7A 172 z%@NL@%
- ^[ 27 1B 033 ESC│ 59 3B 073 ; │ 91 5B 133 [ │ 123 7B 173 {%@NL@%
- ^\ 28 1C 034 FS │ 60 3C 074 < │ 92 5C 134 \ │ 124 7C 174 |%@NL@%
- ^] 29 1D 035 GS │ 61 3D 075 = │ 93 5D 135 ] │ 125 7D 175 }%@NL@%
- ^^ 30 1E 036 RS │ 62 3E 076 > │ 94 5E 136 ^ │ 126 7E 176 ~%@NL@%
- ^_ 31 1F 037 US │ 63 3F 077 ? │ 95 5F 137 _ │ 127 7F 177 %@FN@%
- ASCII code 127 has the code DEL. Under DOS, this code has the same effect as
- ASCII 8 (BS). The DEL code can be generated by the CTRL+BKSP key
- combination.%@EF@%%@NL@%
- %@NL@%
- %@NL@%
- %@NL@%
- %@AB@%D%@AE@%%@FN@%
- Decimal%@EF@% %@AB@%H%@AE@%%@FN@%
- Hexidecimal%@EF@% %@AB@%O%@FN@%
- Octal%@EF@% %@AB@%C%@AE@%%@FN@%
- Character%@EF@% %@AB@%D%@AE@%%@FN@%
- Decimal%@EF@% %@AB@%H%@AE@%%@FN@%
- Hexidecimal%@EF@% %@AB@%O%@AE@%%@FN@%
- Octal%@EF@% %@AB@%C%@AE@%%@FN@%
- Character%@EF@% %@AB@%D%@AE@%%@FN@%
- Decimal%@EF@% %@AB@%H%@AE@%%@FN@%
- Hexidecimal%@EF@% %@AB@%O%@AE@%%@FN@%
- Octal%@EF@% %@AB@%C%@AE@%%@FN@%
- Character%@EF@% %@AB@%D%@AE@%%@FN@%
- Decimal%@EF@% %@AB@%H%@AE@%%@FN@%
- Hexidecimal%@EF@% %@AB@%O%@AE@%%@FN@%
- Octal%@EF@% %@AB@%C%@AE@%%@FN@%
- Character%@EF@%%@NL@%
- %@NL@%
- 128 80 200 Ç │ 160 A0 240 á │ 192 C0 300 └ │ 224 E0 340 α%@NL@%
- 129 81 201 ü │ 161 A1 241 í │ 193 C1 301 ┴ │ 225 E1 341 ß%@NL@%
- 130 82 202 é │ 162 A2 242 ó │ 194 C2 302 ┬ │ 226 E2 342 Γ%@NL@%
- 131 83 203 â │ 163 A3 243 ú │ 195 C3 303 ├ │ 227 E3 343 π%@NL@%
- 132 84 204 ä │ 164 A4 244 ñ │ 196 C4 304 ─ │ 228 E4 344 Σ%@NL@%
- 133 85 205 à │ 165 A5 245 Ñ │ 197 C5 305 ┼ │ 229 E5 345 σ%@NL@%
- 134 86 206 å │ 166 A6 246 ª │ 198 C6 306 ╞ │ 230 E6 346 µ%@NL@%
- 135 87 207 ç │ 167 A7 247 º │ 199 C7 307 ╟ │ 231 E7 347 τ%@NL@%
- 136 88 210 ê │ 168 A8 250 ¿ │ 200 C8 310 ╚ │ 232 E8 350 Φ%@NL@%
- 137 89 211 ë │ 169 A9 251 ⌐ │ 201 C9 311 ╔ │ 233 E9 351 Θ%@NL@%
- 138 8A 212 è │ 170 AA 252 ¬ │ 202 CA 312 ╩ │ 234 EA 352 Ω%@NL@%
- 139 8B 213 ï │ 171 AB 253 ½ │ 203 CB 313 ╦ │ 235 EB 353 δ%@NL@%
- 140 8C 214 î │ 172 AC 254 ¼ │ 204 CC 314 ╠ │ 236 EC 354 ∞%@NL@%
- 141 8D 215 ì │ 173 AD 255 ¡ │ 205 CD 315 ═ │ 237 ED 355 φ%@NL@%
- 142 8E 216 Ä │ 174 AE 256 « │ 206 CE 316 ╬ │ 238 EE 356 ε%@NL@%
- 143 8F 217 Å │ 175 AF 257 » │ 207 CF 317 ╧ │ 239 EF 357 ∩%@NL@%
- 144 90 220 É │ 176 B0 260 ░ │ 208 D0 320 ╨ │ 240 F0 360 ≡%@NL@%
- 145 91 221 æ │ 177 B1 261 ▒ │ 209 D1 321 ╤ │ 241 F1 361 ±%@NL@%
- 146 92 222 Æ │ 178 B2 262 ▓ │ 210 D2 322 ╥ │ 242 F2 362 ≥%@NL@%
- 147 93 223 ô │ 179 B3 263 │ │ 211 D3 323 ╙ │ 243 F3 363 ≤%@NL@%
- 148 94 224 ö │ 180 B4 264 ┤ │ 212 D4 324 ╘ │ 244 F4 364 ⌠%@NL@%
- 149 95 225 ò │ 181 B5 265 ╡ │ 213 D5 325 ╒ │ 245 F5 365 ⌡%@NL@%
- 150 96 226 û │ 182 B6 266 ╢ │ 214 D6 326 ╓ │ 246 F6 366 ÷%@NL@%
- 151 97 227 ù │ 183 B7 267 ╖ │ 215 D7 327 ╫ │ 247 F7 367 ≈%@NL@%
- 152 98 230 ÿ │ 184 B8 270 ╕ │ 216 D8 330 ╪ │ 248 F8 370 °%@NL@%
- 153 99 231 Ö │ 185 B9 271 ╣ │ 217 D9 331 ┘ │ 249 F9 371 ∙%@NL@%
- 154 9A 232 Ü │ 186 BA 272 ║ │ 218 DA 332 ┌ │ 250 FA 372 ·%@NL@%
- 155 9B 233 ¢ │ 187 BB 273 ╗ │ 219 DB 333 █ │ 251 FB 373 √%@NL@%
- 156 9C 234 £ │ 188 BC 274 ╝ │ 220 DC 334 ▄ │ 252 FC 374 ⁿ%@NL@%
- 157 9D 235 ¥ │ 189 BD 275 ╜ │ 221 DD 335 ▌ │ 253 FD 375 ²%@NL@%
- 158 9E 236 ₧ │ 190 BE 276 ╛ │ 222 DE 336 ▐ │ 254 FE 376 ■%@NL@%
- 159 9F 237 ƒ │ 191 BF 277 ┐ │ 223 DF 337 ▀ │ 255 FF 377 %@NL@%
- %@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPa2000@%%@2@%%@AB@%A.2 Extended-Key Codes%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPa2001@%%@4@%The %@AB@%Crt%@AE@% unit's %@AB@%ReadKey%@AE@% function returns a pair of values (instead of a%@EH@%
- single ASCII character) when a key on an extended keyboard is pressed. The
- first code is a null character (ASCII 0), which indicates that the next
- character will be an extended-key code.%@NL@%
- %@NL@%
- %@CR:MQPa2002@%%@4@%This table lists the key or key combination along with the decimal%@EH@%
- extended-key code. This information is also available in the on-line help
- (in a form that can be pasted directly into your program).%@NL@%
- %@CR:MQPaT100@%%@NL@%
- %@TH: 63 4000 2 17 16 17 16 10 @%
- %@AB@%Key Type Extended Key Code Extended Key Code%@AE@%
-
- %@AB@%Arrow%@AE@% UP 72 DOWN 80
- LEFT 75 RIGHT 77
- PGUP 73 PGDN 81
- HOME 71 END 79
- INS 82 DEL 83
-
- %@AB@%CTRL +%@AE@% CTRL+PRTSC 114 CTRL+HOME 119
- %@AB@%Arrow%@AE@% CTRL+LEFT 115 CTRL+END 117
- CTRL+RIGHT 116
- CTRL+PGUP 132 Null key 3
- CTRL+PGDN 118 SHIFT+TAB 15
-
- %@AB@%ALT +%@AE@% ALT+A 30 ALT+N 49
- %@AB@%Letter%@AE@% ALT+B 48 ALT+O 24
- ALT+C 46 ALT+P 25
- ALT+D 32 ALT+Q 16
- ALT+E 18 ALT+R 19
- ALT+F 33 ALT+S 31
- ALT+G 34 ALT+T 20
- ALT+H 35 ALT+U 22
- ALT+I 23 ALT+V 47
- ALT+J 36 ALT+W 17
- ALT+K 37 ALT+X 45
- ALT+L 38 ALT+Y 21
- ALT+M 50 ALT+Z 44
-
- %@AB@%ALT +%@AE@% ALT+1 120 ALT+6 125
- %@AB@%Number%@AE@% ALT+2 121 ALT+7 126
- ALT+3 122 ALT+8 127
- ALT+4 123 ALT+9 128
- ALT+5 124 ALT+0 129
- ALT+MINUS 130 ALT+= 131
-
- %@AB@%Function%@AE@% F1 59 F6 64
- F2 60 F7 65
- F3 61 F8 66
- F4 62 F9 67
- F5 63 F10 68
-
- %@AB@%SHIFT +%@AE@% SHIFT+F1 84 SHIFT+F6 89
- %@AB@%Function%@AE@% SHIFT+F2 85 SHIFT+F7 90
- SHIFT+F3 86 SHIFT+F8 91
- SHIFT+F4 87 SHIFT+F9 92
- SHIFT+F5 88 SHIFT+F10 93
-
- %@AB@%CTRL +%@AE@% CTRL+F1 94 CTRL+F6 99
- %@AB@%Function%@AE@% CTRL+F2 95 CTRL+F7 100
- CTRL+F3 96 CTRL+F8 101
- CTRL+F4 97 CTRL+F9 102
- CTRL+F5 98 CTRL+F10 103
-
- %@AB@%ALT +%@AE@% ALT+F1 104 ALT+F6 109
- %@AB@%Function%@AE@% ALT+F2 105 ALT+F7 110
- ALT+F3 106 ALT+F8 111
- ALT+F4 107 ALT+F9 112
- ALT+F5 108 ALT+F10 113
-
- %@AB@%Extended%@AE@% F11 133 F12 134
- %@AB@%Function%@AE@% SHIFT+F11 135 SHIFT+F12 136
- CTRL+F11 137 CTRL+F12 138
- ALT+F11 139 ALT+F12 140
- %@TE: 63 4000 2 17 16 17 16 10 @%
- %@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPb0000@%%@1@%%@AB@%Appendix B Compiler Directives%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQPb0001@%%@4@%QuickPascal uses a variety of compiler directives to affect code output.%@EH@%
- They can be classed as%@NL@%
- %@NL@%
- %@CR:MQPb0002@% ■ Switch Directives (on and off switches that control compiler options)%@NL@%
- %@NL@%
- ■ Parameter Directives (commands that require numbers or a file name)%@NL@%
- %@NL@%
- ■ Conditional Directives (commands that compile specific portions of the%@NL@%
- source file, depending if certain conditions are met)%@NL@%
- %@NL@%
- %@CR:MQPb0003@%%@4@%Compiler directives can be specified in the source file, in the QuickPascal%@EH@%
- environment, or at the DOS command line.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPb1000@%%@2@%%@AB@%B.1 Switch Directives%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb1001@%%@4@%Switch directives are identified by a single letter enclosed in braces. The%@EH@%
- letter is preceded by a dollar sign ($) and is followed by either a plus (+)
- that enables the switch, or a minus (-) that disables it. If you do not
- specify a switch directive, the default setting will automatically be used.%@NL@%
- %@NL@%
- %@CR:MQPb1002@%%@4@%A space must not come between the left brace and the dollar sign. If one%@EH@%
- does, the compiler considers the line to be a comment. This is useful for
- commenting out directives.%@NL@%
- %@NL@%
- %@CR:MQPb1003@%%@4@%Multiple switches can be set in a single statement. For example,%@EH@%%@NL@%
- %@NL@%
- {$A-,S+,R-,V+}%@NL@%
- %@NL@%
- %@CR:MQPb1004@%%@4@%Certain switch directives must be declared globally at the beginning of the%@EH@%
- program, just after the header. That is, they must appear before any data
- declaration or code. Other switch directives can occur locally, anywhere
- within the source file.%@NL@%
- %@NL@%
- %@CR:MQPb1005@%%@4@%The individual switch directives are described below.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb1006@%%@4@%%@AB@%Align Data%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb1007@%%@AB@%{$A+}%@AE@% or %@AB@%{$A-}%@AE@%%@NL@%
- Default: %@AB@%{$A+}%@AE@%%@NL@%
- Type: Local%@NL@%
- %@NL@%
- %@CR:MQPb1008@%%@4@%Changes from byte alignment to word alignment of typed constants and%@EH@%
- variables. When the align data directive is enabled, all typed constants and
- variables larger than one byte are aligned on a machine-word boundary.
- Although word alignment does not affect program execution on the 8088
- processor, on 80x86 processors, programs can execute faster since word-sized
- items are accessed in one memory cycle.%@NL@%
- %@NL@%
- %@CR:MQPb1009@%%@4@%When the directive is disabled, no alignment occurs, and all typed constants%@EH@%
- and variables are placed at the next available memory address.%@NL@%
- %@NL@%
- %@CR:MQPb100A@%%@4@%%@AB@%Boolean Evaluation%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb100B@%%@AB@%{$B+}%@AE@% or %@AB@%{$B-}%@AE@%%@NL@%
- Default: %@AB@%{$B-}%@AE@%%@NL@%
- Type: Local%@NL@%
- %@NL@%
- %@CR:MQPb100C@%%@4@%Determines which type of code will be generated for the Boolean %@AB@%AND%@AE@% and %@AB@%OR%@AE@%%@EH@%
- operators. When the directive is enabled, code is created for the complete
- Boolean expression, even if the result is already known. If the directive is
- disabled (the default), the evaluation stops as soon as the result becomes
- evident, resulting in faster programs. Enable this switch when the second or
- subsequent operands in the Boolean expression include a procedure or
- function call that needs to be executed, regardless of the value of the
- first operand.%@NL@%
- %@NL@%
- %@CR:MQPb100D@%%@4@%%@AB@%Debug Information%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb100E@%%@AB@%{$D+}%@AE@% or %@AB@%{$D-}%@AE@%%@NL@%
- Default: %@AB@%{$D+}%@AE@%%@NL@%
- Type: Global%@NL@%
- %@NL@%
- %@CR:MQPb100F@%%@4@%Inserts debugging information into your compiled program. When the directive%@EH@%
- is enabled, you can use the QuickPascal debugger to single step through code
- to view VARS, you need %@AB@%{$L+}%@AE@%. Additionally, when a run-time error is
- reported, QuickPascal will move to the line in the source code that caused
- the error.%@NL@%
- %@NL@%
- %@CR:MQPb100G@%%@4@%%@AB@%FAR Calls%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb100H@%%@AB@%{$F+}%@AE@% or %@AB@%{$F-}%@AE@%%@NL@%
- Default: %@AB@%{$F-}%@AE@%%@NL@%
- Type: Local%@NL@%
- %@NL@%
- %@CR:MQPb100I@%%@4@%Determines which model is used for compiled procedures and functions. When%@EH@%
- the FAR calls directive is enabled, procedures and functions always use the
- FAR call model. If the directive is disabled, QuickPascal determines the
- call model based on location of the routine. If the procedure or function is
- declared in the %@AB@%INTERFACE%@AE@% portion of a unit, the FAR model is used.
- Otherwise, the NEAR model is used.%@NL@%
- %@NL@%
- %@CR:MQPb100J@%%@4@%See Chapter 12%@BO: 517ed@%, "Advanced Topics," for a full discussion of FAR and NEAR%@EH@%
- call models.%@NL@%
- %@NL@%
- %@CR:MQPb100K@%%@4@%%@AB@%I/O Checking%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb100L@%%@AB@%{$I+}%@AE@% or %@AB@%{$I-}%@AE@%%@NL@%
- Default: %@AB@%{$I+}%@AE@%%@NL@%
- Type: Local%@NL@%
- %@NL@%
- %@CR:MQPb100M@%%@4@%Generates code that examines the result of an input/output procedure. If an%@EH@%
- I/O error occurs while the directive is enabled, the program displays a
- run-time error and terminates. If the I/O checking directive is disabled,
- you should use the %@AB@%IOResult%@AE@% function to check for I/O errors. See Chapter 9%@BO: 3efa5@%,
- "Text Files," for more information on I/O routines.%@NL@%
- %@NL@%
- %@CR:MQPb100N@%%@4@%%@AB@%Local Symbol Data%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb100O@%%@AB@%{$L+}%@AE@% or %@AB@%{$L-}%@AE@%%@NL@%
- Default: %@AB@%{$L+}%@AE@%%@NL@%
- Type: Global%@NL@%
- %@NL@%
- %@CR:MQPb100P@%%@4@%Generates symbol information in your compiled code. When the directive is%@EH@%
- enabled, you can use the QuickPascal debugger to examine and modify
- variables within your program. The local symbol data directive is used in
- conjunction with the debug information directive. If the debug information
- directive is disabled, the local symbol data directive is automatically
- disabled.%@NL@%
- %@NL@%
- %@CR:MQPb100Q@%%@4@%%@AB@%Method Checking%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb100R@%%@AB@%{$M+}%@AE@% or %@AB@%{$M-}%@AE@%%@NL@%
- Default: %@AB@%{$M-}%@AE@%%@NL@%
- Type: Global%@NL@%
- %@NL@%
- %@CR:MQPb100S@%%@4@%Determines if memory for an object has been allocated before an object's%@EH@%
- method is called. If the directive is enabled and an object hasn't had
- memory allocated, a run-time error is generated. You should always enable
- the method-checking directive when you are using objects and programming in
- object-oriented Pascal.%@NL@%
- %@NL@%
- %@CR:MQPb100T@%%@4@%%@AB@%Numeric Processing%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb100U@%%@AB@%{$N+}%@AE@% or %@AB@%{$N-}%@AE@%%@NL@%
- Default: %@AB@%{$N-}%@AE@%%@NL@%
- Type: Global%@NL@%
- %@NL@%
- %@CR:MQPb100V@%%@4@%Specifies which model of floating-point code is generated by the compiler.%@EH@%
- When the directive is enabled, all floating-point calculations are performed
- by the 80x87 math coprocessor. If the directive is disabled, all real type
- calculations are performed in software using the run-time libraries.%@NL@%
- %@NL@%
- %@CR:MQPb100W@%%@4@%When the directive is enabled (%@AB@%$N+%@AE@%), the resulting program will run only on%@EH@%
- machines equipped with 80x87 coprocessors. Attempting to run the program on
- a computer that is not 80x87-equipped generates an error message informing
- the user that a coprocessor is required.%@NL@%
- %@NL@%
- %@CR:MQPb100X@%%@4@%When the directive is disabled (%@AB@%$N-%@AE@%), the resulting program will run on any%@EH@%
- machine, whether or not it has a coprocessor. However, the code will not use
- the coprocessor, even if present. Use of the %@AB@%$N-%@AE@% directive involves some
- differences in the way %@AB@%Extended%@AE@% and %@AB@%Comp%@AE@% data types are handled. See Chapter
- 2%@BO: bdde@%, "Programming Basics," for more information.%@NL@%
- %@NL@%
- %@CR:MQPb100Y@%%@4@%%@AB@%Range Checking%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb100Z@%%@AB@%{$R+}%@AE@% or %@AB@%{$R-}%@AE@%%@NL@%
- Default: %@AB@%{$R-}%@AE@%%@NL@%
- Type: Local%@NL@%
- %@NL@%
- %@CR:MQPb100a@%%@4@%Generates code that determines if all array and string indexing expressions%@EH@%
- are within bounds, and all assignments to scalar and subrange variables are
- within range. If range checking fails while the directive is enabled, a
- run-time error is reported. The range checking directive should be used
- only for debugging, as it decreases program performance and increases
- program size.%@NL@%
- %@NL@%
- %@CR:MQPb100b@%%@4@%%@AB@%Stack Checking%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb100c@%%@AB@%{$S+}%@AE@% or %@AB@%{$S-}%@AE@%
- Default: %@AB@%{$S+}%@AE@%
- Type: Local%@NL@%
- %@NL@%
- %@CR:MQPb100d@%%@4@%Creates code that checks whether enough space remains on the stack for local%@EH@%
- variables before executing a procedure or function. If a stack overflow
- occurs when the directive is enabled, the program displays a run-time error
- message and terminates.%@NL@%
- %@NL@%
- %@CR:MQPb100e@%%@4@%%@AB@%VAR String Checking%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb100f@%%@AB@%{$V+}%@AE@% or %@AB@%{$V-}%@AE@%
- Default: %@AB@%{$V+}%@AE@%
- Type: Local%@NL@%
- %@NL@%
- %@CR:MQPb100g@%%@4@%Compares the declared type of a %@AB@%VAR%@AE@% type string parameter with the string%@EH@%
- type actually being passed as a parameter when the directive is enabled. The
- types must be identical. If the directive is disabled, no type checking is
- performed.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPb2000@%%@2@%%@AB@%B.2 Parameter Directives%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb2001@%%@4@%Parameter directives instruct the compiler to take a certain action, based%@EH@%
- on parameters that are passed to the compiler. A space always separates the
- single directive letter and the parameter.%@NL@%
- %@NL@%
- %@CR:MQPb2002@%%@4@%The individual parameter directives are described below.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb2003@%%@4@%%@AB@%Include%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb2004@%%@AB@%{$I%@AE@%%@AI@%Filename%@AE@%%@AB@%}%@AE@%%@NL@%
- Type: Local%@NL@%
- %@NL@%
- %@CR:MQPb2005@%%@4@%Includes a named source file in the compilation immediately after the%@EH@%
- directive. QuickPascal assumes the .INC extension if none is specified. If
- the include file is in a different path from the one defined in the
- QuickPascal Environment command in the Options menu, you must type in the
- entire pathname.%@NL@%
- %@NL@%
- %@CR:MQPb2006@%%@4@%You cannot have an include file within a %@AB@%BEGIN...END%@AE@% block.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb2007@%%@4@%%@AB@%Link%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb2008@%%@AB@%{$L%@AE@%%@AI@%ObjectFile%@AE@%%@AB@%}%@AE@%%@NL@%
- Type: Local%@NL@%
- %@NL@%
- %@CR:MQPb2009@%%@4@%Links a relocatable object file containing external routines written in%@EH@%
- assembly language. If the .OBJ file is in a different path from the one
- defined in the QuickPascal Environment command in the Options menu, you must
- type in the entire pathname. For additional information on linking with
- assembly language, see Chapter 12%@BO: 517ed@%, "Advanced Topics."%@NL@%
- %@NL@%
- %@CR:MQPb200A@%%@4@%%@AB@%Memory%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb200B@%%@AB@%{$M%@AE@%%@AI@%StackSize%@AE@%%@AB@%,%@AE@%%@AI@%MinHeap%@AE@%%@AB@%,%@AE@%%@AI@%MaxHeap%@AE@%%@AB@%}%@AE@%%@NL@%
- Default: %@AB@%{$M 16384, 0, 655360}%@AE@%%@NL@%
- Type: Global%@NL@%
- %@NL@%
- %@CR:MQPb200C@%%@4@%Sets stack and heap memory allocationy. Three parameters are passed: stack%@EH@%
- size, minimum heap size, and maximum heap size. Each parameter must be an
- integer within a specific range. See the list of ranges in Table B.1 below.%@NL@%
- %@NL@%
- %@CR:MQPbT100@%%@4@%%@AB@%Table B.1 Minimum and Maximum Memory Allocation Parameters%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Parameter Minimum Value Maximum Value%@AE@%%@NL@%
- %@NL@%
- %@AI@%StackSize%@AE@% 1024 65520%@NL@%
- %@AI@%MinHeap%@AE@% 0 655360%@NL@%
- %@AI@%MaxHeap%@AE@% MinHeap 655360%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPb3000@%%@2@%%@AB@%B.3 Conditional Directives%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb3001@%%@4@%Conditional directives produce different code from the same source file if a%@EH@%
- conditional identifier is defined. The conditional directives are, in
- effect, a variation of the %@AB@%IF%@AE@% control statement. If a condition is true,
- code between the %@AB@%{$IF%@AE@%%@AI@%xxx%@AE@%%@AI@%Condition%@AE@%%@AB@%}%@AE@% and %@AB@%{$ENDIF}%@AE@% directives is compiled. If
- the condition is false, the compiler skips the code between the two
- directives. An optional %@AB@%{$ELSE}%@AE@% directive provides further control.%@NL@%
- %@NL@%
- %@AS@% {$DEFINE DEBUG}%@NL@%
- %@NL@%
- %@AS@% {$IFDEF DEBUG}%@NL@%
- %@AS@% Writeln('tax: ', tax, 'total: ', total)%@NL@%
- %@AS@% {$ELSE}%@NL@%
- %@AS@% Writeln('amount: ',tax + total);%@NL@%
- %@AS@% {ENDIF}%@NL@%
- %@NL@%
- %@CR:MQPb3002@%%@4@%You define and undefine identifiers with the %@AB@%{$DEFINE%@AE@% %@AI@%Name%@AE@%%@AB@%}%@AE@% and%@EH@%
- %@AB@%{$UNDEF%@AE@% %@AI@%Name%@AE@%%@AB@%}%@AE@% directives. Conditional identifiers are treated separately
- from similarly named program constants and variables. In addition to
- user-defined control identifiers, QuickPascal incorporates several
- predefined identifiers (listed in Table B.2 below).%@NL@%
- %@NL@%
- %@CR:MQPbT200@%%@4@%%@AB@%Table B.2 QuickPascal Predefined Conditional Identifiers%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%Conditional%@AE@%%@NL@%
- %@AB@%Identifier State Purpose%@AE@%%@NL@%
- %@NL@%
- %@AB@%VER10%@AE@% Defined Indicates the compiler version%@NL@%
- %@AB@%MSDOS%@AE@% Defined Indicates the operating system%@NL@%
- %@AB@%CPU86%@AE@% Defined Indicates the 80x86 CPU family%@NL@%
- %@AB@%CPU87%@AE@% Defined if an 80x87 is Indicates the use of an 80x87 CPU%@NL@%
- present at compile time%@NL@%
- %@NL@%
- %@CR:MQPb3003@%%@4@%Conditional directives may be placed anywhere in the source file. The%@EH@%
- individual conditional directives are described below.%@NL@%
- %@NL@%
- %@CR:MQPb3004@%%@4@%%@AB@%DEFINE%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb3005@%%@AB@%{$DEFINE%@AE@% %@AI@%Identifier%@AE@%%@AB@%}%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPb3006@%%@4@%Defines a conditional identifier. The identifier exists through the rest of%@EH@%
- the compilation, or until undefined with the UNDEF directive.%@NL@%
- %@NL@%
- %@CR:MQPb3007@%%@AB@%%@4@%ELSE%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb3008@%%@AB@%{$ELSE}%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPb3009@%%@4@%Compiles or skips the source based on the identifier in the preceding IF%@EH@%
- directive.%@NL@%
- %@NL@%
- %@CR:MQPb300A@%%@4@%%@AB@%ENDIF%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb300B@%%@AB@%{$ENDIF}%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPb300C@%%@4@%Ends the conditional compilation associated with the most recent IF%@EH@%
- directive.%@NL@%
- %@NL@%
- %@CR:MQPb300D@%%@4@%%@AB@%IFDEF%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb300E@%%@AB@%{$IFDEF%@AE@% %@AI@%Identifier%@AE@%%@AB@%}%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPb300F@%%@4@%Compiles the source that follows if the identifier has been defined.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb300G@%%@4@%%@AB@%IFNDEF%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb300H@%%@AB@%{$IFNDEF%@AE@% %@AI@%Identifier%@AE@%%@AB@%}%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPb300I@%%@4@%Compiles the source following the directive if the identifier is undefined.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb300J@%%@4@%%@AB@%IFOPT%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb300K@%%@AB@%{$IFOPT%@AE@% %@AI@%Switch%@AE@%%@AB@%}%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPb300L@%%@4@%Compiles the source that follows if the specified switch has been set as%@EH@%
- described. For example,%@NL@%
- %@NL@%
- %@AS@% {$IFOPT I-}%@NL@%
- %@AS@% result := IOResult;%@NL@%
- %@AS@% {$ENDIF}%@NL@%
- %@NL@%
- %@CR:MQPb300M@%%@4@%%@AB@%UNDEF%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPb300N@%%@AB@%{$UNDEF%@AE@%%@AI@% Identifier%@AE@%%@AB@%}%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPb300O@%%@4@%Undefines a previously declared identifier for the remainder of the%@EH@%
- compilation or until the identifier is once again defined.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPc0000@%%@1@%%@AB@%Appendix C Summary of Standard Units%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@CR:MQPc0001@%%@4@%QuickPascal comes with several standard units that expand your programs'%@EH@%
- capabilities. These units──collections of variables, constants, data types,
- procedures, and functions──enhance your control over the screen and text,
- DOS routines, printer use, and graphics. QuickPascal automatically inserts
- the %@AB@%System%@AE@% standard unit whenever you compile a program. %@AB@%System%@AE@% supplies all
- of the QuickPascal standard procedures and functions.%@NL@%
- %@NL@%
- %@CR:MQPc0010@%%@4@%%@AB@%Crt Unit%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPc0011@%%@4@%The %@AB@%Crt%@AE@% unit extends your control of the screen, keyboard input, and sound.%@EH@%
- %@AB@%Crt%@AE@% has procedures and functions that manipulate the screen colors, cursor
- position, text attributes, and windows. It also contains functions for
- checking keyboard activity and lets you turn the internal speaker on and
- off.%@NL@%
- %@NL@%
- %@CR:MQPc0020@%%@4@%%@AB@%Dos Unit%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPc0021@%%@4@%The %@AB@%Dos%@AE@% unit gives you access to file-handling and operating-system%@EH@%
- routines. Programs that need to access DOS procedures and functions in order
- to set or get the time and date, to determine disk sizes and available disk
- space, or to control software interrupts can do so with the %@AB@%Dos%@AE@% unit. Other
- procedures and functions within the %@AB@%Dos%@AE@% unit let you manipulate file names
- and file attributes.%@NL@%
- %@NL@%
- %@CR:MQPc0030@%%@4@%%@AB@%Printer Unit%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPc0031@%%@4@%The %@AB@%Printer%@AE@% unit lets you use a printer. It declares a text file, "Lst," and%@EH@%
- sends the output of %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% calls that use Lst to the printer port
- rather than to the screen. %@AB@%Printer%@AE@% accepts any type of formatting available
- to %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@%. (Lst directs its output to LPT1. Make sure your
- printer connects to that port.)%@NL@%
- %@NL@%
- %@CR:MQPc0040@%%@4@%%@AB@%MSGraph Unit%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPc0041@%%@4@%The %@AB@%MSGraph%@AE@% unit provides graphics in QuickPascal. It supports a large%@EH@%
- number of procedures and functions that draw geometric shapes, fill figures
- with colors and patterns, manipulate images, create windows and viewports,
- and display text in various sizes and type styles. You can display graphics
- on a wide variety of video adapters and can choose the best combination of
- screen resolution and colors for your needs.%@NL@%
- %@NL@%
- %@CR:MQPc0050@%%@4@%%@AB@%System Unit%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPc0051@%%@4@%The %@AB@%System%@AE@% unit contains all of the standard procedures and functions%@EH@%
- (%@AB@%Writeln%@AE@%, %@AB@%Pred%@AE@%, %@AB@%Copy%@AE@%, and so on), which you think of as always being
- available. You do not need to include %@AB@%System%@AE@% in the %@AB@%USES%@AE@% list; QuickPascal
- automatically uses the %@AB@%System%@AE@% unit whenever you compile a program.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPd0000@%%@1@%%@AB@%Appendix D Quick Reference Guide%@AE@%%@EH@%%@NL@%
- ───────────────────────────────────────────────────────────────────────────%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPd1000@%%@2@%%@AB@%D.1 Keywords, Procedures, and Functions%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPd1001@%%@4@%Use the QP Advisor for complete descriptions and information.%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPd1002@%%@AB@%Abs(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the absolute value of x.%@NL@%
- %@NL@%
- %@AB@%ABSOLUTE%@AE@%%@NL@%
- %@NL@%
- Declares a variable to reside at a specific memory location.%@NL@%
- %@NL@%
- %@AB@%Addr(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the address of %@AI@%x%@AE@%, where %@AI@%x%@AE@% is any variable, typed constant,%@NL@%
- procedure identifier, or function identifier.%@NL@%
- %@NL@%
- %@AB@%AND%@AE@%%@NL@%
- %@NL@%
- Acts as logical or bitwise %@AB@%AND%@AE@% operator.%@NL@%
- %@NL@%
- %@AB@%Append(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Opens an existing %@AB@%Text%@AE@% file %@AI@%FileVariable%@AE@% to append additional text.%@NL@%
- %@NL@%
- %@AB@%ArcTan(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the arctangent of x.%@NL@%
- %@NL@%
- %@AB@%ARRAY [%@AE@% %@AI@%Ranges%@AE@%%@AB@% ] OF%@AE@% %@AI@%Type%@AE@%%@NL@%
- %@NL@%
- Defines %@AI@%Type%@AE@% as the base type, and %@AI@%Ranges%@AE@% as the range of indices, for%@NL@%
- an array type, variable, or constant.%@NL@%
- %@NL@%
- %@AB@%Assign(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%Name%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Assigns the file variable %@AI@%FileVariable%@AE@% to the external file named in%@NL@%
- %@AI@%Name%@AE@%.%@NL@%
- %@NL@%
- %@AB@%BEGIN%@AE@%%@NL@%
- %@NL@%
- Starts a statement block.%@NL@%
- %@NL@%
- %@AB@%BlockRead(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%Buffer%@AE@%%@AB@%,%@AE@% %@AI@%Count%@AE@% «%@AB@%,%@AE@% %@AI@%RecordsRead%@AE@%» %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Reads %@AI@%Count%@AE@% number of records into memory from the file specified by%@NL@%
- %@AI@%FileVariable%@AE@%, beginning with the first byte occupied by %@AI@%Buffer%@AE@%.%@NL@%
- Optionally %@AB@%BlockRead%@AE@% returns the number of records successfully read in%@NL@%
- %@AI@%RecordsRead%@AE@%.%@NL@%
- %@NL@%
- %@AB@%BlockWrite(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%Buffer%@AE@%%@AB@%,%@AE@% %@AI@%Count%@AE@% «%@AB@%,%@AE@% %@AI@%RecordsWritten%@AE@%» %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Writes %@AI@%Count%@AE@% number of records from memory to the file specified by%@NL@%
- %@AI@%FileVariable%@AE@%, beginning with the first byte occupied by %@AI@%Buffer%@AE@%.%@NL@%
- Optionally %@AB@%BlockWrite%@AE@% returns the number of records successfully%@NL@%
- written in %@AI@%RecordsWritten%@AE@%.%@NL@%
- %@NL@%
- %@AB@%CASE%@AE@% %@AI@%Selector%@AE@% %@AB@%OF%@AE@% %@AI@%Constant%@AE@%%@AB@%:%@AE@% %@AI@%StatementBlock%@AE@%%@AB@%;%@AE@% ... %@AB@%END%@AE@%%@NL@%
- %@NL@%
- Executes the %@AI@%StatementBlock%@AE@% whose %@AI@%Constant%@AE@% matches %@AI@%Selector%@AE@%.%@NL@%
- %@NL@%
- %@AB@%ChDir(%@AE@% %@AI@%NewDir%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Makes %@AI@%NewDir%@AE@% the current directory.%@NL@%
- %@NL@%
- %@AB@%Chr(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the ASCII character with ordinal value %@AI@%x%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Close(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Closes the open file specified by the file variable %@AI@%FileVariable%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Concat(%@AE@% %@AI@%Str1%@AE@% «%@AB@%,%@AE@% %@AI@%Str2%@AE@% %@AB@%,%@AE@% %@AI@% Str3%@AE@%%@AB@%...%@AE@%» %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the argument strings (%@AI@%Str1%@AE@%, %@AI@%Str2%@AE@%, etc.) as a single string.%@NL@%
- %@NL@%
- %@AB@%CONST%@AE@%%@NL@%
- %@NL@%
- Starts a constant definition section.%@NL@%
- %@NL@%
- %@AB@%Copy(%@AE@% %@AI@%String%@AE@%%@AB@%,%@AE@% %@AI@%Start%@AE@%%@AB@%,%@AE@% %@AI@%Count%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns a substring of %@AI@%String%@AE@%, %@AI@%Count%@AE@% characters long, beginning with%@NL@%
- character number %@AI@%Start%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Cos(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the cosine of x.%@NL@%
- %@NL@%
- %@AB@%CSeg%@AE@%%@NL@%
- %@NL@%
- Returns the value of the CS register.%@NL@%
- %@NL@%
- %@AB@%CSTRING%@AE@% «[%@AI@%Length%@AE@%]»%@NL@%
- %@NL@%
- Defines a variable or constant as a series of up to 255 characters%@NL@%
- ending in a null byte, as in the C programming language. The integer%@NL@%
- %@AI@%Length%@AE@% specifies the maximum length of the string.%@NL@%
- %@NL@%
- %@AB@%Dec(%@AE@% %@AI@%x%@AE@% «%@AB@%,%@AE@% %@AI@%Step%@AE@%» %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Decrements the variable %@AI@%x%@AE@% by 1; if %@AI@%Step%@AE@% is specified, %@AI@%x%@AE@% is decremented%@NL@%
- by %@AI@%Step%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Delete(%@AE@% %@AI@%String%@AE@%%@AB@%,%@AE@% %@AI@%Start%@AE@%%@AB@%,%@AE@% %@AI@%Count%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns a copy of %@AI@%String%@AE@% with %@AI@%Count%@AE@% characters removed, beginning with%@NL@%
- character number %@AI@%Start%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Dispose(%@AE@% %@AI@%p%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Removes the dynamic variable that %@AI@%p%@AE@% points to and returns the memory to%@NL@%
- the heap.%@NL@%
- %@NL@%
- %@AB@%DIV%@AE@%%@NL@%
- %@NL@%
- Acts as the integer division operator. %@AI@%i%@AE@% %@AB@%DIV%@AE@% %@AI@%j%@AE@% returns the quotient of%@NL@%
- %@AI@%i%@AE@% divided by %@AI@%j%@AE@% rounded to the integer nearest zero.%@NL@%
- %@NL@%
- %@AB@%DO%@AE@%%@NL@%
- %@NL@%
- Introduces the statement block with %@AB@%WHILE%@AE@%, %@AB@%FOR%@AE@%, and %@AB@%WITH%@AE@%.%@NL@%
- %@NL@%
- %@AB@%DOWNTO%@AE@%%@NL@%
- %@NL@%
- Indicates that a %@AB@%FOR%@AE@% statement's end value is less than its start value%@NL@%
- and that the control variable is decremented by 1 with each iteration.%@NL@%
- %@NL@%
- %@AB@%DSeg%@AE@%%@NL@%
- %@NL@%
- Returns the value of the DS register.%@NL@%
- %@NL@%
- %@AB@%ELSE%@AE@%%@NL@%
- %@NL@%
- Begins the default clause in an %@AB@%IF...THEN...ELSE%@AE@% or %@AB@%CASE%@AE@% statement.%@NL@%
- %@NL@%
- %@AB@%END%@AE@%%@NL@%
- %@NL@%
- Ends a statement block.%@NL@%
- %@NL@%
- %@AB@%Eof%@AE@% «%@AB@%(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%»%@NL@%
- %@NL@%
- Returns the end-of-file status for the file %@AI@%FileVariable%@AE@%. %@AB@%Eof%@AE@% returns%@NL@%
- %@AB@%True%@AE@% if the end of the file has been reached, otherwise it returns%@NL@%
- %@AB@%False%@AE@%. If you omit %@AI@%FileVariable%@AE@%, %@AB@%Eof%@AE@% checks the status of the standard%@NL@%
- input file.%@NL@%
- %@NL@%
- %@AB@%Eoln%@AE@% «%@AB@%(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%»%@NL@%
- %@NL@%
- Returns the end-of-line status. %@AB@%Eoln%@AE@% returns %@AB@%True%@AE@% if the end of the%@NL@%
- line has been reached, otherwise it returns %@AB@%False%@AE@%. If you omit%@NL@%
- %@AI@%FileVariable%@AE@%, %@AB@%Eoln%@AE@% checks the status of the standard input file.%@NL@%
- %@NL@%
- %@AB@%Erase(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Erases the file referred to by %@AI@%FileVariable%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Exit%@AE@%%@NL@%
- %@NL@%
- In a procedure or function, causes control to return to the main%@NL@%
- program. In the main program, %@AB@%Exit%@AE@% halts program execution.%@NL@%
- %@NL@%
- %@AB@%Exp (%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the exponential of %@AI@%x%@AE@%, that is, the value %@AI@%e%@AE@% raised to the power%@NL@%
- of %@AI@%x%@AE@%.%@NL@%
- %@NL@%
- %@AB@%EXTERNAL%@AE@%%@NL@%
- %@NL@%
- Identifies a separately compiled procedure or function written in%@NL@%
- assembly language.%@NL@%
- %@NL@%
- %@AB@%FILE%@AE@% «%@AB@%OF%@AE@% %@AI@%ComponentType%@AE@%»%@NL@%
- %@NL@%
- Declares a file type composed of values of type %@AI@%ComponentType%@AE@%.%@NL@%
- %@NL@%
- %@AB@%FilePos(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the current position of an open file referred to by file%@NL@%
- variable %@AI@%FileVariable%@AE@%.%@NL@%
- %@NL@%
- %@AB@%FileSize(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the size (in bytes) of an open file referred to by file%@NL@%
- variable %@AI@%FileVariable%@AE@%.%@NL@%
- %@NL@%
- %@AB@%FillChar(%@AE@% %@AI@%Variable%@AE@%%@AB@%,%@AE@% %@AI@%Count%@AE@%%@AB@%,%@AE@% %@AI@%Character%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Fills %@AI@%Count%@AE@% contiguous bytes of memory with %@AI@%Character%@AE@% (either an ASCII%@NL@%
- value or a literal character enclosed in single quotes), starting with%@NL@%
- the first byte occupied by %@AI@%Variable%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Flush(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Writes to disk the buffer of the text file referred to by %@AI@%FileVariable%@AE@%.%@NL@%
- %@NL@%
- %@AB@%FOR%@AE@% %@AI@%ControlVariable%@AE@% %@AB@%:=%@AE@% %@AI@%StartVal%@AE@% {%@AB@%TO%@AE@%|%@AB@%DOWNTO%@AE@%} %@AI@%EndVal%@AE@% %@AB@%DO%@AE@%%@NL@%
- %@AI@%StatementBlock%@AE@%%@NL@%
- %@NL@%
- Executes %@AI@%StatementBlock%@AE@% as long as the value of %@AI@%ControlVariable%@AE@% is%@NL@%
- between its start value %@AI@%StartVal%@AE@% and its end value %@AI@%EndVal%@AE@%, inclusive.%@NL@%
- Use %@AB@%TO%@AE@% if %@AI@%EndVal%@AE@% is greater than %@AI@%StartVal%@AE@%, or %@AB@%DOWNTO%@AE@% if %@AI@%EndVal%@AE@% is less%@NL@%
- than %@AI@%StartVal%@AE@%. %@AB@%FOR%@AE@% increments (with %@AB@%TO%@AE@%) or decrements (with %@AB@%DOWNTO%@AE@%)%@NL@%
- %@AI@%ControlVariable%@AE@% by 1 each time it executes %@AI@%StatementBlock%@AE@%.%@NL@%
- %@NL@%
- %@AB@%FORWARD%@AE@%%@NL@%
- %@NL@%
- Declares a procedure but omits its definition until a second%@NL@%
- declaration. This permits mutually referencing procedures.%@NL@%
- %@NL@%
- %@AB@%Frac(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the fractional portion of the real number %@AI@%x%@AE@%.%@NL@%
- %@NL@%
- %@AB@%FreeMem(%@AE@% %@AI@%Pointer%@AE@%%@AB@%,%@AE@% %@AI@%Size%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Frees %@AI@%Size%@AE@% bytes of dynamic memory at address %@AI@%Pointer%@AE@%.%@NL@%
- %@NL@%
- %@AB@%FUNCTION%@AE@% %@AI@%Identifier%@AE@%«%@AB@%(%@AE@% «%@AB@%VAR%@AE@%» %@AI@%Param1%@AE@%«%@AB@%,%@AE@% %@AI@%Param2 ...%@AE@%» %@AB@%:%@AE@%%@AI@%Ptype1%@AE@%
- «%@AB@%; %@AE@%«%@AB@%VAR%@AE@%» %@AI@%Param3%@AE@%«%@AB@%,%@AE@% %@AI@%Param4 ...%@AE@%» %@AB@%:%@AE@%%@AI@%Ptype2 ...%@AE@%»%@AB@%)%@AE@%» %@AB@%:%@AE@%%@AI@%Typename%@AE@%%@NL@%
- %@NL@%
- Defines a function named %@AI@%Identifier%@AE@% that returns a value of type%@NL@%
- %@AI@%Typename%@AE@%. Any parameters (%@AI@%Param1%@AE@%, %@AI@%Param2%@AE@%, etc.) to the function must be%@NL@%
- declared along with their type (%@AI@%Ptype1%@AE@%, %@AI@%Ptype2%@AE@%, etc.). Every function%@NL@%
- must return a value.%@NL@%
- %@NL@%
- %@AB@%GetDir%@AE@%%@AB@%( %@AE@%%@AI@%Drive%@AE@%%@AB@%,%@AE@% %@AI@%Path%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the current directory in the string %@AI@%Path%@AE@%, given the integer%@NL@%
- %@AI@%Drive%@AE@%. Setting %@AI@%Drive%@AE@% to 0 uses the current drive, %@AI@%Drive%@AE@% to 1 uses%@NL@%
- drive A, %@AI@%Drive%@AE@% to 2 uses drive B, and so on.%@NL@%
- %@NL@%
- %@AB@%GetMem(%@AE@% %@AI@%Pointer%@AE@%%@AB@%,%@AE@% %@AI@%Size%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Creates a new dynamic variable of %@AI@%Size%@AE@% bytes from heap memory, setting%@NL@%
- location %@AI@%Pointer%@AE@%.%@NL@%
- %@NL@%
- %@AB@%GOTO%@AE@% %@AI@%LabelName%@AE@%%@NL@%
- %@NL@%
- Unconditionally transfers program control to the statement at label %@NL@%
- %@AI@%LabelName%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Halt%@AE@%«%@AB@%(%@AE@% %@AI@%Code%@AE@% %@AB@%)%@AE@%»%@NL@%
- %@NL@%
- Halts program execution and returns to DOS. You can optionally include%@NL@%
- the program's exit code.%@NL@%
- %@NL@%
- %@AB@%Hi(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the high-order byte of %@AI@%x%@AE@%, a word or integer.%@NL@%
- %@NL@%
- %@AB@%IF%@AE@% %@AI@%BooleanExpression%@AE@% %@AB@%THEN%@AE@% %@AI@%StatementBlock1%@AE@% «%@AB@%ELSE%@AE@% %@AI@%StatementBlock2%@AE@% »%@NL@%
- %@NL@%
- Executes %@AI@%StatementBlock1%@AE@% if %@AI@%BooleanExpression%@AE@% is %@AB@%True%@AE@%, otherwise%@NL@%
- executes %@AI@%StatementBlock2%@AE@%.%@NL@%
- %@NL@%
- %@AB@%IMPLEMENTATION%@AE@%%@NL@%
- %@NL@%
- Indicates the beginning of the unit section that defines the unit's%@NL@%
- procedures and functions. The identifiers declared in this section are%@NL@%
- private.%@NL@%
- %@NL@%
- %@AB@%IN%@AE@%%@NL@%
- %@NL@%
- Acts as the member-of operator for sets. %@AB@%IN%@AE@% is used to test for the%@NL@%
- presence of an element in a set.%@NL@%
- %@NL@%
- %@AB@%Inc(%@AE@% %@AI@%x%@AE@% «%@AB@%,%@AE@% Step» %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Increments the variable %@AI@%x%@AE@% by 1; if %@AI@%Step%@AE@% is specified, %@AI@%x%@AE@% is incremented%@NL@%
- by %@AI@%Step%@AE@%.%@NL@%
- %@NL@%
- %@AB@%INHERITED%@AE@%%@NL@%
- %@NL@%
- Modifies a message to refer to the parent method.%@NL@%
- %@NL@%
- %@AB@%INLINE(%@AE@% %@AI@%MachineCode%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Defines machine code that is inserted into the program.%@NL@%
- %@NL@%
- %@AB@%Insert(%@AE@% %@AI@%String%@AE@%%@AB@%,%@AE@% %@AI@%SubString%@AE@%%@AB@%,%@AE@% %@AI@%Start%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Inserts the string %@AI@%SubString%@AE@% into the string %@AI@%String%@AE@%, beginning at%@NL@%
- character number %@AI@%Start%@AE@%. If the resulting string is more than 255%@NL@%
- characters long, it is truncated to 255 characters.%@NL@%
- %@NL@%
- %@AB@%Int(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the integral portion of the real number %@AI@%x%@AE@%.%@NL@%
- %@NL@%
- %@AB@%INTERFACE%@AE@%%@NL@%
- %@NL@%
- Indicates the beginning of the unit section that declares the%@NL@%
- variables, constants, procedures, and functions available to the%@NL@%
- calling program.%@NL@%
- %@NL@%
- %@AB@%INTERRUPT%@AE@%%@NL@%
- %@NL@%
- Declares a procedure as an interrupt procedure. Interrupt procedures%@NL@%
- may handle program interrupts.%@NL@%
- %@NL@%
- %@AB@%IOResult%@AE@%%@NL@%
- %@NL@%
- Returns the status of the most recent I/O operation. A status of 0%@NL@%
- indicates the I/O operation was successful.%@NL@%
- %@NL@%
- %@AB@%LABEL%@AE@% {%@AI@%Identifier%@AE@%| 0..9999}%@NL@%
- %@NL@%
- Declares the label %@AI@%Identifier%@AE@% or a number. Labels are the destination%@NL@%
- of %@AB@%GOTO%@AE@% statements.%@NL@%
- %@NL@%
- %@AB@%Length(%@AE@% %@AI@%String%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the length of the string %@AI@%String%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Ln(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the natural logarithm of %@AI@%x%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Lo(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the low-order byte of %@AI@%x%@AE@%, a word or integer.%@NL@%
- %@NL@%
- %@AB@%Mark(%@AE@% %@AI@%Pointer%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Saves the current top of the heap in %@AI@%Pointer%@AE@%.%@NL@%
- %@NL@%
- %@AB@%MaxAvail%@AE@%%@NL@%
- %@NL@%
- Returns the size (in bytes) of the largest continuous block of free%@NL@%
- memory in the heap.%@NL@%
- %@NL@%
- %@AB@%MemAvail%@AE@%%@NL@%
- %@NL@%
- Returns the total free memory in the heap in bytes.%@NL@%
- %@NL@%
- %@AB@%Member(%@AE@% %@AI@%ObjectVariable%@AE@%%@AB@%,%@AE@% %@AI@%ClassId%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns %@AB@%True%@AE@% if %@AI@%ObjectVariable%@AE@% is a member of the class %@AI@%ClassId%@AE@%, and%@NL@%
- %@AB@%False%@AE@% otherwise.%@NL@%
- %@NL@%
- %@AB@%MkDir(%@AE@% %@AI@%NewDir%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Creates a new directory with the path given in the string %@AI@%NewDir%@AE@%.%@NL@%
- %@NL@%
- %@AB@%MOD%@AE@%%@NL@%
- %@NL@%
- Acts as the modular division operator. The expression %@AI@%i%@AE@% %@AB@%MOD%@AE@% %@AI@%j%@AE@% returns%@NL@%
- the remainder of %@AI@%i%@AE@% %@AB@%DIV%@AE@% %@AI@%j%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Move(%@AE@% %@AI@%Source%@AE@%%@AB@%,%@AE@% %@AI@%Destination%@AE@%%@AB@%,%@AE@% %@AI@%Count%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Copies %@AI@%Count%@AE@% bytes of %@AI@%Source%@AE@% to %@AI@%Destination%@AE@%.%@NL@%
- %@NL@%
- %@AB@%New(%@AE@% %@AI@% Pointer%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Allocates space for a new dynamic variable in the heap and sets %@AI@%Pointer%@AE@%%@NL@%
- to the address of the new variable. The type of pointer determines how%@NL@%
- much memory %@AB@%New%@AE@% allocates.%@NL@%
- %@NL@%
- %@AB@%NIL%@AE@%%@NL@%
- %@NL@%
- Indicates the value of a pointer that does not point to anything.%@NL@%
- %@NL@%
- %@AB@%NOT%@AE@%%@NL@%
- %@NL@%
- Acts as the logical or bitwise negation operator.%@NL@%
- %@NL@%
- %@AB@%OBJECT%@AE@%«(%@AI@%Parent%@AE@%)»%@NL@%
- %@NL@%
- Defines an object type or class, descended from the %@AI@%Parent%@AE@% class.%@NL@%
- %@NL@%
- %@AB@%Odd(%@AE@% %@AI@% x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns %@AB@%True%@AE@% if the integral %@AI@%x%@AE@% is odd, %@AB@%False%@AE@% if %@AI@%x%@AE@% is even.%@NL@%
- %@NL@%
- %@AB@%OF%@AE@%%@NL@%
- %@NL@%
- Identifies the base type of an %@AB@%ARRAY%@AE@%, %@AB@%FILE%@AE@%, or %@AB@%SET%@AE@%, or introduces the%@NL@%
- constant list found in a %@AB@%CASE%@AE@% statement.%@NL@%
- %@NL@%
- %@AB@%Ofs(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the offset of %@AI@%x%@AE@%, a variable, typed constant, procedure, or%@NL@%
- function name.%@NL@%
- %@NL@%
- %@AB@%OR%@AE@%%@NL@%
- %@NL@%
- Acts as the logical or bitwise %@AB@%OR%@AE@% operator.%@NL@%
- %@NL@%
- %@AB@%Ord(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the ordinal number of %@AI@%x%@AE@% (an ordinal-type variable).%@NL@%
- %@NL@%
- %@AB@%OVERRIDE%@AE@%%@NL@%
- %@NL@%
- Redefines a parent method to do something new.%@NL@%
- %@NL@%
- %@AB@%PACKED%@AE@%%@NL@%
- %@NL@%
- Required by standard Pascal. Serves only to distinguish types in%@NL@%
- QuickPascal.%@NL@%
- %@NL@%
- %@AB@%ParamCount%@AE@%%@NL@%
- %@NL@%
- Returns the number of command-line parameters.%@NL@%
- %@NL@%
- %@AB@%ParamStr(%@AE@% %@AI@%i%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns a string that is the %@AI@%i%@AE@% th command-line parameter. Parameter%@NL@%
- number 0 is the program path in DOS versions 3.1 and later.%@NL@%
- %@NL@%
- %@AB@%Pi%@AE@%%@NL@%
- %@NL@%
- Returns the value Pi (3.1415926535897932385). The precision of the%@NL@%
- value varies, depending on the floating-point hardware present.%@NL@%
- %@NL@%
- %@AB@%Pointer%@AE@%%@NL@%
- %@NL@%
- Defines a variable as a generic pointer type. A variable of type%@NL@%
- %@AB@%POINTER%@AE@% must be assigned to a variable of a specific pointer type%@NL@%
- before it can be dereferenced.%@NL@%
- %@NL@%
- %@AB@%Pos(%@AE@% %@AI@%SubString%@AE@%%@AB@%,%@AE@% %@AI@%String%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the starting position of string %@AI@%SubString%@AE@% in string %@AI@%String%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Pred%@AE@%( %@AI@%x%@AE@% )%@NL@%
- %@NL@%
- Returns the predecessor of %@AI@%x%@AE@% in the list of values of its ordinal type.%@NL@%
- %@NL@%
- %@AB@%PROCEDURE%@AE@% %@AI@%Identifier%@AE@%«%@AB@%( %@AE@%«%@AB@%VAR%@AE@%» %@AI@%Param1%@AE@%«%@AB@%,%@AE@% %@AI@%Param2%@AE@% ...» %@AB@%:%@AE@% %@AI@%Ptype1%@AE@%
- «%@AB@%;%@AE@% «%@AB@%VAR%@AE@%» %@AI@%Param3%@AE@%«%@AB@%,%@AE@% %@AI@%Param4%@AE@% ...» %@AB@%:%@AE@% %@AI@%Ptype2%@AE@% %@AB@%...%@AE@%»%@AB@%)%@AE@%»%@NL@%
- %@NL@%
- Defines a procedure named %@AI@%Identifier%@AE@%. Any parameters (%@AI@%Param1%@AE@%, %@AI@%Param2%@AE@%,%@NL@%
- etc.) to the procedure must be declared along with their type (%@AI@%Ptype1%@AE@%,%@NL@%
- %@AI@%Ptype2%@AE@%, etc.).%@NL@%
- %@NL@%
- %@AB@%PROGRAM%@AE@% «%@AI@%ProgName%@AE@%»%@NL@%
- %@NL@%
- Declares a program with the name %@AI@%ProgName%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Ptr(%@AE@% %@AI@%Seg%@AE@%%@AB@%,%@AE@% %@AI@%Off%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Converts a segment and offset to a pointer address;%@AI@%Seg%@AE@% and %@AI@%Off%@AE@% are both%@NL@%
- of type %@AB@%Word%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Random%@AE@%«%@AB@%(%@AE@% %@AI@%Limit%@AE@% %@AB@%)%@AE@%»%@NL@%
- %@NL@%
- Returns a random real number between 0 and 1, or a random whole number%@NL@%
- between 0 and %@AI@%Limit%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Randomize%@AE@%%@NL@%
- %@NL@%
- Initializes the random number generator.%@NL@%
- %@NL@%
- %@AB@%Read(%@AE@%«%@AI@%FileVariable%@AE@%%@AB@%,%@AE@%»%@AI@%Var1%@AE@% «%@AB@%,%@AE@% %@AI@%Var2%@AE@% ...»%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Reads one or more values from the standard input device or, optionally,%@NL@%
- from the file specifier %@AI@%FileVariable%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Readln(%@AE@%«%@AI@%FileVariable%@AE@%%@AB@%,%@AE@%»%@AI@%Var1%@AE@% «%@AB@%,%@AE@% %@AI@%Var2%@AE@% ... »%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Executes the %@AB@%Read%@AE@% procedure, then skips to the beginning of the next%@NL@%
- line of the text file specified by %@AI@%FileVariable%@AE@%.%@NL@%
- %@NL@%
- %@AB@%RECORD%@AE@% %@AI@%FieldList%@AE@% %@AB@%END%@AE@%%@NL@%
- %@NL@%
- Creates a compound variable consisting of the items listed in%@NL@%
- %@AI@%FieldList%@AE@%. The different fields in a record can have different types.%@NL@%
- %@NL@%
- %@AB@%Release(%@AE@% %@AI@%Pointer%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the value of the heap-top pointer to %@AI@%Pointer%@AE@%, which was%@NL@%
- previously obtained by %@AB@%Mark%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Rename(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%NewName%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Renames the external file specified by file variable %@AI@%FileVariable%@AE@% to%@NL@%
- the name string %@AI@%NewName%@AE@%.%@NL@%
- %@NL@%
- %@AB@%REPEAT%@AE@% %@AI@%StatementBlock%@AE@% %@AB@%UNTIL%@AE@% %@AI@%BooleanExpression%@AE@%%@NL@%
- %@NL@%
- Executes %@AI@%StatementBlock%@AE@% as long as %@AI@%BooleanExpression%@AE@% remains %@AB@%False%@AE@%.%@NL@%
- When %@AI@%BooleanExpression%@AE@% becomes %@AB@%True%@AE@%, control passes to the statement%@NL@%
- following the %@AB@%UNTIL%@AE@% statement.%@NL@%
- %@NL@%
- %@AB@%Reset(%@AE@% %@AI@%FileVariable%@AE@% «%@AB@%,%@AE@% %@AI@%Size%@AE@%» %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Opens the file specified by %@AI@%FileVariable%@AE@% with a data transfer unit size%@NL@%
- of %@AI@%Size%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Rewrite(%@AE@% %@AI@%FileVariable%@AE@% «%@AB@%,%@AE@% %@AI@%Size%@AE@%» %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Creates and opens a new file %@AI@%FileVariable%@AE@%, with a data transfer unit%@NL@%
- size of %@AI@%Size%@AE@%. If %@AI@%FileVariable%@AE@% already exists, it is truncated to a%@NL@%
- length of zero.%@NL@%
- %@NL@%
- %@AB@%RmDir(%@AE@% %@AI@%Dir%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Removes the empty directory named %@AI@%Dir%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Round(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Rounds the real number %@AI@%x%@AE@% to the nearest whole number.%@NL@%
- %@NL@%
- %@AB@%RunError%@AE@%«%@AB@%(%@AE@% %@AI@%ErrorNum%@AE@% %@AB@%)%@AE@%»%@NL@%
- %@NL@%
- Halts program execution with the run-time error number %@AI@%ErrorNum%@AE@%, or%@NL@%
- run-time error 0 if %@AI@%ErrorNum%@AE@% is not specified.%@NL@%
- %@NL@%
- %@AB@%Seek(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%Pos%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Moves the current position of the file specified by %@AI@%FileVariable%@AE@% to the%@NL@%
- position %@AI@%Pos%@AE@%.%@NL@%
- %@NL@%
- %@AB@%SeekEof%@AE@% «%@AB@%(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%)%@AE@%»%@NL@%
- %@NL@%
- Returns the end-of-file status for the text file specified%@NL@%
- by %@AI@%FileVariable%@AE@%, skipping blanks, tabs, and end-of-line markers. The%@NL@%
- actual file position does not change.%@NL@%
- %@NL@%
- %@AB@%SeekEoln%@AE@%«%@AB@%(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%»%@NL@%
- %@NL@%
- Returns the end-of-line status for the text file specified by%@NL@%
- %@AI@%FileVariable%@AE@%, skipping blanks and tabs.%@NL@%
- %@NL@%
- %@AB@%Seg(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the segment containing %@AI@%x%@AE@%, a variable, typed constant,%@NL@%
- procedure, or function name.%@NL@%
- %@NL@%
- %@AB@%Self%@AE@%%@NL@%
- %@NL@%
- Refers to the object that received a message, used by methods.%@NL@%
- %@NL@%
- %@AB@%SET OF%@AE@% %@AI@%OrdinalType%@AE@%%@NL@%
- %@NL@%
- Identifies %@AI@%OrdinalType%@AE@% as the base type for a set type, constant, or%@NL@%
- variable.%@NL@%
- %@NL@%
- %@AB@%SetTextBuf(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%Buffer%@AE@% «%@AB@%,%@AE@% %@AI@%Size%@AE@%» %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Assigns the text file %@AI@%FileVariable%@AE@% a buffer of %@AI@%Size%@AE@% bytes in memory%@NL@%
- starting at %@AI@%Buffer%@AE@%. If %@AI@%Size%@AE@% is omitted, %@AI@%SizeOf%@AE@%%@AB@%(%@AE@% %@AI@%Buffer%@AE@%%@AB@%)%@AE@% is assumed.%@NL@%
- %@NL@%
- %@AB@%SHL%@AE@%%@NL@%
- %@NL@%
- Acts as the bitwise shift-left operator. The expression %@AI@%i%@AE@% %@AB@%SHL%@AE@% %@AI@%j%@AE@% shifts%@NL@%
- the value of %@AI@%i%@AE@% to the left by %@AI@%j%@AE@% bits.%@NL@%
- %@NL@%
- %@AB@%SHR%@AE@%%@NL@%
- %@NL@%
- Acts as the bitwise shift-right operator. The expression %@AI@%i%@AE@% %@AB@%SHR%@AE@% %@AI@%j%@AE@% shifts%@NL@%
- the value of %@AI@%i%@AE@% to the right by %@AI@%j%@AE@% bits.%@NL@%
- %@NL@%
- %@AB@%Sin(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the sine of %@AI@%x%@AE@%.%@NL@%
- %@NL@%
- %@AB@%SizeOf(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the size of the variable, typed constant, or type %@AI@%x%@AE@% in bytes.%@NL@%
- %@NL@%
- %@AB@%SPtr%@AE@%%@NL@%
- %@NL@%
- Returns the value of the SP register, the current offset of the stack%@NL@%
- pointer in the stack segment.%@NL@%
- %@NL@%
- %@AB@%Sqr(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the square of %@AI@%x%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Sqrt(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the square root of %@AI@%x%@AE@%, a positive integer or real number.%@NL@%
- %@NL@%
- %@AB@%SSeg%@AE@%%@NL@%
- %@NL@%
- Returns the value of the SS register, the stack segment address of the%@NL@%
- stack pointer.%@NL@%
- %@NL@%
- %@AB@%Str(%@AE@% %@AI@% Number%@AE@%«%@AB@%:%@AE@% %@AI@%Width%@AE@%«%@AB@%:%@AE@% %@AI@%Decimals%@AE@%»»%@AB@%,%@AE@% %@AI@%String%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Converts the numeric value %@AI@%Number%@AE@% to the string %@AI@%String%@AE@%. The arguments%@NL@%
- %@AI@%Width%@AE@% and %@AI@%Decimals%@AE@% specify the total width and number of decimal places%@NL@%
- that will appear in the string.%@NL@%
- %@NL@%
- %@AB@%STRING%@AE@%« %@AB@%[%@AE@% %@AI@%Length%@AE@%%@AB@%]%@AE@% »%@NL@%
- %@NL@%
- Defines a variable or constant as a series of up to 255 characters. The%@NL@%
- integer %@AI@%Length%@AE@% specifies the maximum length of the string.%@NL@%
- %@NL@%
- %@AB@%Succ(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the successor to %@AI@%x%@AE@% in the list of values of its ordinal type.%@NL@%
- %@NL@%
- %@AB@%Swap(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Exchanges the high- and low-order bytes of %@AI@%x%@AE@%, an integer or word.%@NL@%
- %@NL@%
- %@AB@%THEN%@AE@% %@AI@%StatementBlock%@AE@%%@NL@%
- %@NL@%
- Used in the second half of an %@AB@%IF...THEN%@AE@% statement. If the condition in%@NL@%
- the %@AB@%IF%@AE@% portion of the statement is %@AB@%True%@AE@%, the statements in%@NL@%
- %@AI@%StatementBlock%@AE@% execute.%@NL@%
- %@NL@%
- %@AB@%TO%@AE@%%@NL@%
- %@NL@%
- Indicates that a %@AB@%FOR%@AE@% statement's ending value is greater than its%@NL@%
- starting value and that the control variable will be incremented by%@NL@%
- one.%@NL@%
- %@NL@%
- %@AB@%Trunc(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Truncates a real value %@AI@%x%@AE@% to an integer.%@NL@%
- %@NL@%
- %@AB@%Truncate(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Truncates the file specified by %@AI@%FileVariable%@AE@% at the current file%@NL@%
- position.%@NL@%
- %@NL@%
- %@AB@%TYPE%@AE@%%@NL@%
- %@NL@%
- Begins a type definition section.%@NL@%
- %@NL@%
- %@AB@%UNIT%@AE@% %@AI@%Identifier%@AE@%%@NL@%
- %@NL@%
- Identifies the code that follows as a unit and gives the unit the name%@NL@%
- %@AI@%Identifier.%@AE@%%@NL@%
- %@NL@%
- %@AB@%UNTIL%@AE@% %@AI@%BooleanExpression%@AE@%%@NL@%
- %@NL@%
- Terminates a %@AB@%REPEAT%@AE@% statement when %@AI@%BooleanExpression%@AE@% becomes %@AB@%True%@AE@%.%@NL@%
- %@NL@%
- %@AB@%UpCase(%@AE@% %@AI@%Char%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns character %@AI@%Char%@AE@% in uppercase.%@NL@%
- %@NL@%
- %@AB@%USES%@AE@% %@AI@%Identifier%@AE@%«%@AB@%,%@AE@% %@AI@%Identifier%@AE@%»...%@NL@%
- %@NL@%
- Identifies units required by the program to resolve references to%@NL@%
- identifiers defined within the units.%@NL@%
- %@NL@%
- %@AB@%Val(%@AE@% %@AI@%String%@AE@%%@AB@%,%@AE@% %@AI@%Number%@AE@%%@AB@%,%@AE@% %@AI@%ErrorPosition%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Converts the numeric string %@AI@%String%@AE@% to its numeric representation%@NL@%
- %@AI@%Number%@AE@%. If %@AI@%String%@AE@% does not represent a number, %@AI@%ErrorPosition%@AE@% returns%@NL@%
- the position of the first offending character.%@NL@%
- %@NL@%
- %@AB@%VAR%@AE@%%@NL@%
- %@NL@%
- Begins a variable declaration section or declares a variable parameter.%@NL@%
- %@NL@%
- %@AB@%WHILE%@AE@% %@AI@%BooleanExpression%@AE@% %@AB@%DO%@AE@% %@AI@%StatementBlock%@AE@%%@NL@%
- %@NL@%
- Executes %@AI@%StatementBlock%@AE@% as long as %@AI@%BooleanExpression%@AE@% remains %@AB@%True%@AE@%. When%@NL@%
- %@AI@%BooleanExpression%@AE@% becomes %@AB@%False%@AE@%, control passes to the statement%@NL@%
- following %@AI@%StatementBlock%@AE@%.%@NL@%
- %@NL@%
- %@AB@%WITH%@AE@% %@AI@%RecordName1%@AE@% «%@AB@%,%@AE@% %@AI@%RecordName2%@AE@% %@AB@%...%@AE@%»%@AB@%DO%@AE@% %@AI@%StatementBlock%@AE@%%@NL@%
- %@NL@%
- Allows statements within %@AI@%StatementBlock%@AE@% to refer to the fields of one%@NL@%
- or more records without specifying the names of the records%@NL@%
- (%@AI@%RecordName1%@AE@%, %@AI@%RecordName2%@AE@%...).%@NL@%
- %@NL@%
- %@AB@%Write(%@AE@%«%@AI@%FileVariable%@AE@%%@AB@%,%@AE@%»%@AI@%Var1%@AE@%«%@AB@%,%@AE@% %@AI@%Var2%@AE@%%@AB@%...%@AE@%» %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Writes one or more values to the standard output device or to the file%@NL@%
- specified by %@AI@%FileVariable%@AE@%.%@NL@%
- %@NL@%
- %@AB@%Writeln(%@AE@%«%@AI@%FileVariable%@AE@% %@AB@%,%@AE@%»%@AI@%Var1%@AE@%«%@AB@%,%@AE@% %@AI@%Var2%@AE@%%@AB@%...%@AE@%» %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Executes the %@AB@%Write%@AE@% procedure, then sends an end-of-line marker to the%@NL@%
- standard output device or the file specified by a %@AI@%FileVariable%@AE@%.%@NL@%
- %@NL@%
- %@AB@%XOR%@AE@%%@NL@%
- %@NL@%
- Acts as the logical or bitwise exclusive-or operator.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPd2000@%%@2@%%@AB@%D.2 Crt Procedures and Functions%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPd2001@%%@AB@%AssignCrt(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Associates a %@AB@%Text%@AE@% file variable %@AI@%FileVariable%@AE@% with the CRT device%@NL@%
- (screen).%@NL@%
- %@NL@%
- %@AB@%ClrEol%@AE@%%@NL@%
- %@NL@%
- Clears a line from the cursor to the end of the line.%@NL@%
- %@NL@%
- %@AB@%ClrScr%@AE@%%@NL@%
- %@NL@%
- Clears the window and moves the cursor to the upper left corner.%@NL@%
- %@NL@%
- %@AB@%Delay(%@AE@% %@AI@%Microseconds%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Pauses program execution for a specified length of time.%@NL@%
- %@NL@%
- %@AB@%DelLine%@AE@%%@NL@%
- %@NL@%
- Deletes the line at the current cursor location.%@NL@%
- %@NL@%
- %@AB@%GotoXY(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@% y%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Moves the cursor to designated column and row.%@NL@%
- %@NL@%
- %@AB@%HighVideo%@AE@%%@NL@%
- %@NL@%
- Turns on high-intensity video for the current foreground color.%@NL@%
- %@NL@%
- %@AB@%InsLine%@AE@%%@NL@%
- %@NL@%
- Inserts a blank line at the current cursor location.%@NL@%
- %@NL@%
- %@AB@%KeyPressed%@AE@%%@NL@%
- %@NL@%
- Returns %@AB@%True%@AE@% if the keyboard buffer contains a character.%@NL@%
- %@NL@%
- %@AB@%LowVideo%@AE@%%@NL@%
- %@NL@%
- Turns off high-intensity video for the current foreground color.%@NL@%
- %@NL@%
- %@AB@%NormVideo%@AE@%%@NL@%
- %@NL@%
- Restores the text colors and attributes that were in effect at program%@NL@%
- start-up.%@NL@%
- %@NL@%
- %@AB@%NoSound%@AE@%%@NL@%
- %@NL@%
- Turns off the computer's speaker.%@NL@%
- %@NL@%
- %@AB@%ReadKey%@AE@%%@NL@%
- %@NL@%
- Returns one character from the keyboard buffer but does not echo%@NL@%
- character on the screen.%@NL@%
- %@NL@%
- %@AB@%Sound(%@AE@% %@AI@%Frequency%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Generates a tone from the computer's speaker at the specified%@NL@%
- frequency.%@NL@%
- %@NL@%
- %@AB@%TextBackground(%@AE@% %@AI@%Color%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the background color for character output.%@NL@%
- %@NL@%
- %@AB@%TextColor(%@AE@% %@AI@%Color%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the foreground color and blinking attribute for character output.%@NL@%
- %@NL@%
- %@AB@%TextMode(%@AE@% %@AI@%Mode%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the display to the specified text mode.%@NL@%
- %@NL@%
- %@AB@%WhereX%@AE@%%@NL@%
- %@NL@%
- Returns the current x-coordinate of the text cursor.%@NL@%
- %@NL@%
- %@AB@%WhereY%@AE@%%@NL@%
- %@NL@%
- Returns the current y-coordinate of the text cursor.%@NL@%
- %@NL@%
- %@AB@%Window(%@AE@% %@AI@%x1%@AE@%%@AB@%,%@AE@% %@AI@%y1%@AE@%%@AB@%,%@AE@% %@AI@%x2%@AE@%%@AB@%,%@AE@% %@AI@%y2%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Defines a text display window. The coordinates give the upper left and%@NL@%
- lower right corners of the window.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPd3000@%%@2@%%@AB@%D.3 Dos Procedures and Functions%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPd3001@%%@AB@%DiskFree(%@AE@% %@AI@%DriveNumber%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the number of bytes of free space on the specified drive.%@NL@%
- %@NL@%
- %@AB@%DiskSize(%@AE@% %@AI@%DriveNumber%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the total capacity in bytes of the specified drive.%@NL@%
- %@NL@%
- %@AB@%DosExitCode%@AE@%%@NL@%
- %@NL@%
- Returns the exit code from a child process.%@NL@%
- %@NL@%
- %@AB@%DosVersion%@AE@%%@NL@%
- %@NL@%
- Returns the version number of the operating system.%@NL@%
- %@NL@%
- %@AB@%EnvCount%@AE@%%@NL@%
- %@NL@%
- Returns the number of variables defined in the DOS environment.%@NL@%
- %@NL@%
- %@AB@%EnvStr(%@AE@% %@AI@%EnvironmentStringIndex%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the value of a variable from the DOS environment.%@NL@%
- %@NL@%
- %@AB@%Exec(%@AE@% %@AI@%ProgramPath%@AE@%%@AB@%,%@AE@% %@AI@%CommandLine%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Loads and runs a child process while suspending parent process.%@NL@%
- %@NL@%
- %@AB@%FExpand(%@AE@% %@AI@%FilePath%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Expands a name to a fully qualified DOS path name.%@NL@%
- %@NL@%
- %@AB@%FindFirst(%@AE@% %@AI@%SearchPattern%@AE@%%@AB@%,%@AE@% %@AI@% Attributes%@AE@%%@AB@%,%@AE@% %@AI@%Matched%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Searches the specified directory for the first file matching the given %@NL@%
- %@AI@%SearchPattern%@AE@% and set of attributes.%@NL@%
- %@NL@%
- %@AB@%FindNext(%@AE@% %@AI@%Matched%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Searches the specified directory for the next file matching the%@NL@%
- %@AI@%SearchPattern%@AE@% and attributes specified in a previous call to %@AB@%FindFirst%@AE@%.%@NL@%
- %@NL@%
- %@AB@%FSearch(%@AE@% %@AI@%FilePath%@AE@%%@AB@%,%@AE@% %@AI@%DirectoryList%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Searches for a file in a list of directories.%@NL@%
- %@NL@%
- %@AB@%FSplit(%@AE@% %@AI@%FilePath%@AE@%%@AB@%,%@AE@% %@AI@%Directory%@AE@%%@AB@%,%@AE@% %@AI@%FileName%@AE@%%@AB@%,%@AE@% %@AI@%Extension%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Separates a path name into its directory, basename, and extension%@NL@%
- parts.%@NL@%
- %@NL@%
- %@AB@%GetCBreak(%@AE@% %@AI@%Breaking%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Gets the current state of DOS CTRL+BREAK checking.%@NL@%
- %@NL@%
- %@AB@%GetDate(%@AE@% %@AI@%Year%@AE@%%@AB@%,%@AE@% %@AI@%Month%@AE@%%@AB@%,%@AE@% %@AI@%Day%@AE@%%@AB@%,%@AE@% %@AI@%DayOfWeek%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Gets the current system date.%@NL@%
- %@NL@%
- %@AB@%GetEnv(%@AE@% %@AI@%EnvironmentStringLabel%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the current value of a DOS environment variable.%@NL@%
- %@NL@%
- %@AB@%GetFAttr(%@AE@% %@AI@% FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%Attribute%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Gets a file's attributes.%@NL@%
- %@NL@%
- %@AB@%GetFTime(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%TimeStamp%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Gets the %@AB@%LongInt%@AE@% representing a file's date and time of modification.%@NL@%
- %@NL@%
- %@AB@%GetIntVec(%@AE@% %@AI@%InterruptNumber%@AE@%%@AB@%,%@AE@% %@AI@%Vector%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Gets the vector address for a given interrupt number.%@NL@%
- %@NL@%
- %@AB@%GetTime(%@AE@% %@AI@%Hour%@AE@%%@AB@%,%@AE@% %@AI@%Minute%@AE@%%@AB@%,%@AE@% %@AI@%Second%@AE@%%@AB@%,%@AE@% %@AI@%Sec100%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Gets the current system time.%@NL@%
- %@NL@%
- %@AB@%GetVerify(%@AE@% %@AI@%Verifying%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Gets the current state of the DOS verify flag.%@NL@%
- %@NL@%
- %@AB@%Intr(%@AE@% %@AI@%InterruptNumber%@AE@%%@AB@%,%@AE@% %@AI@%RegisterValues%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Calls a software interrupt, loading and returning register values.%@NL@%
- %@NL@%
- %@AB@%Keep(%@AE@% %@AI@%ExitCode%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Terminates a program but keeps it resident in memory.%@NL@%
- %@NL@%
- %@AB@%MsDos(%@AE@% %@AI@%RegisterValues%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Calls DOS interrupt $21.%@NL@%
- %@NL@%
- %@AB@%PackTime(%@AE@% %@AI@%DateTime%@AE@%%@AB@%,%@AE@% %@AI@%TimeStamp%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Converts an unpacked %@AI@%DateTime%@AE@% record to a packed %@AB@%LongInt%@AE@% %@AI@%TimeStamp%@AE@%%@NL@%
- %@NL@%
- %@AB@%SetCBreak(%@AE@% %@AI@%Breaking%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Turns DOS CTRL+BREAK checking on or off.%@NL@%
- %@NL@%
- %@AB@%SetDate(%@AE@% %@AI@%Year%@AE@%%@AB@%,%@AE@% %@AI@%Month%@AE@%%@AB@%,%@AE@% %@AI@%Day%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the current system date.%@NL@%
- %@NL@%
- %@AB@%SetFAttr(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%Attribute%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets a file's attributes.%@NL@%
- %@NL@%
- %@AB@%SetFTime(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%TimeStamp%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets a file's date and time of file modification record.%@NL@%
- %@NL@%
- %@AB@%SetIntVec(%@AE@% %@AI@%InterruptNumber%@AE@%%@AB@%,%@AE@% %@AI@%Vector%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Installs a new interrupt handler. If a program changes an interrupt%@NL@%
- vector, it must restore it before terminating.%@NL@%
- %@NL@%
- %@AB@%SetTime(%@AE@% %@AI@%Hour%@AE@%%@AB@%,%@AE@% %@AI@%Minute%@AE@%%@AB@%,%@AE@% %@AI@%Second%@AE@%%@AB@%,%@AE@% %@AI@%Sec100%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the system time.%@NL@%
- %@NL@%
- %@AB@%SetVerify(%@AE@% %@AI@%Verifying%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the state of the DOS verify flag.%@NL@%
- %@NL@%
- %@AB@%SwapVectors%@AE@%%@NL@%
- %@NL@%
- Swaps interrupt vectors with previously saved values.%@NL@%
- %@NL@%
- %@AB@%UnpackTime(%@AE@% %@AI@%TimeStamp%@AE@%%@AB@%,%@AE@% %@AI@%DateTime%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Converts the %@AB@%LongInt%@AE@% %@AI@%TimeStamp%@AE@% argument to an unpacked %@AI@%DateTime%@AE@% record.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPd4000@%%@2@%%@AB@%D.4 Printer Unit Interface%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@CR:MQPd4001@%%@4@%The printer unit does not contain any procedures or functions. It connects%@EH@%
- the file variable Lst with the printer port. Using Lst in a %@AB@%Write%@AE@% or %@AB@%Writeln%@AE@%
- statement sends the text to the printer:%@NL@%
- %@NL@%
- %@AS@%Write( Lst, 'This text goes to the printer.' );%@AE@%%@NL@%
- %@NL@%
- %@CR:MQPd4002@%%@4@%Lst is a text variable assigned to the file variable %@AB@%PRN%@AE@% and preconnected to%@EH@%
- the LPT1 printer port.%@NL@%
- %@NL@%
- %@NL@%
- %@CR:MQPd5000@%%@2@%%@AB@%D.5 MSGraph Procedures and Functions%@AE@%%@EH@%%@NL@%
- %@NL@%
- %@AB@%_Arc(%@AE@%%@AI@%x1%@AE@%%@AB@%,%@AE@%%@AI@%y1%@AE@%%@AB@%,%@AE@%%@AI@%x2%@AE@%%@AB@%,%@AE@%%@AI@%y2%@AE@%%@AB@%,%@AE@%%@AI@%x3%@AE@%%@AB@%,%@AE@%%@AI@%y3%@AE@%%@AB@%,%@AE@%%@AI@%x4%@AE@%%@AB@%,%@AE@%%@AI@%y4%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Draws an arc given the bounding rectangle and beginning and ending%@NL@%
- points in viewport coordinates.%@NL@%
- %@NL@%
- %@AB@%_Arc_wxy(%@AE@% %@AI@%wxy1%@AE@%%@AB@%,%@AE@% %@AI@%wxy2%@AE@%%@AB@%,%@AE@% %@AI@%wxy3%@AE@%%@AB@%,%@AE@% %@AI@%wxy4%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Draws an arc given the bounding rectangle and beginning and ending%@NL@%
- points in window coordinates in %@AB@%_WXYCoord%@AE@% records.%@NL@%
- %@NL@%
- %@AB@%_ClearScreen(%@AE@% %@AI@%Area%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Clears the specified area of the screen.%@NL@%
- %@NL@%
- %@AB@%_DisplayCursor(%@AE@% %@AI@%Toggle%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Specifies whether to turn the cursor back on or leave it off after%@NL@%
- executing graphics routines.%@NL@%
- %@NL@%
- %@AB@%_Ellipse(%@AE@% %@AI@%Control%@AE@%%@AB@%,%@AE@% %@AI@%x1%@AE@%%@AB@%,%@AE@% %@AI@%y1%@AE@%%@AB@%,%@AE@% %@AI@%x2%@AE@%%@AB@%,%@AE@% %@AI@%y2%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Draws an ellipse given the fill control and bounding rectangle in%@NL@%
- viewport coordinates.%@NL@%
- %@NL@%
- %@AB@%_Ellipse_w(%@AE@% %@AI@%Control%@AE@%%@AB@%,%@AE@% %@AI@%wx1%@AE@%%@AB@%,%@AE@% %@AI@%wy1%@AE@%%@AB@%,%@AE@% %@AI@%wx2%@AE@%%@AB@%,%@AE@% %@AI@%wy2%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Draws an ellipse given the fill control and bounding rectangle in%@NL@%
- window coordinates.%@NL@%
- %@NL@%
- %@AB@%_Ellipse_wxy(%@AE@% %@AI@%Control%@AE@%%@AB@%,%@AE@% %@AI@%wxy1%@AE@%%@AB@%,%@AE@% %@AI@%wxy2%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Draws an ellipse given the fill control and bounding rectangle in%@NL@%
- window coordinates in the %@AB@%_WXYCoord%@AE@% records %@AI@%wxy1%@AE@% and %@AI@%wxy2%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_FloodFill(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%,%@AE@% %@AI@%Boundary%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Fills an area with the current color and fill mask. If the point (%@AI@%x%@AE@%, %@AI@%y%@AE@%)%@NL@%
- lies inside the figure, it fills the interior; if (%@AI@%x%@AE@%, %@AI@%y%@AE@%) lies outside%@NL@%
- the figure, it fills the background. %@AI@%x%@AE@% and %@AI@%y%@AE@% are given in viewport%@NL@%
- coordinates.%@NL@%
- %@NL@%
- %@AB@%_FloodFill_w(%@AE@% %@AI@%wx%@AE@%%@AB@%,%@AE@% %@AI@%wy%@AE@%%@AB@%,%@AE@% %@AI@%Boundary%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Fills an area with the current color and fill mask. If the point (%@AI@%x%@AE@%, %@AI@%y%@AE@%)%@NL@%
- lies inside the figure, it fills the interior; if (%@AI@%x%@AE@%, %@AI@%y%@AE@%) lies outside%@NL@%
- the figure, it fills the background. %@AI@%wx%@AE@% and %@AI@%wy%@AE@% are given in window%@NL@%
- coordinates.%@NL@%
- %@NL@%
- %@AB@%_GetActivePage%@AE@%%@NL@%
- %@NL@%
- Returns the current active page number.%@NL@%
- %@NL@%
- %@AB@%_GetArcInfo(%@AE@% %@AI@%Start%@AE@%%@AB@%,%@AE@% %@AI@%End%@AE@%%@AB@%,%@AE@% %@AI@%Paint%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns information about the most recently drawn %@AB@%_Arc%@AE@% or %@AB@%_Pie%@AE@%. The%@NL@%
- %@AI@%Start%@AE@% point, %@AI@%End%@AE@% point, and %@AI@%Paint%@AE@% point are returned in %@AB@%_XYCoord%@AE@%%@NL@%
- records.%@NL@%
- %@NL@%
- %@AB@%_GetBkColor%@AE@%%@NL@%
- %@NL@%
- Returns the current background color.%@NL@%
- %@NL@%
- %@AB@%_GetColor%@AE@%%@NL@%
- %@NL@%
- Returns the current color index.%@NL@%
- %@NL@%
- %@AB@%_GetCurrentPosition(%@AE@% %@AI@%xy%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the current graphics cursor position in viewport coordinates in%@NL@%
- the %@AB@%_XYCoord%@AE@% record %@AI@%xy%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_GetCurrentPosition_wxy(%@AE@% %@AI@%wxy%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the current graphics cursor position in window coordinates in%@NL@%
- the %@AB@%_WXYCoord%@AE@% record %@AI@%wxy%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_GetFillMask(%@AE@% %@AI@%Mask%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the current fill mask in %@AI@%mask%@AE@%, if one is defined.%@NL@%
- %@NL@%
- %@AB@%_GetFontInfo(%@AE@% %@AI@%FInfo%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Gets the current font characteristics and returns them in the %@AB@%_FontInfo%@AE@%%@NL@%
- record %@AI@%FInfo%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_GetGTextExtent(%@AE@% %@AI@%TextString%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the pixel width required to print the string %@AI@%TextString%@AE@% in the%@NL@%
- current font with the %@AB@%_OutGText%@AE@% function.%@NL@%
- %@NL@%
- %@AB@%_GetGTextVector(%@AE@% %@AI@%Vector%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the current rotation vector that is applied to font-based text%@NL@%
- output in the %@AB@%_XYCoord%@AE@% record %@AI@%Vector%@AE@%. The default is (1,0).%@NL@%
- %@NL@%
- %@AB@%_GetImage(%@AE@% %@AI@%x1%@AE@%%@AB@%,%@AE@% %@AI@%y1%@AE@%%@AB@%,%@AE@% %@AI@%x2%@AE@%%@AB@%,%@AE@% %@AI@%y2%@AE@%%@AB@%,%@AE@% %@AI@%Image%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Stores the screen image inside the bounding rectangle specified in%@NL@%
- viewport coordinates. Stores the image in the buffer %@AI@%Image%@AE@%. The%@NL@%
- rectangle must be completely within the current clipping region.%@NL@%
- %@NL@%
- %@AB@%_GetImage_w(%@AE@% %@AI@%wx1%@AE@%%@AB@%,%@AE@% %@AI@%wy1%@AE@%%@AB@%,%@AE@% %@AI@%wx2%@AE@%%@AB@%,%@AE@% %@AI@%wy2%@AE@%%@AB@%,%@AE@% %@AI@%Image%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Stores the screen image inside the bounding rectangle specified in%@NL@%
- window coordinates. Stores the image in the buffer %@AI@%Image%@AE@%. The rectangle%@NL@%
- must be completely within the current clipping region.%@NL@%
- %@NL@%
- %@AB@%_GetImage_wxy(%@AE@% %@AI@%wxy1%@AE@%%@AB@%,%@AE@% %@AI@%wxy2%@AE@%%@AB@%,%@AE@% %@AI@%Image%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Stores the screen image inside the bounding rectangle specified in%@NL@%
- window coordinates in the %@AB@%_WXYCoord%@AE@% records %@AI@%wxy1%@AE@% and %@AI@%wxy2%@AE@%. Stores the%@NL@%
- image in the buffer %@AI@%Image%@AE@%. The rectangle must be completely within the%@NL@%
- current clipping region.%@NL@%
- %@NL@%
- %@AB@%_GetLineStyle%@AE@%%@NL@%
- %@NL@%
- Returns the current line-style mask.%@NL@%
- %@NL@%
- %@AB@%_GetPhysCoord(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%,%@AE@% %@AI@%xy%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Translates the viewport coordinates (%@AI@%x%@AE@%, %@AI@%y%@AE@%) into physical screen%@NL@%
- coordinates and returns them in the %@AB@%_XYCoord%@AE@% record %@AI@%xy%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_GetPixel(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the pixel value (color index) at the location specified in%@NL@%
- viewport coordinates (%@AI@%x%@AE@%, %@AI@%y%@AE@%).%@NL@%
- %@NL@%
- %@AB@%_GetPixel_w(%@AE@% %@AI@%wx%@AE@%%@AB@%,%@AE@% %@AI@%wy%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the pixel value (color index) at the location specified in%@NL@%
- window coordinates (%@AI@%wx%@AE@%, %@AI@%wy%@AE@%).%@NL@%
- %@NL@%
- %@AB@%_GetTextColor%@AE@%%@NL@%
- %@NL@%
- Returns the color index (attribute) of the current text color.%@NL@%
- %@NL@%
- %@AB@%_GetTextCursor%@AE@%%@NL@%
- %@NL@%
- Returns the current cursor attribute (shape) in text modes.%@NL@%
- %@NL@%
- %@AB@%_GetTextPosition(%@AE@% %@AI@%r%@AE@%%@AB@%,%@AE@% %@AI@%c%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the current row and column position of the text cursor.%@NL@%
- %@NL@%
- %@AB@%_GetTextWindow(%@AE@% %@AI@%r1%@AE@%%@AB@%,%@AE@% %@AI@%c1%@AE@%%@AB@%,%@AE@% %@AI@%r2%@AE@%%@AB@%,%@AE@% %@AI@%c2%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the boundaries of the current text window in row and column%@NL@%
- coordinates.%@NL@%
- %@NL@%
- %@AB@%_GetVideoConfig(%@AE@% %@AI@%vc%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the current graphics environment configuration in the%@NL@%
- %@AB@%_VideoConfig%@AE@% record %@AI@%vc%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_GetViewCoord(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%,%@AE@% %@AI@%xy%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Translates physical coordinates (%@AI@%x%@AE@%, %@AI@%y%@AE@%) into viewport coordinates,%@NL@%
- returning the viewport coordinates in the %@AB@%_XYCoord%@AE@% record %@AI@%xy%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_GetViewCoord_w(%@AE@% %@AI@%wx%@AE@%%@AB@%,%@AE@% %@AI@%wy%@AE@%%@AB@%,%@AE@% %@AI@%xy%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Translates window coordinates (%@AI@%wx%@AE@%, %@AI@%wy%@AE@%) into viewport coordinates,%@NL@%
- returning the viewport coordinates in the %@AB@%_XYCoord%@AE@% record %@AI@%xy%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_GetViewCoord_wxy(%@AE@% %@AI@%wxy%@AE@%%@AB@%,%@AE@% %@AI@%xy%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Translates window coordinates given in the %@AB@%_WXYCoord%@AE@% record %@AI@%wxy%@AE@% into%@NL@%
- viewport coordinates, returning the viewport coordinates in the%@NL@%
- %@AB@%_XYCoord%@AE@% record %@AI@%xy%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_GetVisualPage%@AE@%%@NL@%
- %@NL@%
- Returns the current visual page number.%@NL@%
- %@NL@%
- %@AB@%_GetWindowCoord(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%,%@AE@% %@AI@%wxy%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Translates viewport coordinates (%@AI@%x%@AE@%, %@AI@%y%@AE@%) into window coordinates and%@NL@%
- returns them in the %@AB@%_WXYCoord%@AE@% record %@AI@%wxy%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_ImageSize(%@AE@% %@AI@%x1%@AE@%%@AB@%,%@AE@% %@AI@%y1%@AE@%%@AB@%,%@AE@% %@AI@%x2%@AE@%%@AB@%,%@AE@% %@AI@%y2%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the number of bytes needed to store the image inside the%@NL@%
- bounding rectangle specified by the viewport coordinates (%@AI@%x1%@AE@%, %@AI@%y1%@AE@%), (%@AI@%x2%@AE@%,%@NL@%
- %@AI@%y2%@AE@%). This function returns a %@AB@%LongInt%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_ImageSize_w(%@AE@% %@AI@%wx1%@AE@%%@AB@%,%@AE@% %@AI@%wy1%@AE@%%@AB@%,%@AE@% %@AI@%wx2%@AE@%%@AB@%,%@AE@% %@AI@%wy2%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the number of bytes needed to store the image inside the%@NL@%
- bounding rectangle specified by the window coordinates (%@AI@%wx1%@AE@%, %@AI@%wy1%@AE@%),%@NL@%
- (%@AI@%wx2%@AE@%, %@AI@%wy2%@AE@%). This function returns a %@AB@%LongInt%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_ImageSize_wxy(%@AE@% %@AI@%wxy1%@AE@%%@AB@%,%@AE@% %@AI@%wxy2%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Returns the number of bytes needed to store the image inside the%@NL@%
- bounding rectangle specified by the window coordinates in the %@AB@%_WXYCoord%@AE@%%@NL@%
- records %@AI@%wxy1%@AE@% and %@AI@%wxy2%@AE@%. This function returns a %@AB@%LongInt%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_LineTo(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Draws a line from the current position to the point specified in%@NL@%
- viewport coordinates, using the current color, line-style mask, and%@NL@%
- logical write mode.%@NL@%
- %@NL@%
- %@AB@%_LineTo_w(%@AE@% %@AI@%wx%@AE@%%@AB@%,%@AE@% %@AI@%wy%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Draws a line from the current position to the point specified in window%@NL@%
- coordinates, using the current color, line-style mask, and logical%@NL@%
- write mode.%@NL@%
- %@NL@%
- %@AB@%_MoveTo(%@AE@% %@AI@%x, y%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Moves the graphics cursor to the point specified by the viewport%@NL@%
- coordinates (%@AI@%x%@AE@%, %@AI@%y%@AE@%).%@NL@%
- %@NL@%
- %@AB@%_MoveTo_w(%@AE@% %@AI@%wx%@AE@%%@AB@%,%@AE@% %@AI@%wy%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Moves the graphics cursor to the point specified by the window%@NL@%
- coordinates (%@AI@%wx%@AE@%, %@AI@%wy%@AE@%).%@NL@%
- %@NL@%
- %@AB@%_OutGText(%@AE@% %@AI@%TextString%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Prints %@AI@%TextString%@AE@% on the screen using the current font and graphics%@NL@%
- color at the current graphics cursor position.%@NL@%
- %@NL@%
- %@AB@%_OutMem(%@AE@% %@AI@%TextString%@AE@%%@AB@%,%@AE@% %@AI@%Length%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Prints %@AI@%TextString%@AE@% on the screen at the current text cursor position.%@NL@%
- This procedure treats ASCII 0, 10, and 13 as graphics characters.%@NL@%
- Formatting is not supported.%@NL@%
- %@NL@%
- %@AB@%_OutText(%@AE@% %@AI@%TextString%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Prints %@AI@%TextString%@AE@% on the screen at the current text cursor position.%@NL@%
- Formatting is not supported, except for carriage return and line feed.%@NL@%
- %@NL@%
- %@AB@%_Pie(%@AE@% %@AI@%Control, x1, y1, x2, y2, x3, y3, x4, y4%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- %@NL@%
- Draws a pie-shaped wedge given the fill control, bounding rectangle,%@NL@%
- starting point, and ending point. All coordinates are given in viewport%@NL@%
- coordinates.%@NL@%
- %@NL@%
- %@AB@%_Pie_wxy(%@AE@% %@AI@%Control%@AE@%%@AB@%,%@AE@% %@AI@%wxy1%@AE@%%@AB@%,%@AE@% %@AI@%wxy2%@AE@%%@AB@%,%@AE@% %@AI@%wxy3%@AE@%%@AB@%,%@AE@% %@AI@%wxy4%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Draws a pie-shaped wedge given the fill control, bounding rectangle,%@NL@%
- starting point, and ending point. All coordinates are given in%@NL@%
- %@AB@%_WXYCoord%@AE@% records.%@NL@%
- %@NL@%
- %@AB@%_PutImage(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%,%@AE@% %@AI@%Image%@AE@%%@AB@%,%@AE@% %@AI@%Action%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Transfers the image stored in the buffer %@AI@%Image%@AE@% to the screen (using the%@NL@%
- logical operator %@AI@%Action%@AE@%) with the upper left corner at the specified%@NL@%
- viewport coordinates. If the image does not completely fit in the%@NL@%
- current clipping region, the image is not transferred.%@NL@%
- %@NL@%
- %@AB@%_PutImage_w(%@AE@% %@AI@%wx%@AE@%%@AB@%,%@AE@% %@AI@%wy%@AE@%%@AB@%,%@AE@% %@AI@%Image%@AE@%%@AB@%,%@AE@% %@AI@%Action%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Transfers the image stored in the buffer %@AI@%Image%@AE@% to the screen (using the%@NL@%
- logical operator %@AI@%Action%@AE@%) with the upper left corner at the specified%@NL@%
- window coordinates. If the image does not completely fit in the current%@NL@%
- clipping region, the image is not transferred.%@NL@%
- %@NL@%
- %@AB@%_Rectangle(%@AE@% %@AI@%Control%@AE@%%@AB@%,%@AE@% %@AI@%x1%@AE@%%@AB@%,%@AE@% %@AI@%y1%@AE@%%@AB@%,%@AE@% %@AI@%x2%@AE@%%@AB@%,%@AE@% %@AI@%y2%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Draws a rectangle given the fill control and bounding rectangle in%@NL@%
- viewport coordinates, using the current color, line-style mask, and%@NL@%
- logical write mode.%@NL@%
- %@NL@%
- %@AB@%_Rectangle_w(%@AE@% %@AI@%Control%@AE@%%@AB@%,%@AE@% %@AI@%wx1%@AE@%%@AB@%,%@AE@% %@AI@%wy1%@AE@%%@AB@%,%@AE@% %@AI@%wx2%@AE@%%@AB@%,%@AE@% %@AI@%wy2%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Draws a rectangle given the fill control and bounding rectangle in%@NL@%
- window coordinates, using the current color, line-style mask, and%@NL@%
- logical write mode.%@NL@%
- %@NL@%
- %@AB@%_Rectangle_wxy(%@AE@% %@AI@%Control%@AE@%%@AB@%,%@AE@% %@AI@%wxy1%@AE@%%@AB@%,%@AE@% %@AI@%wxy2%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Draws a rectangle given the fill control and bounding rectangle in the%@NL@%
- window coordinates specified in the %@AB@%_WXYCoord%@AE@% records %@AI@%wxy1%@AE@% and %@AI@%wxy2%@AE@% and%@NL@%
- using the current color, line-style mask, and logical write mode.%@NL@%
- %@NL@%
- %@AB@%_RegisterFonts(%@AE@% %@AI@%PathName%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Registers the fonts in the file given in %@AI@%PathName%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_RemapAllPalette(%@AE@% %@AI@%NewPalette%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Remaps the entire color palette simultaneously, given an array of color%@NL@%
- values.%@NL@%
- %@NL@%
- %@AB@%_RemapPalette(%@AE@% %@AI@%Index%@AE@%%@AB@%,%@AE@% %@AI@%Value%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Remaps the color index %@AI@%Index%@AE@% to the color value %@AI@%Value%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_ScrollTextWindow(%@AE@% %@AI@%Count%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Scrolls the current text window by %@AI@%Count%@AE@% lines. If %@AI@%Count%@AE@% is positive,%@NL@%
- the text scrolls up; if negative, the text scrolls down.%@NL@%
- %@NL@%
- %@AB@%_SelectPalette(%@AE@% %@AI@%Number%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the active palette to palette number %@AI@%Number%@AE@% in CGA and Olivetti%@NL@%
- graphics modes.%@NL@%
- %@NL@%
- %@AB@%_SetActivePage(%@AE@% %@AI@%Page%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Makes page number %@AI@%Page%@AE@% the active page for graphics output, available%@NL@%
- only for configurations that support multiple screen pages.%@NL@%
- %@NL@%
- %@AB@%_SetBkColor(%@AE@% %@AI@%Color%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the current background color to %@AI@%Color%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_SetClipRgn(%@AE@% %@AI@%x1%@AE@%%@AB@%,%@AE@% %@AI@%y1%@AE@%%@AB@%,%@AE@% %@AI@%x2%@AE@%%@AB@%,%@AE@% %@AI@%y2%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Limits the display of subsequent graphics and font text to the bounding%@NL@%
- rectangle, given in viewport coordinates.%@NL@%
- %@NL@%
- %@AB@%_SetColor(%@AE@% %@AI@%Color%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the current graphics color to color index %@AI@%Color%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_SetFillMask(%@AE@% %@AI@%Mask%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Defines the current fill mask.%@NL@%
- %@NL@%
- %@AB@%_SetFont(%@AE@% %@AI@%Options%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Selects a new active font from one of the registered fonts. Font%@NL@%
- selection is based on the characteristics specified by %@AI@%Options%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_SetGTextVector(%@AE@% %@AI@%xvect%@AE@%%@AB@%,%@AE@% %@AI@%yvect%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the current rotation vector that is applied to font-based text%@NL@%
- output. The default is horizontal text (1,0).%@NL@%
- %@NL@%
- %@AB@%_SetLineStyle(%@AE@% %@AI@%Style%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the current line-style mask to %@AI@%Style%@AE@%. The line-style mask affects%@NL@%
- the output of %@AB@%_LineTo%@AE@% and %@AB@%_Rectangle%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_SetPixel(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Changes the specified pixel to the current color. The point is%@NL@%
- specified in viewport coordinates.%@NL@%
- %@NL@%
- %@AB@%_SetPixel_w(%@AE@% %@AI@%wx%@AE@%%@AB@%,%@AE@% %@AI@%wy%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the specified pixel to the current color. The point is specified%@NL@%
- in window coordinates.%@NL@%
- %@NL@%
- %@AB@%_SetTextColor(%@AE@% %@AI@%Color%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the text color to color index %@AI@%Color%@AE@%. Subsequent text output from%@NL@%
- %@AB@%_OutText%@AE@% and %@AB@%_OutMem%@AE@% appears in the new color.%@NL@%
- %@NL@%
- %@AB@%_SetTextCursor(%@AE@% %@AI@%Attr%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the cursor shape in text mode.%@NL@%
- %@NL@%
- %@AB@%_SetTextPosition(%@AE@% %@AI@%r%@AE@%%@AB@%,%@AE@% %@AI@%c%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Moves the text cursor position to the row and column specified,%@NL@%
- relative to the current text window.%@NL@%
- %@NL@%
- %@AB@%_SetTextRows(%@AE@% %@AI@%Rows%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the number of rows available for text modes.%@NL@%
- %@NL@%
- %@AB@%_SetTextWindow(%@AE@% %@AI@%r1%@AE@%%@AB@%,%@AE@% %@AI@%c1%@AE@%%@AB@%,%@AE@% %@AI@%r2%@AE@%%@AB@%,%@AE@% %@AI@%c2%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Defines the upper left and lower right boundaries of the current text%@NL@%
- window. Output from %@AB@%_OutText%@AE@% and %@AB@%_OutMem%@AE@% is limited to this window.%@NL@%
- %@NL@%
- %@AB@%_SetVideoMode(%@AE@% %@AI@%Mode%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Selects a screen mode for a particular hardware/display configuration.%@NL@%
- %@NL@%
- %@AB@%_SetVideoModeRows(%@AE@% %@AI@%Mode%@AE@%%@AB@%,%@AE@% %@AI@%Rows%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the screen mode and number of text rows for a particular hardware/%@NL@%
- display configuration.%@NL@%
- %@NL@%
- %@AB@%_SetViewOrg(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%,%@AE@% %@AI@%Org%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Moves the viewport origin to the physical coordinates (%@AI@%x%@AE@%, %@AI@%y%@AE@%), and%@NL@%
- returns the previous origin in the %@AB@%_XYCoord%@AE@% record %@AI@%Org%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_SetViewport(%@AE@% %@AI@%x1%@AE@%%@AB@%,%@AE@% %@AI@%y1%@AE@%%@AB@%,%@AE@% %@AI@%x2%@AE@%%@AB@%,%@AE@% %@AI@%y2%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Defines the graphics viewport (defines the clipping region and sets the%@NL@%
- viewport origin to the upper left corner of the region) given the%@NL@%
- bounding rectangle in physical coordinates.%@NL@%
- %@NL@%
- %@AB@%_SetVisualPage(%@AE@% %@AI@%Page%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Makes %@AI@%Page%@AE@% the current visual page (requires a configuration that%@NL@%
- supports multiple screen pages).%@NL@%
- %@NL@%
- %@AB@%_SetWindow(%@AE@% %@AI@%FInvert%@AE@%%@AB@%,%@AE@% %@AI@%x1%@AE@%%@AB@%,%@AE@% %@AI@%y1%@AE@%%@AB@%,%@AE@% %@AI@%x2%@AE@%%@AB@%,%@AE@% %@AI@%y2%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Creates a floating-point graphics window given a bounding rectangle in%@NL@%
- window coordinates. If %@AI@%FInvert%@AE@% is %@AB@%True%@AE@%, the window is inverted%@NL@%
- vertically.%@NL@%
- %@NL@%
- %@AB@%_SetWriteMode(%@AE@% %@AI@%WMode%@AE@% %@AB@%)%@AE@%%@NL@%
- %@NL@%
- Sets the logical operation applied to line-drawing output to one of the%@NL@%
- following: %@AB@%_Gor%@AE@%, %@AB@%_Gand%@AE@%, %@AB@%_GPReset%@AE@%, %@AB@%_GPSet%@AE@%, or %@AB@%_Gxor%@AE@%. Only %@AB@%LineTo%@AE@% and%@NL@%
- %@AB@%_Rectangle%@AE@% are affected.%@NL@%
- %@NL@%
- %@AB@%_UnRegisterFonts%@AE@%%@NL@%
- %@NL@%
- Disables fonts and frees memory previously allocated by %@AB@%_RegisterFonts%@AE@%.%@NL@%
- %@NL@%
- %@AB@%_WrapOn(%@AE@% %@AI@%Option%@AE@%%@AB@%)%@AE@%%@NL@%
- %@NL@%
- Controls text wrapping for %@AB@%_OutText%@AE@% and %@AB@%_OutMem%@AE@% when the output reaches%@NL@%
- the edge of the text window. By default, text wrapping is enabled.%@NL@%
- %@NL@%
- %@NL@%
-