home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / books / qpexam.db < prev    next >
Encoding:
Text File  |  1991-03-01  |  613.1 KB  |  12,283 lines

  1. %@1@%%@AB@%Microsoft QuickPascal - Pascal by Example%@EH@%%@AE@%%@NL@%
  2. %@NL@%
  3. %@NL@%
  4. %@NL@%
  5. ───────────────────────────────────────────────────────────────────────────%@NL@%
  6. %@NL@%
  7. %@NL@%
  8. %@NL@%
  9. %@AB@%MICROSOFT(R) QUICKPASCAL%@AE@%
  10. %@AB@%PASCAL BY EXAMPLE%@AE@%%@NL@%
  11. %@NL@%
  12. %@NL@%
  13. %@NL@%
  14. ───────────────────────────────────────────────────────────────────────────%@NL@%
  15. %@NL@%
  16. %@NL@%
  17. %@NL@%
  18. Information in this document is subject to change without notice and does
  19. not represent a commitment on the part of Microsoft Corporation. The
  20. software described in this document is furnished under a license agreement
  21. or nondisclosure agreement. The software may be used or copied only in
  22. accordance with the terms of the agreement. It is against the law to copy
  23. the software on any medium except as specifically allowed in the license or
  24. nondisclosure agreement. No part of this manual may be reproduced or
  25. transmitted in any form or by any means, electronic or mechanical, including
  26. photocopying and recording, for any purpose without the express written
  27. permission of Microsoft.%@NL@%
  28. %@NL@%
  29. (c)Copyright Microsoft Corporation, 1989. All rights reserved.
  30. Simultaneously published in the U.S. and Canada.%@NL@%
  31. %@NL@%
  32. Printed and bound in the United States of America.%@NL@%
  33. %@NL@%
  34. Microsoft, MS, MS-DOS, CodeView, GW-BASIC, QuickC, and XENIX are registered
  35. trademarks of Microsoft Corporation.%@NL@%
  36. %@NL@%
  37. IBM is a registered trademark of International Business Machines
  38. Corporation.%@NL@%
  39. %@NL@%
  40. Intel is a registered trademark of Intel Corporation.%@NL@%
  41. %@NL@%
  42. Document No. LN0114-200-R00-0689 Part No. 06792 10 9 8 7 6 5 4 3 2 1%@NL@%
  43. %@NL@%
  44. %@NL@%
  45. %@1@%%@AB@%Table of Contents%@AE@%%@EH@%%@NL@%
  46. %@NL@%
  47. ───────────────────────────────────────────────────────────────────────────%@NL@%
  48. %@NL@%
  49. %@AB@%Introduction%@BO:    3f28@%%@AE@%%@NL@%
  50. About This Book%@BO:    4493@%%@NL@%
  51. Using the Example Programs%@BO:    5185@%%@NL@%
  52. Key to Document Conventions%@BO:    5795@%%@NL@%
  53. Other Books on Pascal Programming%@BO:    6284@%%@NL@%
  54. Getting Assistance or Reporting Problems%@BO:    6f9c@%%@NL@%
  55. %@NL@%
  56. %@AB@%Part 1%@BO:    71ed@%  Pascal Basics%@AE@%%@NL@%
  57. ───────────────────────────────────────────────────────────────────────────%@NL@%
  58. %@NL@%
  59. %@AB@%Chapter 1%@BO:    7513@%  Your First Pascal Program%@AE@%%@NL@%
  60. 1.1%@BO:    79e2@%  Sample Pascal Program%@NL@%
  61. 1.2%@BO:    82df@%  Parts of a Pascal Program%@NL@%
  62. 1.3%@BO:    9096@%  Some Terms You Should Know%@NL@%
  63.       1.3.1%@BO:    922a@%  Keywords%@NL@%
  64.       1.3.2%@BO:    9d71@%  Identifiers%@NL@%
  65.       1.3.3%@BO:    a769@%  Constants and Variables%@NL@%
  66.       1.3.4%@BO:    abdd@%  Data Types%@NL@%
  67.       1.3.5%@BO:    b140@%  Operators and Expressions%@NL@%
  68. 1.4%@BO:    b575@%  Input and Output%@NL@%
  69. 1.5%@BO:    bc89@%  Moving On%@NL@%
  70. %@NL@%
  71. %@AB@%Chapter 2%@BO:    bdde@%  Programming Basics%@AE@%%@NL@%
  72. 2.1%@BO:    c018@%  Data Types%@NL@%
  73.       2.1.1%@BO:    c379@%  Integer Types%@NL@%
  74.       2.1.2%@BO:    d12d@%  Floating-Point Types%@NL@%
  75.       2.1.3%@BO:    da04@%  Character Type%@NL@%
  76.       2.1.4%@BO:    df20@%  String Types%@NL@%
  77.       2.1.5%@BO:    ed5c@%  Boolean Type%@NL@%
  78. 2.2%@BO:    f248@%  Constants%@NL@%
  79.       2.2.1%@BO:    f483@%  Simple Constants%@NL@%
  80.       2.2.2%@BO:    ff0c@%  Typed Constants%@NL@%
  81. 2.3%@BO:   109d4@%  Simple Variables%@NL@%
  82. 2.4%@BO:   11422@%  Pascal Operators%@NL@%
  83.       2.4.1%@BO:   11673@%  Kinds of Operators%@NL@%
  84.       2.4.2%@BO:   12303@%  Operator Precedence%@NL@%
  85. 2.5%@BO:   12f1f@%  Simple Pascal Expressions%@NL@%
  86.       2.5.1%@BO:   13216@%  Arithmetic Expressions%@NL@%
  87.       2.5.2%@BO:   13806@%  String Expressions%@NL@%
  88. %@NL@%
  89. %@AB@%Chapter 3%@BO:   13ad7@%  Procedures and Functions%@AE@%%@NL@%
  90. 3.1%@BO:   13e04@%  Overview%@NL@%
  91. 3.2%@BO:   145ab@%  Procedures%@NL@%
  92.       3.2.1%@BO:   14e12@%  Calling Procedures%@NL@%
  93.       3.2.2%@BO:   1522e@%  Declaring Procedures%@NL@%
  94.       3.2.3%@BO:   16069@%  Declaring Local Variables%@NL@%
  95.       3.2.4%@BO:   16f16@%  Passing Arguments%@NL@%
  96. 3.3%@BO:   1927a@%  Functions%@NL@%
  97.       3.3.1%@BO:   19aaf@%  Calling Functions%@NL@%
  98.       3.3.2%@BO:   19f8d@%  Returning Values from Functions%@NL@%
  99.       3.3.3%@BO:   1a1ff@%  Declaring Functions%@NL@%
  100. 3.4%@BO:   1a604@%  Nested Procedures%@NL@%
  101. 3.5%@BO:   1b35f@%  Recursion%@NL@%
  102. %@NL@%
  103. %@AB@%Chapter 4%@BO:   1beca@%  Controlling Program Flow%@AE@%%@NL@%
  104. 4.1%@BO:   1c11f@%  Relational and Boolean Operators%@NL@%
  105. 4.2%@BO:   1cf98@%  Looping Statements%@NL@%
  106.       4.2.1%@BO:   1d0d3@%  WHILE Loops%@NL@%
  107.       4.2.2%@BO:   1daa5@%  REPEAT Loops%@NL@%
  108.       4.2.3%@BO:   1e6c8@%  FOR Loops%@NL@%
  109. 4.3%@BO:   1f1a6@%  Decision-Making Statements%@NL@%
  110.       4.3.1%@BO:   1f2fc@%  IF Statements%@NL@%
  111.       4.3.2%@BO:   1f9e9@%  ELSE Clauses%@NL@%
  112.       4.3.3%@BO:   20767@%  CASE Statements%@NL@%
  113. %@NL@%
  114. %@AB@%Chapter 5%@BO:   21492@%  User-Defined Data Types%@AE@%%@NL@%
  115. 5.1%@BO:   21a50@%  Enumerated Data Types%@NL@%
  116.       5.1.1%@BO:   2228d@%  The First Function%@NL@%
  117.       5.1.2%@BO:   228e4@%  The Last Function%@NL@%
  118.       5.1.3%@BO:   22a58@%  The Succ Function%@NL@%
  119.       5.1.4%@BO:   22f68@%  The Pred Function%@NL@%
  120.       5.1.5%@BO:   23484@%  The Inc Procedure%@NL@%
  121.       5.1.6%@BO:   2382a@%  The Dec Procedure%@NL@%
  122.       5.1.7%@BO:   23bc9@%  The Ord Function%@NL@%
  123. 5.2%@BO:   24018@%  Subrange Types%@NL@%
  124.       5.2.1%@BO:   24a6b@%  Integer Subranges%@NL@%
  125.       5.2.2%@BO:   253a2@%  Character Subranges%@NL@%
  126.       5.2.3%@BO:   256fa@%  Enumerated Subranges%@NL@%
  127. 5.3%@BO:   25a4e@%  Sets%@NL@%
  128.       5.3.1%@BO:   261cb@%  Declaring Set Types%@NL@%
  129.       5.3.2%@BO:   26ba8@%  Assigning Set Elements to Variables%@NL@%
  130.       5.3.3%@BO:   26f86@%  Set Operators%@NL@%
  131. %@NL@%
  132. %@AB@%Chapter 6%@BO:   29b51@%  Arrays and Records%@AE@%%@NL@%
  133. 6.1%@BO:   2a0e9@%  Arrays%@NL@%
  134.       6.1.1%@BO:   2a47d@%  Declaring Arrays%@NL@%
  135.       6.1.2%@BO:   2b109@%  Accessing Array Elements%@NL@%
  136.       6.1.3%@BO:   2be3c@%  Declaring Constant Arrays%@NL@%
  137.       6.1.4%@BO:   2c39a@%  Passing Arrays as Parameters%@NL@%
  138.       6.1.5%@BO:   2cd87@%  Using the Debugger with Arrays%@NL@%
  139. 6.2%@BO:   2d29a@%  Records%@NL@%
  140.       6.2.1%@BO:   2d6c1@%  Declaring Records%@NL@%
  141.       6.2.2%@BO:   2e043@%  Accessing Record Fields%@NL@%
  142.       6.2.3%@BO:   2ed4f@%  Using the WITH Statement to Access Fields%@NL@%
  143.       6.2.4%@BO:   2f368@%  Constant Records%@NL@%
  144.       6.2.5%@BO:   2fa5c@%  Assigning Records to Record Variables%@NL@%
  145.       6.2.6%@BO:   2fe0f@%  Using the Debugger with Records%@NL@%
  146. 6.3%@BO:   30028@%  Variant Records%@NL@%
  147.       6.3.1%@BO:   30582@%  Declaring Variant Records%@NL@%
  148.       6.3.2%@BO:   30df6@%  Accessing Variant Record Fields%@NL@%
  149. %@NL@%
  150. %@AB@%Chapter 7%@BO:   31ac9@%  Units%@AE@%%@NL@%
  151. 7.1%@BO:   31dd4@%  Understanding Units%@NL@%
  152. 7.2%@BO:   32500@%  Using Units in a Program%@NL@%
  153. 7.3%@BO:   32a17@%  Standard QuickPascal Units%@NL@%
  154. 7.4%@BO:   33158@%  Creating Your Own Units%@NL@%
  155.       7.4.1%@BO:   33318@%  Writing a New Unit%@NL@%
  156.       7.4.2%@BO:   34a58@%  Compiling a Unit%@NL@%
  157.       7.4.3%@BO:   35177@%  Tips for Programming with Units%@NL@%
  158. %@NL@%
  159. %@AB@%Part 2%@BO:   35989@%  Programming Topics%@AE@%%@NL@%
  160. ───────────────────────────────────────────────────────────────────────────%@NL@%
  161. %@NL@%
  162. %@AB@%Chapter 8%@BO:   35d22@%  The Keyboard and Screen%@AE@%%@NL@%
  163. 8.1%@BO:   36061@%  Basic Input and Output%@NL@%
  164.       8.1.1%@BO:   36a44@%  Read and Readln Procedures%@NL@%
  165.       8.1.2%@BO:   37b4e@%  Write and Writeln Procedures%@NL@%
  166.       8.1.3%@BO:   384b0@%  Formatted Output with Write and Writeln%@NL@%
  167.       8.1.4%@BO:   394eb@%  DOS Redirection: Input and Output Files%@NL@%
  168. 8.2%@BO:   3a5eb@%  The Crt Unit%@NL@%
  169.       8.2.1%@BO:   3a956@%  Using the Crt Unit%@NL@%
  170.       8.2.2%@BO:   3cbf9@%  Character Input%@NL@%
  171.       8.2.3%@BO:   3dc1c@%  Cursor and Screen Control%@NL@%
  172.       8.2.4%@BO:   3e432@%  Using Windows%@NL@%
  173. %@NL@%
  174. %@AB@%Chapter 9%@BO:   3efa5@%  Text Files%@AE@%%@NL@%
  175. 9.1%@BO:   3f3c9@%  Working with Text Files%@NL@%
  176.       9.1.1%@BO:   3f8c2@%  Declaring a File Variable and File Name%@NL@%
  177.       9.1.2%@BO:   401de@%  Opening a Text File%@NL@%
  178.       9.1.3%@BO:   40db1@%  Writing Text to a File%@NL@%
  179.       9.1.4%@BO:   411c8@%  Reading Text from a File%@NL@%
  180.       9.1.5%@BO:   41bbe@%  Closing a Text File%@NL@%
  181. 9.2%@BO:   42062@%  Increasing the Speed for Input and Output%@NL@%
  182. 9.3%@BO:   42ab2@%  Redirecting Text Output%@NL@%
  183. 9.4%@BO:   43606@%  Standard Procedures and Functions for Input and Output%@NL@%
  184. %@NL@%
  185. %@AB@%Chapter 10%@BO:   43fd9@%  Binary Files%@AE@%%@NL@%
  186. 10.1%@BO:   4456a@%  Typed Files%@NL@%
  187.        10.1.1%@BO:   449bb@%  Declaring Typed Files%@NL@%
  188.        10.1.2%@BO:   45029@%  Accessing Data in a Typed File%@NL@%
  189.        10.1.3%@BO:   45fb4@%  Using Random Access%@NL@%
  190. 10.2%@BO:   46ff6@%  Untyped Files%@NL@%
  191. %@NL@%
  192. %@AB@%Chapter 11%@BO:   48f3e@%  Pointers and Dynamic Memory%@AE@%%@NL@%
  193. 11.1%@BO:   495bb@%  Declaring and Accessing Pointers%@NL@%
  194.        11.1.1%@BO:   4978e@%  Declaring Pointers%@NL@%
  195.        11.1.2%@BO:   49b6b@%  Initializing Pointers%@NL@%
  196.        11.1.3%@BO:   4a2d1@%  Manipulating Pointers%@NL@%
  197. 11.2%@BO:   4af71@%  Dynamic-Memory Allocation%@NL@%
  198.        11.2.1%@BO:   4b365@%  Allocating a Single Object%@NL@%
  199.        11.2.2%@BO:   4bb28@%  Allocating a Memory Block%@NL@%
  200. 11.3%@BO:   4cd58@%  Linked Lists%@NL@%
  201. 11.4%@BO:   4fc62@%  Binary Trees%@NL@%
  202. %@NL@%
  203. %@AB@%Chapter 12%@BO:   517ed@%  Advanced Topics%@AE@%%@NL@%
  204. 12.1%@BO:   51c30@%  The Bitwise Operators%@NL@%
  205. 12.2%@BO:   52d18@%  QuickPascal Memory Map%@NL@%
  206. 12.3%@BO:   548d8@%  Managing the Heap%@NL@%
  207.        12.3.1%@BO:   55258@%  Using Mark and Release to Free Memory%@NL@%
  208.        12.3.2%@BO:   55b90@%  Determining Free Memory and Size of the Free List%@NL@%
  209.        12.3.3%@BO:   563da@%  Preventing Deadlock with the Free List%@NL@%
  210.        12.3.4%@BO:   568f3@%  Writing a Heap-Error Function%@NL@%
  211. 12.4%@BO:   5721f@%  Internal Data Formats%@NL@%
  212.        12.4.1%@BO:   574ac@%  Non-Floating-Point Data Types%@NL@%
  213.        12.4.2%@BO:   58bd3@%  Floating-Point Data Types%@NL@%
  214. 12.5%@BO:   59c8d@%  Linking to Assembly Language%@NL@%
  215.        12.5.1%@BO:   5a2af@%  Setting Up a Link to Assembly Language%@NL@%
  216.        12.5.2%@BO:   5a798@%  Segment and Data Conventions%@NL@%
  217.        12.5.3%@BO:   5ad07@%  Entering the Procedure%@NL@%
  218.        12.5.4%@BO:   5b2ab@%  Accessing Parameters%@NL@%
  219.        12.5.5%@BO:   5c7bc@%  Returning a Value%@NL@%
  220.        12.5.6%@BO:   5ccd5@%  Exiting the Procedure%@NL@%
  221.        12.5.7%@BO:   5cf03@%  A Complete Example%@NL@%
  222. %@NL@%
  223. %@AB@%Part 3%@BO:   5d7d0@%  Graphics and Objects%@AE@%%@NL@%
  224. ───────────────────────────────────────────────────────────────────────────%@NL@%
  225. %@NL@%
  226. %@AB@%Chapter 13%@BO:   5dac7@%  Using Graphics%@AE@%%@NL@%
  227. 13.1%@BO:   5e065@%  Getting Started with Graphics%@NL@%
  228.        13.1.1%@BO:   5e1f2@%  Graphics Terms%@NL@%
  229.        13.1.2%@BO:   5e8fb@%  For More Information%@NL@%
  230. 13.2%@BO:   5eefe@%  Writing Your First Graphics Program%@NL@%
  231. 13.3%@BO:   63072@%  Using Video Modes%@NL@%
  232.        13.3.1%@BO:   63cb8@%  Selecting a Video Mode%@NL@%
  233.        13.3.2%@BO:   6586d@%  CGA Color Graphics Modes%@NL@%
  234.        13.3.3%@BO:   66a86@%  EGA, MCGA, and VGA Palettes%@NL@%
  235.        13.3.4%@BO:   675cb@%  EGA Color Graphics Modes%@NL@%
  236.        13.3.5%@BO:   68574@%  VGA Color Graphics Modes%@NL@%
  237.        13.3.6%@BO:   697e7@%  Using the Color Video Text Modes%@NL@%
  238. 13.4%@BO:   6ac8a@%  Understanding Coordinate Systems%@NL@%
  239.        13.4.1%@BO:   6afe1@%  Text Coordinates%@NL@%
  240.        13.4.2%@BO:   6b49b@%  Physical Screen Coordinates%@NL@%
  241.        13.4.3%@BO:   6c75c@%  Viewport Coordinates%@NL@%
  242.        13.4.4%@BO:   6ca35@%  Real Coordinates in a Window%@NL@%
  243. 13.5%@BO:   717c6@%  Animation%@NL@%
  244.        13.5.1%@BO:   71b98@%  Video-Page Animation%@NL@%
  245.        13.5.2%@BO:   734df@%  Bit-Mapped Animation%@NL@%
  246. %@NL@%
  247. %@AB@%Chapter 14%@BO:   76456@%  Using Fonts%@AE@%%@NL@%
  248. 14.1%@BO:   7682b@%  Overview of QuickPascal Fonts%@NL@%
  249. 14.2%@BO:   7768c@%  Using Fonts in QuickPascal%@NL@%
  250.        14.2.1%@BO:   77ccb@%  Registering Fonts%@NL@%
  251.        14.2.2%@BO:   783ef@%  Setting the Current Font%@NL@%
  252.        14.2.3%@BO:   7a3e5@%  Displaying Text Using the Current Font%@NL@%
  253. 14.3%@BO:   7a7dd@%  A Few Hints on Using Fonts%@NL@%
  254. 14.4%@BO:   7b054@%  Example Program%@NL@%
  255. %@NL@%
  256. %@AB@%Chapter 15%@BO:   7c122@%  Object-Oriented Programming%@AE@%%@NL@%
  257. 15.1%@BO:   7c365@%  Overview%@NL@%
  258. 15.2%@BO:   7cd69@%  Object Programming Concepts%@NL@%
  259. 15.3%@BO:   7d4fb@%  Using Objects%@NL@%
  260.        15.3.1%@BO:   7d6e2@%  Setting the Method Compiler Directive%@NL@%
  261.        15.3.2%@BO:   7d93f@%  Creating Classes%@NL@%
  262.        15.3.3%@BO:   7e4cd@%  Creating Subclasses%@NL@%
  263.        15.3.4%@BO:   7ee55@%  Defining Methods%@NL@%
  264.        15.3.5%@BO:   7f80c@%  Using INHERITED%@NL@%
  265.        15.3.6%@BO:   7fcc6@%  Declaring Objects%@NL@%
  266.        15.3.7%@BO:   7ff59@%  Allocating Memory%@NL@%
  267.        15.3.8%@BO:   80182@%  Calling Methods%@NL@%
  268.        15.3.9%@BO:   8047c@%  Testing Membership%@NL@%
  269.        15.3.10%@BO:   80673@%  Disposing of Objects%@NL@%
  270. 15.4%@BO:   808ff@%  Object Programming Strategies%@NL@%
  271.        15.4.1%@BO:   80b96@%  Object Style Conventions%@NL@%
  272.        15.4.2%@BO:   811ab@%  Object Reusability%@NL@%
  273.        15.4.3%@BO:   81412@%  Modularity%@NL@%
  274.        15.4.4%@BO:   815a6@%  Methods%@NL@%
  275.        15.4.5%@BO:   81792@%  Data Fields%@NL@%
  276. 15.5%@BO:   8198a@%  Example Program%@NL@%
  277. %@NL@%
  278. %@AB@%Appendixes%@AE@%%@NL@%
  279. ───────────────────────────────────────────────────────────────────────────%@NL@%
  280. %@NL@%
  281. %@AB@%Appendix A  ASCII Character Codes and Extended Key Codes%@BO:   829c0@%%@AE@%%@NL@%
  282. A.1%@BO:   82a85@%  ASCII Character Codes%@NL@%
  283. A.2%@BO:   84573@%  Extended-Key Codes%@NL@%
  284. %@NL@%
  285. %@AB@%Appendix B  Compiler Directives%@BO:   857d9@%%@AE@%%@NL@%
  286. B.1%@BO:   85aff@%  Switch Directives%@NL@%
  287. B.2%@BO:   87cb0@%  Parameter Directives%@NL@%
  288. B.3%@BO:   8865e@%  Conditional Directives%@NL@%
  289. %@NL@%
  290. %@AB@%Appendix C  Summary of Standard Units%@BO:   8964c@%%@AE@%%@NL@%
  291. %@NL@%
  292. %@AB@%Appendix D  Quick Reference Guide%@BO:   8a285@%%@AE@%%@NL@%
  293. D.1%@BO:   8a333@%  Keywords, Procedures, and Functions%@NL@%
  294. D.2%@BO:   91a8b@%  Crt Procedures and Functions%@NL@%
  295. D.3%@BO:   925b1@%  Dos Procedures and Functions%@NL@%
  296. D.4%@BO:   93c84@%  Printer Unit Interface%@NL@%
  297. D.5%@BO:   93ebf@%  MSGraph Procedures and Functions%@NL@%
  298. %@NL@%
  299. %@AB@%Tables%@AE@%%@NL@%
  300. ───────────────────────────────────────────────────────────────────────────%@NL@%
  301. %@NL@%
  302. Table 2.1%@BO:    c523@%    Integer Data Types%@NL@%
  303. Table 2.2%@BO:    d3d7@%    Floating-Point Data Types%@NL@%
  304. Table 2.3%@BO:   11a7d@%    Arithmetic Operators%@NL@%
  305. Table 2.4%@BO:   11ea9@%    Relational Operators%@NL@%
  306. Table 2.5%@BO:   12531@%    Operator Precedence%@NL@%
  307. Table 4.1%@BO:   1c848@%    Relational Operators%@NL@%
  308. Table 4.2%@BO:   1caf6@%    Boolean Operators%@NL@%
  309. Table 5.1%@BO:   273ef@%    Relational Operators%@NL@%
  310. Table 8.1%@BO:   3abde@%    Crt Text-Mode Constants%@NL@%
  311. Table 8.2%@BO:   3afb0@%    Crt Color Constants%@NL@%
  312. Table 8.3%@BO:   3b42e@%    Variables Provided by the Crt Unit%@NL@%
  313. Table 8.4%@BO:   3bfd0@%    Procedures and Functions Provided by the Crt Unit%@NL@%
  314. Table 8.6%@BO:   3e005@%    Statement Effects%@NL@%
  315. Table 9.1%@BO:   43776@%    Standard Procedures and Functions for All File Types%@NL@%
  316. Table 9.2%@BO:   43bda@%    Standard Procedures and Functions for Text Files%@NL@%
  317. Table 11.1%@BO:   4c9f4@%   Pointer Procedures%@NL@%
  318. Table 13.1%@BO:   60246@%   Constants Set by _SetVideoMode%@NL@%
  319. Table 13.2%@BO:   636da@%   Constants for Graphics Adapters%@NL@%
  320. Table 13.3%@BO:   63a63@%   Constants for Monitors%@NL@%
  321. Table 13.4%@BO:   65aa1@%   Available CGA Colors%@NL@%
  322. Table 13.5%@BO:   65e9f@%   CGA Colors:  _MResNoColor Mode%@NL@%
  323. Table 13.6%@BO:   6a0ff@%   Text Colors%@NL@%
  324. Table 14.1%@BO:   7735c@%   Typefaces and Type Sizes in QuickPascal%@NL@%
  325. Table B.1%@BO:   884e4@%    Minimum and Maximum Memory Allocation Parameters%@NL@%
  326. Table B.2%@BO:   88b7f@%    QuickPascal Predefined Conditional Identifiers%@NL@%
  327. %@NL@%
  328. %@NL@%
  329. %@NL@%
  330. %@CR:MQP00000@%%@1@%%@AB@%Introduction%@AE@%%@EH@%%@NL@%
  331. ───────────────────────────────────────────────────────────────────────────%@NL@%
  332. %@NL@%
  333. %@CR:MQP00001@%%@4@%Congratulations on your purchase of Microsoft(R) QuickPascal. By now you%@EH@%
  334. should have read the other book in this package, %@AI@%Up and Running%@AE@%, and
  335. installed the software. And you're getting a feel for the many features of
  336. the product and the power that QuickPascal places at your fingertips. Now
  337. you're ready to use that power as you learn how to program in Pascal.
  338. QuickPascal makes learning easy with%@NL@%
  339. %@NL@%
  340. %@CR:MQP00002@%  ■  An integrated programming environment. You can write and edit code with%@NL@%
  341.      the built-in editor, and then compile, run, and save your programs with%@NL@%
  342.      easy-to-use menus.%@NL@%
  343. %@NL@%
  344.   ■  A powerful on-line help system, the QuickPascal Advisor. By pressing%@NL@%
  345.      one key, the F1 key, you can access everything you need to know about%@NL@%
  346.      the QuickPascal environment and about the Pascal language itself.%@NL@%
  347. %@NL@%
  348.   ■  An excellent debugger. You can find out exactly where a syntax error%@NL@%
  349.      occurred, or trace through a program to find errors in logic.%@NL@%
  350. %@NL@%
  351.   ■  Object-oriented extensions. You can use QuickPascal to learn and use%@NL@%
  352.      the newest concept in programming: object-oriented programming.%@NL@%
  353. %@NL@%
  354. %@NL@%
  355. %@CR:MQP01000@%%@2@%%@AB@%About This Book%@AE@%%@EH@%%@NL@%
  356. %@NL@%
  357. %@CR:MQP01001@%%@4@%This book, %@AI@%Pascal by Example%@AE@%, complements the on-line features of%@EH@%
  358. QuickPascal to teach you how to program in this language. In discussing
  359. programming terms and processes, this book refers frequently to example
  360. programs that are located on-line. Fragments of the example code are often
  361. quoted in text, thus teaching you as you read along. You can also load the
  362. whole example, so you can compile and experiment with working code.%@NL@%
  363. %@NL@%
  364. %@CR:MQP01002@%%@4@%As you read the book and run the example programs, you'll learn about these%@EH@%
  365. QuickPascal programming features:%@NL@%
  366. %@NL@%
  367. %@CR:MQP01003@%  ■  Programming basics such as variables, operators, and expressions%@NL@%
  368. %@NL@%
  369.   ■  Specific programming features such as strings, loops, units,%@NL@%
  370.      procedures, data types, and input/output%@NL@%
  371. %@NL@%
  372.   ■  Powerful graphics capabilities and object-oriented programming%@NL@%
  373. %@NL@%
  374. %@CR:MQP01004@%%@4@%%@AI@%Pascal by Example%@AE@% makes certain assumptions about your knowledge. It does%@EH@%
  375. not explain programming concepts and terms in their simplest form. This book
  376. assumes you have programmed in other programming languages but are not
  377. familiar with Pascal. The following list summarizes the book's contents:%@NL@%
  378. %@NL@%
  379. %@CR:MQP01005@%  ■  Part 1, "Pascal Basics," covers basic Pascal language fundamentals such%@NL@%
  380.      as procedures and data types. These chapters are designed to be read in%@NL@%
  381.      order, from beginning to end.%@NL@%
  382. %@NL@%
  383.   ■  Part 2, "Programming Topics," covers practical programming topics such%@NL@%
  384.      as using pointers and files. An advanced topics chapter discusses%@NL@%
  385.      bitwise operators, calling assembly language routines, and similar%@NL@%
  386.      problems.%@NL@%
  387. %@NL@%
  388.   ■  Part 3, "Graphics and Objects," covers QuickPascal graphics, which%@NL@%
  389.      include graphics primitives and font support. The final chapter%@NL@%
  390.      introduces you to the object extensions in QuickPascal. If you've never%@NL@%
  391.      seen object-oriented programming before, this will get you started.%@NL@%
  392. %@NL@%
  393.   ■  Appendix A%@BO:   829c0@%, "ASCII Character Codes and Extended Key Codes," provides%@NL@%
  394.      valuable reference information on ASCII codes and the extended key%@NL@%
  395.      codes returned by the %@AB@%Crt%@AE@% unit function %@AB@%ReadKey%@AE@%.%@NL@%
  396. %@NL@%
  397.   ■  Appendix B%@BO:   857d9@%, "Compiler Directives," lists all QuickPascal directives.%@NL@%
  398. %@NL@%
  399.   ■  Appendix C%@BO:   8964c@%, "Summary of Standard Units," briefly describes each unit%@NL@%
  400.      provided with QuickPascal.%@NL@%
  401. %@NL@%
  402.   ■  Appendix D%@BO:   8a285@%, "Quick Reference Guide," lists all QuickPascal keywords and%@NL@%
  403.      the standard units' procedures and functions.%@NL@%
  404. %@NL@%
  405. ───────────────────────────────────────────────────────────────────────────%@NL@%
  406. %@AI@%NOTE%@AE@%%@NL@%
  407.    Microsoft documentation uses the term "DOS" to refer to both the%@NL@%
  408.    MS-DOS(R) and IBM Personal Computer DOS operating systems. The name of a%@NL@%
  409.    specific operating system is used when it is necessary to note features%@NL@%
  410.    that are unique to that system.%@NL@%
  411. ───────────────────────────────────────────────────────────────────────────%@NL@%
  412. %@NL@%
  413. %@NL@%
  414. %@CR:MQP02000@%%@2@%%@AB@%Using the Example Programs%@AE@%%@EH@%%@NL@%
  415. %@NL@%
  416. %@CR:MQP02001@%%@4@%The QuickPascal Advisor includes all of the significant program examples in%@EH@%
  417. this book (although it doesn't include all of the code fragments). This
  418. feature allows you to load, run, and experiment with example programs as you
  419. read.%@NL@%
  420. %@NL@%
  421. %@CR:MQP02002@%%@4@%Every complete program in this book starts with a comment of this general%@EH@%
  422. form:%@NL@%
  423. %@NL@%
  424. %@AS@%     { %FTOC.PAS: converts temperatures }%@NL@%
  425. %@NL@%
  426. %@CR:MQP02003@%%@4@%The comment contains the program's name and a brief description of what it%@EH@%
  427. does. This program can be found in the QP Advisor as FTOC.PAS.%@NL@%
  428. %@NL@%
  429. %@CR:MQP02004@%%@4@%You must be using the QuickPascal environment to load an example. To load%@EH@%
  430. the example program, open the Help menu and choose the Contents command.
  431. Choose the title of this book from within the Contents screen. Then find the
  432. desired program in the list of %@AI@%Pascal by Example%@AE@% programs, and copy it into
  433. the source window using the Copy and Paste commands from the Edit menu.%@NL@%
  434. %@NL@%
  435. %@CR:MQP02005@%%@4@%After you copy an example program into the QuickPascal source window, treat%@EH@%
  436. it as you would any Pascal source program. You can compile or edit the
  437. program, save it on disk, and so on.%@NL@%
  438. %@NL@%
  439. %@CR:MQP02006@%%@4@%Note that you can easily print out an example program, in whole or in part,%@EH@%
  440. from Help or from your file, by choosing the Print command from the File
  441. menu.%@NL@%
  442. %@NL@%
  443. %@NL@%
  444. %@CR:MQP03000@%%@2@%%@AB@%Key to Document Conventions%@AE@%%@EH@%%@NL@%
  445. %@NL@%
  446. %@CR:MQP03001@%%@4@%This book uses the following document conventions:%@EH@%%@NL@%
  447. %@NL@%%@NL@%
  448. %@TH: 48 2568 2 23 53 @%
  449. %@AB@%Example%@AE@%                %@AB@%Description%@AE@%
  450. ────────────────────────────────────────────────────────────────────────────
  451. COPY TEST.OBJ C:       UPPERCASE type represents DOS commands and filenames.
  452. %@NL@%
  453. %@AB@%BEGIN%@AE@%                  Boldface type (whether in all uppercase or in both
  454.                        upper- and lowercase letters) indicates standard 
  455.                        features of the QuickPascal language: keywords,
  456.                        operators, and standard procdures and functions.
  457. %@NL@%
  458. %@AS@%PROGRAM FtoC%@AE@%           This typeface is used for example programs, program
  459. %@AS@%CONST%@AE@%                  fragments, and the names of user-defined procedures,
  460. %@AS@% Factor = 32.0%@AE@%         functions and variables. It also indicates user input
  461.                        and screen output.
  462. %@NL@%
  463. %@AI@%ArrayName%@AE@%              Words in italics indicate placeholders for
  464.                        information that you must supply. A file name is an
  465.                        example of this kind of information.
  466. %@NL@%
  467. «%@AI@%Option%@AE@%»               Items inside chevrons are optional.
  468. %@NL@%
  469. {%@AI@%Choice1%@AE@% | %@AI@%Choice2%@AE@%}    Braces and a vertical bar indicate a choice among two
  470.                        or more items. You must choose one of the items
  471.                        unless all of the items are also enclosed in
  472.                        chevrons.
  473. %@NL@%
  474. Repeating elements...  Three dots following an item indicate that more items
  475.                        having the same form may be entered.
  476. %@NL@%
  477. %@AS@%REPEAT%@AE@%                 A column of three dots indicates that part of the
  478. %@AS@%.%@AE@%                      example program has intentionally been omitted.
  479. %@AS@%.%@AE@%
  480. %@AS@%.%@AE@%
  481. %@AS@%UNTIL%@AE@%
  482. %@NL@%
  483. F1                     Small capital letters denote names of keys on the 
  484.                        keyboard. A plus (+) indicates a combination of keys.
  485.                        For example, SHIFT+F5 tells you to hold down the
  486.                        SHIFT key while pressing the F5 key.
  487. %@NL@%
  488. "array pointer"        The first time a new term is defined, it is enclosed
  489.                        in quotation marks. Since some knowledge of 
  490.                        programming is assumed, common terms such as memory
  491.                        or branch are not defined.
  492. %@NL@%
  493. American National      An acronym is spelled out the first time it appears.
  494. Standards Institute      
  495. (ANSI)
  496. ────────────────────────────────────────────────────────────────────────────%@NL@%
  497. %@TE: 48 2568 2 23 53 @%
  498. %@NL@% 
  499. %@CR:MQP03002@%
  500. %@NL@%
  501. %@CR:MQP04000@%%@2@%%@AB@%Other Books on Pascal Programming%@AE@%%@EH@%%@NL@%
  502. %@NL@%
  503. %@CR:MQP04001@%%@4@%This book introduces the Pascal language and some practical programming%@EH@%
  504. topics. It does not attempt to teach you basic computer programming or
  505. advanced Pascal programming techniques. The following books cover a variety
  506. of topics that you may find useful. They are listed only for your
  507. convenience. With the exception of its own publications, Microsoft does not
  508. endorse these books or recommend them over others on the same subject.%@NL@%
  509. %@NL@%
  510. %@CR:MQP04002@%Cooper, Doug. %@AI@%Standard Pascal: User Reference Manual%@AE@%. New York, NY: W.W.
  511. Norton & Company, 1983.%@NL@%
  512. %@NL@%
  513.   ■  A complete and concise reference manual to standard Pascal.%@NL@%
  514. %@NL@%
  515. Cooper, Doug and Michael Clancy. %@AI@%Oh! Pascal!%@AE@% 2d ed. New York, NY: W. W.
  516. Norton & Company, 1985.%@NL@%
  517. %@NL@%
  518.   ■  A beginner's introduction to standard Pascal.%@NL@%
  519. %@NL@%
  520. Craig, John Clark. %@AI@%Microsoft QuickPascal Programmer's%@AE@% %@AI@%Toolbox.%@AE@% Redmond, WA:
  521. Microsoft Press. In press.%@NL@%
  522. %@NL@%
  523.   ■  A sourcebook that beginners will find useful for learning by example.%@NL@%
  524.      Seasoned professionals using QuickPascal as a development system will%@NL@%
  525.      find the routines to be valuable and immediately useful extensions to%@NL@%
  526.      the Pascal language.%@NL@%
  527. %@NL@%
  528. Grogono, Peter. %@AI@%Programming in Pascal.%@AE@% rev. ed. Menlo Park, CA:
  529. Addison-Wesley, 1980.%@NL@%
  530. %@NL@%
  531.   ■  A good teaching source, but one that also covers sophisticated topics.%@NL@%
  532. %@NL@%
  533. Jamsa, Kris. %@AI@%Microsoft QuickPascal Programming.%@AE@% Redmond, WA: Microsoft
  534. Press. In press.%@NL@%
  535. %@NL@%
  536.   ■  A comprehensive introduction to mastering QuickPascal programming for%@NL@%
  537.      the beginning- to intermediate- level programmer complete with hands-on%@NL@%
  538.      examples.%@NL@%
  539. %@NL@%
  540. Jamsa, Kris. %@AI@%Microsoft QuickPascal: Programmer's Quick  Reference.%@AE@% Redmond,
  541. WA: Microsoft Press. In press.%@NL@%
  542. %@NL@%
  543.   ■  This alphabetical reference provides concise descriptions of all%@NL@%
  544.      QuickPascal procedures and functions.%@NL@%
  545. %@NL@%
  546. Kernighan, Brian W., and P.J. Plauger. %@AI@%Software Tools%@AE@% %@AI@%in Pascal%@AE@%. Menlo Park,
  547. CA: Addison-Wesley, 1981.%@NL@%
  548. %@NL@%
  549.   ■  A beginning- to intermediate-level guide to software tools and%@NL@%
  550.      programming techniques.%@NL@%
  551. %@NL@%
  552. Ladd, Robert Scott. %@AI@%Learning Object-Oriented Programming%@AE@% %@AI@%with Microsoft%@AE@%
  553. %@AI@%QuickPascal.%@AE@% Redmond, WA: Microsoft Press. In press.%@NL@%
  554. %@NL@%
  555.   ■  Provides an example-rich introduction to the philosophy and procedures%@NL@%
  556.      of object-oriented programming for the beginning- to intermediate-level%@NL@%
  557.      QuickPascal user.%@NL@%
  558. %@NL@%
  559. Leestma, Sanford, and Larry Nyhoff. %@AI@%Pascal: Programming%@AE@% %@AI@%and Problem%@AE@% %@AI@%Solving%@AE@%.
  560. New York, NY: Macmillan Publishing Company, 1987.%@NL@%
  561. %@NL@%
  562.   ■  A beginner's guide to Pascal programming. The book also covers problem%@NL@%
  563.      analysis, algorithm development, algorithm translation to Pascal, and%@NL@%
  564.      program validation.%@NL@%
  565. %@NL@%
  566. Wirth, Niklaus, and Kathleen Jensen. %@AI@%Pascal User Manual%@AE@% %@AI@%and Report.%@AE@% 3d ed.
  567. New York, NY: Springer-Verlag, 1985.%@NL@%
  568. %@NL@%
  569.   ■  The definitive source.%@NL@%
  570. %@NL@%
  571. %@NL@%
  572. %@CR:MQP05000@%%@2@%%@AB@%Getting Assistance or Reporting Problems%@AE@%%@EH@%%@NL@%
  573. %@NL@%
  574. %@CR:MQP05001@%%@4@%If you feel you have discovered a problem in the software, please report the%@EH@%
  575. problem using the Product Assistance Request form at the back of this book.%@NL@%
  576. %@NL@%
  577. %@CR:MQP05002@%%@4@%If you have comments or suggestions reqarding any of the books accompanying%@EH@%
  578. this product, please use the Documentation Feedback Card, also at the back
  579. of this book.%@NL@%
  580. %@NL@%
  581. %@CR:MQP05003@%
  582. %@NL@%
  583. ───────────────────────────────────────────────────────────────────────────%@NL@%
  584. %@CR:MQPP1000@%%@1@%%@AB@%Part 1  Pascal Basics%@AE@%%@EH@%%@NL@%
  585. %@NL@%
  586. %@CR:MQPP1004@%%@4@%Part 1 of %@AI@%Pascal by Example%@AE@% introduces you to the Pascal programming%@EH@%
  587. language and the basic elements of Pascal programs. The chapters in this
  588. part assume that you know some programming concepts but are not familiar
  589. with Pascal. Experienced Pascal programmers may want to skim these chapters.%@NL@%
  590. %@NL@%
  591. %@CR:MQPP1005@%%@4@%The information in Part 1 helps you start writing Pascal programs%@EH@%
  592. immediately. Chapters progress through such major topics as procedures,
  593. program flow, user-defined data types, and units. If you're new to Pascal,
  594. reading the chapters in this part sequentially will give you a thorough
  595. introduction to the fundamentals of programming in Pascal.%@NL@%
  596. %@NL@%
  597. %@NL@%
  598. %@CR:MQP10000@%%@1@%%@AB@%Chapter 1  Your First Pascal Program%@AE@%%@EH@%%@NL@%
  599. ───────────────────────────────────────────────────────────────────────────%@NL@%
  600. %@NL@%
  601. %@CR:MQP10001@%%@4@%You're probably eager to use QuickPascal and begin writing programs in%@EH@%
  602. Pascal. In this chapter, you'll compile and run your first Pascal program,
  603. FTOC.PAS, which is shown in Figure 1.1%@BO:    7b6b@%. As with all of the complete
  604. programs in this book, we've done the work of typing it in for you. You
  605. just need to use the Copy and Paste commands on the Edit menu to copy the
  606. program from the QuickPascal Advisor into a blank source window. Then you
  607. can press F5 to compile and run the program.%@NL@%
  608. %@NL@%
  609. %@CR:MQP10002@%%@4@%This chapter uses the sample program to introduce the parts of a Pascal%@EH@%
  610. program, some terms you should know, and input and output. Most of these
  611. terms are discussed in more detail in Chapter 2%@BO:    bdde@%.%@NL@%
  612. %@NL@%
  613. %@CR:MQP10003@%%@4@%If you're an experienced programmer in another structured language such as%@EH@%
  614. C, you might want to skip this chapter and begin with Chapter 2%@BO:    bdde@%,
  615. "Programming Basics," or Chapter 3%@BO:   13ad7@%, "Procedures and Functions."%@NL@%
  616. %@NL@%
  617. %@NL@%
  618. %@CR:MQP11000@%%@2@%%@AB@%1.1  Sample Pascal Program%@AE@%%@EH@%%@NL@%
  619. %@NL@%
  620. %@CR:MQP11001@%%@4@%FTOC.PAS is a simple program that converts temperatures from Fahrenheit to%@EH@%
  621. Celsius. Like all of the sample programs in this book, you'll find it in the
  622. QuickPascal Advisor. Figure 1.1%@BO:    7b6b@% contains the FTOC.PAS program code and
  623. illustrates the program parts.%@NL@%
  624. %@NL@%
  625. %@NL@%
  626. %@CR:MQPf0101@%%@4@%%@AB@%Figure 1.1  Parts of a Pascal Program%@AE@%%@EH@%%@NL@%
  627.             %@AB@%┌─────%@AE@%
  628.            %@FN@%
  629. Program declaration%@EF@%%@AB@%│%@AE@% %@AS@%PROGRAM FtoC;%@AE@%
  630.            %@FN@%
  631. Comment%@EF@%%@AB@%│%@AE@% %@AS@%{ FTOC.PAS: converts temperatures }
  632.             %@AB@%│%@AE@%
  633.            %@FN@%
  634. Uses statement%@EF@%%@AB@%│%@AE@% %@AS@%USES%@AE@%
  635.             %@AB@%│%@AE@%     %@AS@%Crt;%@AE@%
  636.             %@AB@%│%@AE@%
  637. %@AB@%Declara-    │%@AE@% %@AS@%CONST%@AE@%
  638.   %@AB@%tions     │%@AE@%     %@AS@%factor = 32.0;%@AE@%
  639.             %@AB@%│%@AE@%
  640.             %@AB@%│%@AE@% %@AS@%VAR%@AE@%
  641.            %@FN@%
  642. Variable declaration%@EF@%%@AB@%│%@AE@%     %@AS@%degrees_fahr, degrees_cel, answer : Real;%@AE@%
  643.             %@AB@%│%@AE@%
  644.            %@FN@%
  645. Function declaration%@EF@%%@AB@%│%@AE@% %@AS@%FUNCTION    ConvertToCel( degrees : Real ) : Real;%@AE@%
  646.             %@AB@%│%@AE@%     %@AS@%BEGIN%@AE@%
  647.             %@AB@%│%@AE@%         %@AS@%ConvertToCel := ((degrees - factor) * 5.0) / 9.0;%@AE@%
  648.             %@AB@%│%@AE@%     %@AS@%END;%@AE@%
  649.             %@AB@%└─────%@AE@%
  650.             %@AB@%┌─────%@AE@%
  651.             %@AB@%│%@AE@% %@AS@%BEGIN%@AE@%
  652.             %@AB@%│%@AE@%     %@AS@%ClrScr;%@AE@%
  653.             %@AB@%│%@AE@%     %@AS@%Writeln( 'Temperature Converter' );%@AE@%
  654.             %@AB@%│%@AE@%     %@AS@%Writeln( 'Fahrenheit to Celsius' );%@AE@%
  655.   %@AB@%Main      │%@AE@%     %@AS@%Writeln;%@AE@%
  656. %@AB@%Program     │%@AE@%     %@AS@%Write( 'Temperature in degrees Fahrenheit? ' );%@AE@%
  657.             %@AB@%│%@AE@%     %@AS@%Readln( degrees_fahr );%@AE@%
  658.             %@AB@%│%@AE@%     %@AS@%degrees_cel := ConvertToCel( degrees_fahr );%@AE@%
  659.             %@AB@%│%@AE@%     %@AS@%Writeln( 'Equals ', degrees_cel:4:1, ' degrees Celsius' );%@AE@%
  660.             %@AB@%│%@AE@%     %@AS@%Writeln;
  661.             %@AB@%│%@AE@% %@AS@%END.
  662.             %@AB@%└─────%@AE@%
  663. %@NL@%
  664. %@NL@%
  665. %@CR:MQP12000@%%@2@%%@AB@%1.2  Parts of a Pascal Program%@AE@%%@EH@%%@NL@%
  666. %@NL@%
  667. %@CR:MQP12001@%%@4@%Pascal is a highly structured language. Programs have parts, and the parts%@EH@%
  668. have a required order. This section explains the parts of a Pascal program.%@NL@%
  669. %@NL@%
  670. %@CR:MQP12010@%%@4@%%@AB@%The Program Declaration%@AE@%%@EH@%%@NL@%
  671. %@NL@%
  672. %@CR:MQP12011@%%@CR:MQP12012@%%@4@%Traditionally, the first line of every Pascal program contains the program%@EH@%
  673. declaration. This declaration consists of the keyword %@AB@%PROGRAM%@AE@%, the name of
  674. the program, and a semicolon. With Microsoft QuickPascal, such a declaration
  675. is not required, but it is still helpful as a way of labeling a program.
  676. Also, a program declaration is necessary if you want your program to compile
  677. on compilers other than those developed by Microsoft.%@NL@%
  678. %@NL@%
  679. %@CR:MQP12020@%%@4@%%@AB@%The USES Statement%@AE@%%@EH@%%@NL@%
  680. %@NL@%
  681. %@CR:MQP12021@%%@4@%The %@AB@%USES%@AE@% statement always follows the program declaration. It specifies%@EH@%
  682. which units are called from the program. Units are explained in detail in
  683. Chapter 7%@BO:   31ac9@%.%@NL@%
  684. %@NL@%
  685. %@CR:MQP12022@%%@4@%The %@AB@%USES%@AE@% statement in the FTOC.PAS program calls the %@AB@%Crt%@AE@% unit. This unit%@EH@%
  686. contains procedures and functions that allow you to control your computer
  687. screen.%@NL@%
  688. %@NL@%
  689. %@CR:MQP12030@%%@4@%%@AB@%Constant and Variable Declarations%@AE@%%@EH@%%@NL@%
  690. %@NL@%
  691. %@CR:MQP12031@%%@4@%Pascal requires that you declare constants, types, and variables before%@EH@%
  692. using them. The keywords %@AB@%CONST%@AE@%, %@AB@%TYPE%@AE@%, and %@AB@%VAR%@AE@% are used for this purpose.
  693. Constant declarations are made with the %@AB@%CONST%@AE@% keyword and include both the
  694. constant identifier (a name) and its value. For example, the constant shown
  695. in the FTOC.PAS program is named %@AS@%factor%@AE@% and has the value %@AS@%32.0%@AE@%.%@NL@%
  696. %@NL@%
  697. %@CR:MQP12032@%%@4@%The %@AB@%VAR%@AE@% keyword is used for variable declarations. Variable declarations%@EH@%
  698. include the variable identifier (a name) and its type. Multiple variables of
  699. the same type can be declared in the same statement.%@NL@%
  700. %@NL@%
  701. %@CR:MQP12040@%%@4@%%@AB@%Procedures and Functions%@AE@%%@EH@%%@NL@%
  702. %@NL@%
  703. %@CR:MQP12041@%%@4@%Procedure and function declarations come after the constant and variable%@EH@%
  704. declarations. Each procedure or function has its own %@AB@%BEGIN...END%@AE@% block.
  705. FTOC.PAS uses the function %@AS@%converttocel%@AE@% to convert the temperature from
  706. Fahrenheit to Celsius.%@NL@%
  707. %@NL@%
  708. %@CR:MQP12050@%%@4@%%@AB@%The Program Body%@AE@%%@EH@%%@NL@%
  709. %@NL@%
  710. %@CR:MQP12051@%%@4@%The body of the program, as shown in Figure 1.1%@BO:    7b6b@%, is enclosed by the keywords%@EH@%
  711. %@AB@%BEGIN%@AE@% and %@AB@%END%@AE@%. Pascal executes the instructions between %@AB@%BEGIN%@AE@% and %@AB@%END%@AE@%. The
  712. period after the %@AB@%END%@AE@% keyword tells Pascal that the program is over; anything
  713. that follows the period is ignored.%@NL@%
  714. %@NL@%
  715. %@CR:MQP12060@%%@4@%%@AB@%Comments%@AE@%%@EH@%%@NL@%
  716. %@NL@%
  717. %@CR:MQP12061@%%@4@%Comments are notes to yourself or others that make your programs easier to%@EH@%
  718. understand and maintain. Braces tell QuickPascal to ignore comment text.
  719. Instead of braces, comments can also be enclosed in parentheses and
  720. asterisks, as shown in this example:%@NL@%
  721. %@NL@%
  722. %@AS@%     (* This is a comment between the special symbols *)%@NL@%
  723. %@NL@%
  724. %@CR:MQP12062@%%@4@%The text on line 2 of FTOC.PAS is a comment.%@EH@%%@NL@%
  725. %@NL@%
  726. %@NL@%
  727. %@CR:MQP13000@%%@2@%%@AB@%1.3  Some Terms You Should Know%@AE@%%@EH@%%@NL@%
  728. %@NL@%
  729. %@CR:MQP13001@%%@4@%If you've never programmed before, the terms "keyword" and "identifier" may%@EH@%
  730. be confusing to you. These and other terms are discussed in this section. If
  731. you are an experienced programmer, you can skip this section and go on to
  732. Chapter 2%@BO:    bdde@%, "Programming Basics."%@NL@%
  733. %@NL@%
  734. %@NL@%
  735. %@CR:MQP13100@%%@3@%%@AB@%1.3.1  Keywords%@AE@%%@EH@%%@NL@%
  736. %@NL@%
  737. %@CR:MQP13101@%%@4@%Pascal contains a set of "keywords," or words that it reserves for its own%@EH@%
  738. use. Whenever the Pascal compiler encounters a keyword, a specific action is
  739. performed. In the sample program FTOC.PAS, the words %@AB@%PROGRAM%@AE@%, %@AB@%VAR%@AE@%, %@AB@%BEGIN%@AE@%,
  740. and %@AB@%END%@AE@% are all keywords. A keyword always means the same thing to a
  741. program; for example, the keyword %@AB@%BEGIN%@AE@% always signals the beginning of a
  742. statement block, and the keyword %@AB@%END%@AE@% always signals the end of a statement
  743. block.%@NL@%
  744. %@NL@%
  745. %@CR:MQP13102@%%@4@%The QuickPascal environment gives you the option of displaying keywords in a%@EH@%
  746. special color. This makes your programs easier to read on screen. See %@AI@%Up and%@AE@%
  747. %@AI@%Running%@AE@% for more information on how to display in color.%@NL@%
  748. %@NL@%
  749. %@CR:MQP13103@%%@4@%Always remember that you cannot use a keyword as a variable name or for%@EH@%
  750. anything other than its intended purpose. Keywords are shown in all
  751. uppercase letters in this book, and in the sample programs. A list of
  752. QuickPascal keywords is shown below:%@NL@%
  753. %@NL@%
  754. %@CR:MQP13104@%     %@AB@%ABSOLUTE%@AE@%              %@AB@%IF%@AE@%                    %@AB@%RECORD%@AE@%%@NL@%
  755.      %@AB@%AND%@AE@%                   %@AB@%IMPLEMENTATION%@AE@%        %@AB@%REPEAT%@AE@%%@NL@%
  756.      %@AB@%ARRAY%@AE@%                 %@AB@%IN%@AE@%                    %@AB@%SET%@AE@%%@NL@%
  757.      %@AB@%BEGIN%@AE@%                 %@AB@%INHERITED%@AE@%             %@AB@%SHL%@AE@%%@NL@%
  758.      %@AB@%CASE%@AE@%                  %@AB@%INLINE%@AE@%                %@AB@%SHR%@AE@%%@NL@%
  759.      %@AB@%CONST%@AE@%                 %@AB@%INTERFACE%@AE@%             %@AB@%STRING%@AE@%%@NL@%
  760.      %@AB@%CSTRING%@AE@%               %@AB@%INTERRUPT%@AE@%             %@AB@%THEN%@AE@%%@NL@%
  761.      %@AB@%DIV%@AE@%                   %@AB@%LABEL%@AE@%                 %@AB@%TO%@AE@%%@NL@%
  762.      %@AB@%DO%@AE@%                    %@AB@%MOD%@AE@%                   %@AB@%TYPE%@AE@%%@NL@%
  763.      %@AB@%DOWNTO%@AE@%                %@AB@%NIL%@AE@%                   %@AB@%UNIT%@AE@%%@NL@%
  764.      %@AB@%ELSE%@AE@%                  %@AB@%NOT%@AE@%                   %@AB@%UNTIL%@AE@%%@NL@%
  765.      %@AB@%END%@AE@%                   %@AB@%OBJECT%@AE@%                %@AB@%USES%@AE@%%@NL@%
  766.      %@AB@%EXTERNAL%@AE@%              %@AB@%OF%@AE@%                    %@AB@%VAR%@AE@%%@NL@%
  767.      %@AB@%FILE%@AE@%                  %@AB@%OR%@AE@%                    %@AB@%WHILE%@AE@%%@NL@%
  768.      %@AB@%FOR%@AE@%                   %@AB@%OVERRIDE%@AE@%              %@AB@%WITH%@AE@%%@NL@%
  769.      %@AB@%FORWARD%@AE@%               %@AB@%PACKED%@AE@%                %@AB@%XOR%@AE@%%@NL@%
  770.      %@AB@%FUNCTION%@AE@%              %@AB@%PROCEDURE%@AE@%%@NL@%
  771.      %@AB@%GOTO%@AE@%                  %@AB@%PROGRAM%@AE@%%@NL@%
  772. %@NL@%
  773. %@NL@%
  774. %@CR:MQP13200@%%@3@%%@AB@%1.3.2  Identifiers%@AE@%%@EH@%%@NL@%
  775. %@NL@%
  776. %@CR:MQP13201@%%@4@%"Identifiers" are names that you use in your program. In the example%@EH@%
  777. program, the word %@AS@%degrees_cel%@AE@% is the identifier for a variable. You could
  778. call it %@AS@%celsiusdegrees%@AE@% or %@AS@%cd%@AE@% or %@AS@%fred%@AE@% if you wanted to; however, for the sake
  779. of good programming practice, the name should provide information about the
  780. purpose of the variable. Thus %@AS@%degrees_cel%@AE@% is preferable to %@AS@%cd%@AE@% or %@AS@%fred%@AE@%.
  781. QuickPascal requires that you follow three rules when creating identifiers:%@NL@%
  782. %@NL@%
  783. %@CR:MQP13202@%  1. The first character of an identifier must be a letter or underscore%@NL@%
  784.      character (_).%@NL@%
  785. %@NL@%
  786.   2. Digits can be used within an identifier.%@NL@%
  787. %@NL@%
  788.   3. Identifier names can be of any length, but only the first 63 characters%@NL@%
  789.      are significant.%@NL@%
  790. %@NL@%
  791. %@CR:MQP13203@%%@4@%Thus, the following are examples of valid identifiers:%@EH@%%@NL@%
  792. %@NL@%
  793.      %@AS@%FirstTime%@AE@%%@NL@%
  794.      %@AS@%first_time%@AE@%%@NL@%
  795.      %@AS@%index0%@AE@%%@NL@%
  796.      %@AS@%area233%@AE@%%@NL@%
  797.      %@AS@%area_555%@AE@%%@NL@%
  798.      %@AS@%A4_9RT4_98NNS%@AE@%%@NL@%
  799. %@NL@%
  800. %@CR:MQP13204@%%@4@%By contrast, the following are examples of invalid identifiers:%@EH@%%@NL@%
  801. %@NL@%
  802. %@CR:MQP13205@%     %@AB@%Identifier      Reason It's Invalid%@AE@%%@NL@%
  803. %@NL@%
  804.      %@AS@%First Time%@AE@%      There is a space between %@AS@%First%@AE@% and %@AS@%Time%@AE@%.%@NL@%
  805.      %@AS@%index0$%@AE@%         The %@AS@%$%@AE@% sign is not a valid identifier character.%@NL@%
  806.      %@AS@%area!233%@AE@%        The %@AS@%!%@AE@% mark is not a valid identifier character.%@NL@%
  807.      %@AS@%555area%@AE@%         The first character is a digit.%@NL@%
  808. %@NL@%
  809. %@CR:MQP13206@%%@4@%Identifiers in Pascal are not case sensitive. This means that the%@EH@%
  810. identifiers %@AS@%First_Time%@AE@%, %@AS@%first_Time%@AE@%, %@AS@%first_time%@AE@%, and %@AS@%FIRST_TIME%@AE@% all refer to
  811. the same identifier. If these identifiers were typed in a program, the
  812. compiler would not generate an error. Instead, the compiler would treat them
  813. as the same identifier.%@NL@%
  814. %@NL@%
  815. %@CR:MQP13207@%%@4@%Some identifiers are defined by Microsoft. These identifiers name certain%@EH@%
  816. data types, standard procedures and functions, units, and variables and
  817. constants defined in standard units. In this manual and throughout the
  818. sample programs, these "standard identifiers" are shown with initial capital
  819. letters.%@NL@%
  820. %@NL@%
  821. %@NL@%
  822. %@CR:MQP13300@%%@3@%%@AB@%1.3.3  Constants and Variables%@AE@%%@EH@%%@NL@%
  823. %@NL@%
  824. %@CR:MQP13301@%%@4@%"Constants" and "variables" are two different ways for your program to use%@EH@%
  825. data. A constant is defined at the beginning of your program and always has
  826. the same value. In the sample program FTOC.PAS, the constant %@AS@%factor%@AE@% is
  827. assigned the value %@AS@%32.0%@AE@%. After such an assignment is made (using the %@AB@%CONST%@AE@%
  828. keyword), QuickPascal replaces the identifier %@AS@%factor%@AE@% with the value %@AS@%32.0%@AE@%
  829. whenever the identifier is encountered. Constants can make your program more
  830. readable and understandable.%@NL@%
  831. %@NL@%
  832. %@CR:MQP13302@%%@4@%Programs operate on data. In Pascal, as in other programming languages, data%@EH@%
  833. are stored in variables. Variables must be declared in a Pascal program
  834. before being used. Variable declarations follow the keyword %@AB@%VAR%@AE@% and have two
  835. parts: a variable name (identifier) and type. Data types are discussed
  836. below. In our sample program, both %@AS@%degrees_fahr%@AE@% and %@AS@%degrees_cel%@AE@% are
  837. variables of type %@AS@%Real%@AE@%.%@NL@%
  838. %@NL@%
  839. %@NL@%
  840. %@CR:MQP13400@%%@3@%%@AB@%1.3.4  Data Types%@AE@%%@EH@%%@NL@%
  841. %@NL@%
  842. %@CR:MQP13401@%%@4@%Pascal classifies data according to "type." Roughly speaking, data types%@EH@%
  843. allow the computer to determine how much memory a variable requires, and
  844. what level of precision should be maintained for a number. Type declarations
  845. keep you from making mistakes such as storing your zip code where your
  846. salary should be.%@NL@%
  847. %@NL@%
  848. %@CR:MQP13402@%%@4@%When you declare a variable, you must declare its type as well as its name.%@EH@%
  849. Data naturally falls into two general categories: text and numbers. Textual
  850. data items (which may include numbers, as in a street address) are referred
  851. to as "strings." Numbers can be integers (whole numbers such as 1 and 34) or
  852. real numbers (decimal numbers such as 29.5 and 3.14159). Four simple data
  853. types are illustrated below:%@NL@%
  854. %@NL@%
  855. %@CR:MQP13403@%      %@AB@%Data                  Type%@AE@%%@NL@%
  856. %@NL@%
  857.       %@AS@%Mary Smith%@AE@%            String%@NL@%
  858. %@NL@%
  859.       %@AS@%1413 Oak Lane%@AE@%         String%@NL@%
  860. %@NL@%
  861.       %@AS@%76%@AE@%                    Integer%@NL@%
  862. %@NL@%
  863.       %@AS@%21.0987%@AE@%               Real%@NL@%
  864. %@NL@%
  865.       %@AS@%Y%@AE@%                     Character%@NL@%
  866. %@NL@%
  867. %@CR:MQP13404@%%@4@%Data types are discussed in more detail in Chapter 2%@BO:    bdde@%, "Programming Basics."%@EH@%%@NL@%
  868. %@NL@%
  869. %@NL@%
  870. %@CR:MQP13500@%%@3@%%@AB@%1.3.5  Operators and Expressions%@AE@%%@EH@%%@NL@%
  871. %@NL@%
  872. %@CR:MQP13501@%%@4@%Operators are used in expressions to manipulate data within your program.%@EH@%
  873. Pascal includes many operators, but the simplest are already familiar to
  874. you: addition, subtraction, multiplication, and division. Another class of
  875. common operators are relational operators, such as "greater than," "less
  876. than," and "equal to." You'll use operators in your programs to do tasks
  877. such as counting how many lines you've printed on a page, or seeing if the
  878. number of hours someone worked in a week exceeds 40. More sophisticated uses
  879. for operators also exist, and those are discussed in Chapter 2%@BO:    bdde@%,
  880. "Programming Basics."%@NL@%
  881. %@NL@%
  882. %@CR:MQP13502@%%@4@%Expressions combine operators with data, as shown in the example below:%@EH@%%@NL@%
  883. %@NL@%
  884. %@AS@%       { Multiply the number of hours worked by the rate of%@NL@%
  885. %@AS@%         pay. Store the answer in the variable 'Salary'%@NL@%
  886. %@AS@%       }%@NL@%
  887.        %@AS@%salary := hours * pay_rate;%@NL@%
  888. %@NL@%
  889. %@NL@%
  890. %@CR:MQP14000@%%@2@%%@AB@%1.4  Input and Output%@AE@%%@EH@%%@NL@%
  891. %@NL@%
  892. %@CR:MQP14001@%%@4@%At the risk of oversimplification, you could say that most programs get some%@EH@%
  893. data, manipulate that data in some fashion, and display some final data to a
  894. user. So far in this chapter you've learned a bit about data and data
  895. manipulation. "Input" and "output" refer to the processes of getting and
  896. displaying data.%@NL@%
  897. %@NL@%
  898. %@CR:MQP14002@%%@4@%%@AB@%Input%@AE@%%@EH@%%@NL@%
  899. %@NL@%
  900. %@CR:MQP14003@%%@4@%Pascal programs frequently make use of the %@AB@%Read%@AE@% and %@AB@%Readln%@AE@% procedures for%@EH@%
  901. data input. %@AB@%Read%@AE@% is useful for getting a single keystroke──for instance,
  902. when you want the user to press a key to stop a process. %@AB@%Readln%@AE@% is useful
  903. when you want the user to be able to type and correct a complete line of
  904. text before the program accepts it. %@AB@%Readln%@AE@% doesn't do anything until the
  905. user presses ENTER, thus providing the user with the ability to edit the
  906. input line before sending it on to the program for processing.%@NL@%
  907. %@NL@%
  908. %@CR:MQP14004@%%@4@%In the example below, the first line that the user types is stored as the%@EH@%
  909. variable %@AS@%name%@AE@% and the next line is stored as %@AS@%address%@AE@%.%@NL@%
  910. %@NL@%
  911.      %@AS@%Readln( name );%@NL@%
  912.      %@AS@%Readln( address );%@NL@%
  913. %@NL@%
  914. %@CR:MQP14005@%%@4@%%@AB@%Output%@AE@%%@EH@%%@NL@%
  915. %@NL@%
  916. %@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@%
  917. %@AB@%Writeln%@AE@% differs from %@AB@%Write%@AE@% in that %@AB@%Writeln%@AE@% generates a carriage return at
  918. the end of the string (the line of text). Thus, %@AB@%Writeln%@AE@% moves the cursor to
  919. a new line on your output screen.%@NL@%
  920. %@NL@%
  921. %@NL@%
  922. %@CR:MQP15000@%%@2@%%@AB@%1.5  Moving On%@AE@%%@EH@%%@NL@%
  923. %@NL@%
  924. %@CR:MQP15001@%%@4@%So far you have looked at and compiled your first program, and you have been%@EH@%
  925. exposed to some basic Pascal terms. The next chapter elaborates on the
  926. concepts introduced here and shows you how to create some more complex
  927. programs.%@NL@%
  928. %@NL@%
  929. %@NL@%
  930. %@CR:MQP20000@%%@1@%%@AB@%Chapter 2  Programming Basics%@AE@%%@EH@%%@NL@%
  931. ───────────────────────────────────────────────────────────────────────────%@NL@%
  932. %@NL@%
  933. %@CR:MQP20001@%%@4@%This chapter introduces you to some Pascal programming fundamentals, such as%@EH@%
  934. data types, constants, variables, operators, and expressions. If you're
  935. already an experienced programmer in another language, you may find most of
  936. this material to be familiar. In that case, you might want to skim this
  937. chapter quickly or just skip ahead to Chapter 3%@BO:   13ad7@%.%@NL@%
  938. %@NL@%
  939. %@NL@%
  940. %@CR:MQP21000@%%@2@%%@AB@%2.1  Data Types%@AE@%%@EH@%%@NL@%
  941. %@NL@%
  942. %@CR:MQP21001@%%@4@%All data in your program is either a constant or a variable; each has an%@EH@%
  943. associated data type. Two kinds of data types exist in QuickPascal:
  944. predefined data types and user-defined data types. Predefined data types,
  945. such as %@AB@%Real%@AE@% and %@AB@%STRING%@AE@%, are a built-in part of the language and are
  946. discussed below. User-defined data types expand your programming power
  947. considerably. They are complex enough that Chapter 5%@BO:   21492@% of this book is
  948. devoted to them.%@NL@%
  949. %@NL@%
  950. %@CR:MQP21002@%%@4@%The predefined data types supported by QuickPascal and explained in the%@EH@%
  951. following sections are:%@NL@%
  952. %@NL@%
  953. %@CR:MQP21003@%  ■  Integers%@NL@%
  954.   ■  Floating-point numbers%@NL@%
  955.   ■  Characters%@NL@%
  956.   ■  Strings%@NL@%
  957.   ■  Booleans%@NL@%
  958. %@NL@%
  959. %@NL@%
  960. %@CR:MQP21100@%%@3@%%@AB@%2.1.1  Integer Types%@AE@%%@EH@%%@NL@%
  961. %@NL@%
  962. %@CR:MQP21101@%%@4@%Integers are whole numbers like the numbers you use to count with; that is,%@EH@%
  963. they have no fractional parts. The number 12 is an integer; 12.0 and 12.5
  964. are not. Table 2.1%@BO:    c523@% lists the five integer types that QuickPascal supports.
  965. Programs discussed later in this chapter show how these integers are used.%@NL@%
  966. %@NL@%
  967. %@CR:MQP2T100@%%@4@%%@AB@%Table 2.1  Integer Data Types%@AE@%%@EH@%%@NL@%
  968. %@NL@%
  969. %@AB@%Integer Type       Range of Values       Byte Size    Examples%@AE@%%@NL@%
  970. %@NL@%
  971. %@AB@%ShortInt%@AE@%           -128 to 127           1            -7, 55, 123, 0, $F%@NL@%
  972. %@NL@%
  973. %@AB@%Byte%@AE@%               0 to 255              1            55, 123, $F, 0%@NL@%
  974. %@NL@%
  975. %@AB@%Integer%@AE@%            -32768 to 32767       2            -555, 30000, 0, $FF%@NL@%
  976. %@NL@%
  977. %@AB@%Word%@AE@%               0 to 65535            2            30000, 60000, $FFFF%@NL@%
  978. %@NL@%
  979. %@AB@%LongInt%@AE@%            -2147483648 to        4            -100000, 100000, $FFFF%@NL@%
  980.                     2147483647%@NL@%
  981. %@NL@%
  982. %@NL@%
  983. %@CR:MQP21102@%%@4@%The integer types %@AB@%Byte%@AE@% and %@AB@%Word%@AE@% are called "unsigned" integers, while the%@EH@%
  984. other integer types are called "signed" integers. The word "unsigned"
  985. indicates that the integer includes values from zero to the upper positive
  986. limit. Signed integers include negative numbers.%@NL@%
  987. %@NL@%
  988. %@CR:MQP21103@%%@4@%You can see that the main difference between the different integer types is%@EH@%
  989. the range of the values that can be stored. In the %@AB@%VAR%@AE@% section of your
  990. program, you declare the variable identifier and the specific type.%@NL@%
  991. %@NL@%
  992. %@CR:MQP21104@%%@4@%As the examples in Table 2.1%@BO:    c523@% show, QuickPascal allows you to write integers%@EH@%
  993. in either decimal (base 10) or hexadecimal notation (base 16). Hexadecimal
  994. numbers begin with the dollar sign ($) and use the characters 0-9 and A-F.%@NL@%
  995. %@NL@%
  996. %@CR:MQP21105@%%@4@%The INTTYPES.PAS program below demonstrates different types of integers.%@EH@%%@NL@%
  997. %@NL@%
  998. %@AS@%     PROGRAM Inttypes;%@NL@%
  999. %@AS@%     { INTTYPES.PAS demonstrates integer data types. }%@NL@%
  1000. %@NL@%
  1001. %@AS@%     USES%@NL@%
  1002. %@AS@%         Crt;%@NL@%
  1003. %@NL@%
  1004. %@AS@%     VAR%@NL@%
  1005. %@AS@%         short_int_val    :   ShortInt;%@NL@%
  1006. %@AS@%         byte_val         :   Byte;%@NL@%
  1007. %@AS@%         integer_val      :   Integer;%@NL@%
  1008. %@AS@%         word_val         :   Word;%@NL@%
  1009. %@AS@%         long_int_val     :   LongInt;%@NL@%
  1010. %@NL@%
  1011. %@NL@%
  1012. %@AS@%     BEGIN%@NL@%
  1013. %@AS@%         short_int_val := -31;%@NL@%
  1014. %@AS@%         byte_val      := 255;%@NL@%
  1015. %@AS@%         integer_val   := -21212;%@NL@%
  1016. %@AS@%         word_val      := $FFFF;%@NL@%
  1017. %@AS@%         long_int_val  := 12918656;%@NL@%
  1018. %@AS@%         ClrScr;%@NL@%
  1019. %@AS@%         Writeln( 'short_int_val = ', short_int_val );%@NL@%
  1020. %@AS@%         Writeln( 'byte_val      = ', byte_val );%@NL@%
  1021. %@AS@%         Writeln( 'integer_val   = ', integer_val );%@NL@%
  1022. %@AS@%         Writeln( 'word_val      = ', word_val );%@NL@%
  1023. %@AS@%         Writeln( 'long_int_val  = ', long_int_val );%@NL@%
  1024. %@AS@%     END.%@NL@%
  1025. %@NL@%
  1026. %@CR:MQP21106@%%@4@%Here is the output from INTTYPES.PAS:%@EH@%%@NL@%
  1027. %@NL@%
  1028.      %@AS@%short_int_val  = -31%@AE@%%@NL@%
  1029.      %@AS@%byte_val  = 255%@AE@%%@NL@%
  1030.      %@AS@%integer_val    = -21212%@AE@%%@NL@%
  1031.      %@AS@%word_val  = 65535%@AE@%%@NL@%
  1032.      %@AS@%long_int_val   = 12918656%@AE@%%@NL@%
  1033. %@NL@%
  1034. %@NL@%
  1035. %@CR:MQP21200@%%@3@%%@AB@%2.1.2  Floating-Point Types%@AE@%%@EH@%%@NL@%
  1036. %@NL@%
  1037. %@CR:MQP21201@%%@4@%Floating-point numbers are not integers; that is, they are written with a%@EH@%
  1038. decimal point. Thus the number 12.5 is a floating-point number, as is
  1039. .00021459862. Also, QuickPascal treats constants larger than its maximum as
  1040. long-integer size floating-point numbers, even if they do not contain a
  1041. decimal point. Floating-point numbers are also referred to as "real"
  1042. numbers.%@NL@%
  1043. %@NL@%
  1044. %@CR:MQP21202@%%@4@%QuickPascal supports a group of floating-point types that vary in their%@EH@%
  1045. precision, range of values, and storage requirements. They are shown in
  1046. Table 2.2.%@NL@%
  1047. %@NL@%
  1048. %@CR:MQP2T200@%%@4@%%@AB@%Table 2.2  Floating-Point Data Types%@AE@%%@EH@%%@NL@%
  1049. %@NL@%
  1050. %@AB@%Type              Range of Value            Byte Size     Significant Digits%@AE@%%@NL@%
  1051. %@NL@%
  1052. %@AB@%Single%@AE@%            1.5E-45 to 3.4E+38         4            7-8%@NL@%
  1053. %@NL@%
  1054. %@AB@%Real%@AE@%              2.9E-39 to 1.7E+38         6            11-12%@NL@%
  1055. %@NL@%
  1056. %@AB@%Double%@AE@%            5.0E-324 to 1.7E+308       8            15-16%@NL@%
  1057. %@NL@%
  1058. %@AB@%Extended%@AE@%          3.4E-4951 to 1.1E+4932    10            15-16%@NL@%
  1059. %@NL@%
  1060. %@AB@%Comp%@AE@%              -9.2E+18 to 9.2E+18        8            15-16%@NL@%
  1061. %@NL@%
  1062. %@NL@%
  1063. %@CR:MQP21203@%%@4@%By default, QuickPascal assumes that your computer does not use a math%@EH@%
  1064. coprocessor, resulting in fewer significant digits than if it did use a
  1065. coprocessor. However, if you have a math coprocessor available (any member
  1066. of the 8087 family of processors), you can increase the precision of %@AB@%Comp%@AE@%
  1067. and %@AB@%Extended%@AE@% data types by 4 significant digits by including the %@AB@%{$N+}%@AE@%
  1068. compiler directive in your program.%@NL@%
  1069. %@NL@%
  1070. %@CR:MQP21204@%%@4@%Unlike some other Pascal compilers, QuickPascal makes all real number types%@EH@%
  1071. available for your use, whether or not your computer has a numeric
  1072. coprocessor.%@NL@%
  1073. %@NL@%
  1074. %@CR:MQP21205@%%@4@%The %@AB@%Comp%@AE@% type is a little different from the other floating-point types.%@EH@%
  1075. %@AB@%Comp%@AE@% is designed to count very large numbers, and so it stores only the
  1076. integer part of a number between -(2^63)+1 and (2^63)-1.%@NL@%
  1077. %@NL@%
  1078. %@NL@%
  1079. %@CR:MQP21300@%%@3@%%@AB@%2.1.3  Character Type%@AE@%%@EH@%%@NL@%
  1080. %@NL@%
  1081. %@CR:MQP21301@%%@4@%The character data type %@AB@%Char%@AE@% stores only one character. Each character%@EH@%
  1082. occupies one byte of storage. You can represent characters using the
  1083. following formats:%@NL@%
  1084. %@NL@%
  1085. %@CR:MQP21302@%%@AB@%Characters                  Representation%@AE@%%@NL@%
  1086. %@NL@%
  1087. Readable characters         Can be represented by using same letters,%@NL@%
  1088. (that is, the alphabet,     digits, and punctuation.%@NL@%
  1089. digits, and punctuation     %@NL@%
  1090. characters)                 %@NL@%
  1091. %@NL@%
  1092. Control characters          Can be represented using the carat symbol (^)%@NL@%
  1093. (ASCII characters 0         followed by the control letter. For example, the%@NL@%
  1094. through 31)                 form feed is represented by ^L, since form feed%@NL@%
  1095.                             is ASCII 12 and L is the 12th letter in the%@NL@%
  1096.                             alphabet. Appendix A%@BO:   829c0@% contains a chart of all%@NL@%
  1097.                             ASCII codes.%@NL@%
  1098. %@NL@%
  1099. All characters,             Can be represented by using the number sign (#)%@NL@%
  1100. including those in the      followed by the ASCII code number. Thus, #65 is%@NL@%
  1101. extended ASCII table        the letter A, #12 is the form feed, and so on.%@NL@%
  1102. %@NL@%
  1103. %@NL@%
  1104. %@CR:MQP21400@%%@3@%%@AB@%2.1.4  String Types%@AE@%%@EH@%%@NL@%
  1105. %@NL@%
  1106. %@CR:MQP21401@%%@4@%This data type stores a string of characters such as a name or an address.%@EH@%
  1107. QuickPascal strings can hold up to 255 characters. Many of the examples in
  1108. this book use strings to display messages and store input. The STRINGS.PAS
  1109. program demonstrates how to create, read, and write simple strings.%@NL@%
  1110. %@NL@%
  1111. %@AS@%     PROGRAM Strings;%@NL@%
  1112. %@NL@%
  1113. %@AS@%     { STRINGS.PAS demonstrates basic string operations. }%@NL@%
  1114. %@NL@%
  1115. %@AS@%     USES%@NL@%
  1116. %@AS@%         Crt;%@NL@%
  1117. %@NL@%
  1118. %@AS@%     CONST%@NL@%
  1119. %@AS@%         str_constant = 'Type something and press Enter: ';%@NL@%
  1120. %@NL@%
  1121. %@AS@%     VAR%@NL@%
  1122. %@AS@%         prompt_one : STRING;%@NL@%
  1123. %@AS@%         prompt_two : STRING;%@NL@%
  1124. %@AS@%         input_str  : STRING;%@NL@%
  1125. %@NL@%
  1126. %@AS@%     BEGIN%@NL@%
  1127. %@AS@%         prompt_one := str_constant;%@NL@%
  1128. %@AS@%         prompt_two := 'You typed: ';%@NL@%
  1129. %@NL@%
  1130. %@AS@%         ClrScr;%@NL@%
  1131. %@AS@%         Write( prompt_one );%@NL@%
  1132. %@AS@%         Readln( input_str );%@NL@%
  1133. %@AS@%         Write( prompt_two );%@NL@%
  1134. %@AS@%         Writeln( input_str );%@NL@%
  1135. %@AS@%     END.%@NL@%
  1136. %@NL@%
  1137. %@CR:MQP21402@%%@4@%Here is typical output from STRINGS.PAS:%@EH@%%@NL@%
  1138. %@NL@%
  1139.      %@AS@%Type something and press Enter: QuickPascal!%@AE@%%@NL@%
  1140.      %@AS@%You typed: QuickPascal!%@AE@%%@NL@%
  1141. %@NL@%
  1142. %@CR:MQP21410@%%@4@%%@AB@%2.1.4.1  Declaring Strings%@AE@%%@EH@%%@NL@%
  1143. %@NL@%
  1144. %@CR:MQP21411@%%@4@%Pascal strings are usually of the %@AB@%STRING%@AE@% type. In STRINGS.PAS, the%@EH@%
  1145. statements%@NL@%
  1146. %@NL@%
  1147. %@AS@%     VAR%@NL@%
  1148. %@AS@%         prompt_one : STRING;%@NL@%
  1149. %@AS@%         prompt_two : STRING;%@NL@%
  1150. %@AS@%         input_str  : STRING;%@NL@%
  1151. %@NL@%
  1152. %@CR:MQP21412@%%@4@%declare three string variables named %@AS@%prompt_one%@AE@%, %@AS@%prompt_two%@AE@%, and %@AS@%input_str%@AE@%.%@EH@%%@NL@%
  1153. %@NL@%
  1154. %@CR:MQP21420@%%@4@%%@AB@%2.1.4.2  Initializing Strings%@AE@%%@EH@%%@NL@%
  1155. %@NL@%
  1156. %@CR:MQP21421@%%@4@%You can initialize string variables by assigning string literals or%@EH@%
  1157. constants to them:%@NL@%
  1158. %@NL@%
  1159. %@AS@%     CONST%@NL@%
  1160. %@AS@%         str_constant = 'Type something and press Enter: ';%@NL@%
  1161. %@AS@%         .%@NL@%
  1162. %@AS@%         .%@NL@%
  1163. %@AS@%         .%@NL@%
  1164. %@AS@%         prompt_one := str_constant;  { Assign string constant }%@NL@%
  1165. %@AS@%         prompt_two := 'You typed: '; { Assign string literal }%@NL@%
  1166. %@NL@%
  1167. %@CR:MQP21422@%%@4@%Pascal strings can contain as many as 255 characters. The first character of%@EH@%
  1168. a string is a "length byte" that indicates the number of characters in the
  1169. string. Procedures such as %@AB@%Writeln%@AE@% look at this byte to determine the
  1170. string's size.%@NL@%
  1171. %@NL@%
  1172. %@CR:MQP21423@%%@4@%Thus, if you assign %@AS@%Hello%@AE@% to a string variable, the variable actually%@EH@%
  1173. contains six characters: a length byte that contains the number 5, followed
  1174. by the 5 characters of %@AS@%Hello%@AE@%.%@NL@%
  1175. %@NL@%
  1176. %@CR:MQP21430@%%@4@%%@AB@%2.1.4.3  Reading and Writing Strings%@AE@%%@EH@%%@NL@%
  1177. %@NL@%
  1178. %@CR:MQP21431@%%@4@%You can use the %@AB@%Read%@AE@% and %@AB@%Readln%@AE@% procedures to read a string:%@EH@%%@NL@%
  1179. %@NL@%
  1180. %@AS@%     Readln( input_str );%@NL@%
  1181. %@NL@%
  1182. %@CR:MQP21432@%%@4@%and the %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% procedures to write a string:%@EH@%%@NL@%
  1183. %@NL@%
  1184. %@AS@%     Write( prompt_two );%@NL@%
  1185. %@AS@%     Writeln( input_str );%@NL@%
  1186. %@NL@%
  1187. %@CR:MQP21433@%%@4@%These procedures read input from the keyboard and write output to the%@EH@%
  1188. screen. See Chapter 8%@BO:   35d22@%, "The Keyboard and Screen," for more information on
  1189. input and output.%@NL@%
  1190. %@NL@%
  1191. %@NL@%
  1192. %@CR:MQP21500@%%@3@%%@AB@%2.1.5  Boolean Type%@AE@%%@EH@%%@NL@%
  1193. %@NL@%
  1194. %@CR:MQP21501@%%@4@%A variable of type %@AB@%Boolean%@AE@% can be assigned a value of true or false.%@EH@%
  1195. Variables of this type are often used as "flags" when a condition in your
  1196. program becomes true (or false). Suppose, for example, that you wanted to
  1197. check whether a user had finished entering data. If the variable %@AS@%all_done%@AE@%
  1198. had been declared as type %@AB@%Boolean%@AE@%, you may use it like this:%@NL@%
  1199. %@NL@%
  1200. %@AS@%     IF (x = 0) THEN all_done := true;%@NL@%
  1201. %@NL@%
  1202. %@CR:MQP21502@%%@4@%Later you may need to check the %@AS@%all_done%@AE@% variable:%@EH@%%@NL@%
  1203. %@NL@%
  1204. %@AS@%     IF (all_done = True) THEN ...%@NL@%
  1205. %@NL@%
  1206. %@CR:MQP21503@%%@4@%A shorthand way of writing this statement is%@EH@%%@NL@%
  1207. %@NL@%
  1208. %@AS@%     IF (all_done) THEN ...%@NL@%
  1209. %@NL@%
  1210. %@CR:MQP21504@%%@4@%It is understood that %@AS@%IF all_done%@AE@% means the same as %@AS@%IF (all_done  = True)%@AE@%%@EH@%
  1211. and by the same understanding, %@AS@%IF (NOT all_done)%@AE@% means %@AS@%IF (all_done  =%@AE@%
  1212. %@AS@%False%@AE@%).%@NL@%
  1213. %@NL@%
  1214. %@CR:MQP21505@%%@4@%For more information about %@AB@%Boolean%@AE@% types and what you can do with them, see%@EH@%
  1215. Chapter 12, "Advanced Topics."%@NL@%
  1216. %@NL@%
  1217. %@NL@%
  1218. %@CR:MQP22000@%%@2@%%@AB@%2.2  Constants%@AE@%%@EH@%%@NL@%
  1219. %@NL@%
  1220. %@CR:MQP22001@%%@4@%Fixed data, or "constants," are assigned a value which is never changed (an%@EH@%
  1221. exception to this, called "typed constants," is discussed below). When you
  1222. declare constants in Pascal, you assign them a name and value. This value,
  1223. once assigned, cannot be changed in your program. The assignment of name and
  1224. value to a constant is called a constant declaration.%@NL@%
  1225. %@NL@%
  1226. %@CR:MQP22002@%%@4@%QuickPascal supports two kinds of constants: simple and typed.%@EH@%%@NL@%
  1227. %@NL@%
  1228. %@NL@%
  1229. %@CR:MQP22100@%%@3@%%@AB@%2.2.1  Simple Constants%@AE@%%@EH@%%@NL@%
  1230. %@NL@%
  1231. %@CR:MQP22101@%%@4@%Simple constants can be used for two purposes. First, they can store fixed%@EH@%
  1232. values, like the number of inches in a foot. Second, they can store values
  1233. you wish to use within your program, like the text of a title screen or your
  1234. assumption for the rate of inflation. Since constants are all declared at
  1235. the beginning of your program, it is easy to change any of those values and
  1236. recompile your program. Remember, changing the value of a constant in its
  1237. initial declaration gives that new value to the constant wherever it is
  1238. used. In fact, any other constants that depend on the one you alter will
  1239. also receive their updated values when you recompile the program.%@NL@%
  1240. %@NL@%
  1241. %@CR:MQP22102@%%@4@%The general syntax for declaring and initializing a constant is:%@EH@%%@NL@%
  1242. %@NL@%
  1243. %@CR:MQP22103@%%@4@%%@AB@%CONST%@AE@% %@AI@%ConstantIdentifier%@AE@% = {%@AI@%ConstantValue%@AE@%|%@AI@%Expression%@AE@%}%@EH@%%@NL@%
  1244. %@NL@%
  1245. %@CR:MQP22104@%%@4@%For example:%@EH@%%@NL@%
  1246. %@NL@%
  1247. %@AS@%     CONST%@NL@%
  1248. %@NL@%
  1249. %@AS@%         ft_per_mile = 5280;%@NL@%
  1250. %@NL@%
  1251. %@CR:MQP22105@%%@4@%In this example, the %@AI@%ConstantIdentifier%@AE@% is %@AS@%ft_per_mile%@AE@% and the%@EH@%
  1252. %@AI@%ConstantValue%@AE@% is %@AS@%5280%@AE@%.%@NL@%
  1253. %@NL@%
  1254. %@CR:MQP22106@%%@4@%In QuickPascal, you can use an expression that contains a previously%@EH@%
  1255. declared constant. You can also set a constant equal to an expression, as in%@NL@%
  1256. %@NL@%
  1257. %@AS@%     CONST%@NL@%
  1258. %@NL@%
  1259. %@AS@%         days_per_year = 365;%@NL@%
  1260. %@AS@%         seconds_per_day = 60 * 60 * 24;%@NL@%
  1261. %@AS@%         light_speed = 186282;%@NL@%
  1262. %@AS@%         light_year = light_speed * seconds_per_day%@NL@%
  1263. %@AS@%                      * days_per_year;%@NL@%
  1264. %@NL@%
  1265. %@CR:MQP22107@%%@4@%However, if you declare a constant equal to an expression, that expression%@EH@%
  1266. can only contain simple operations like addition, subtraction,
  1267. multiplication, and division. More advanced Pascal functions like square
  1268. root cannot be used.%@NL@%
  1269. %@NL@%
  1270. %@CR:MQP22108@%%@4@%Here are some more examples of constants:%@EH@%%@NL@%
  1271. %@NL@%
  1272. %@AS@%     CONST%@NL@%
  1273. %@NL@%
  1274. %@AS@%         max_row = 10;%@NL@%
  1275. %@AS@%         max_col = 10;%@NL@%
  1276. %@NL@%
  1277. %@AS@%       { Uses previously declared constants  }%@NL@%
  1278. %@AS@%         table_size = max_row * max_col;%@NL@%
  1279. %@NL@%
  1280. %@AS@%         prompt = 'Press any key to resume...';%@NL@%
  1281. %@AS@%         byebye = 'Thank you for using the program...';%@NL@%
  1282. %@NL@%
  1283. %@AS@%         euler_const = 0.577215664901;%@NL@%
  1284. %@NL@%
  1285. %@AS@%       { An approximation of the Euler constant }%@NL@%
  1286. %@AS@%         euler_const2 = 228.0 / 395.0;%@NL@%
  1287. %@NL@%
  1288. %@NL@%
  1289. %@CR:MQP22200@%%@3@%%@AB@%2.2.2  Typed Constants%@AE@%%@EH@%%@NL@%
  1290. %@NL@%
  1291. %@CR:MQP22201@%%@4@%QuickPascal lets you use another kind of constant called a "typed constant."%@EH@%
  1292. In standard Pascal, you can't specify the data type of a constant. The
  1293. compiler assigns the data a type according to how it is presented. For
  1294. example, a constant called %@AS@%number_of_people%@AE@% with a value of 35 would be
  1295. assigned an integer type by QuickPascal, which makes sense. However, if you
  1296. declared %@AS@%number_of_people%@AE@% equal to 35.0, then the compiler would assign a
  1297. real number type to %@AS@%number_of_people%@AE@%, which doesn't make much sense.%@NL@%
  1298. %@NL@%
  1299. %@CR:MQP22202@%%@4@%Fortunately, QuickPascal allows you to specifically state the data type%@EH@%
  1300. associated with a constant, which is the typed constant. You may also see
  1301. the terms "variable constant" or "static variable" used to describe such a
  1302. constant. Declaring data with a typed constant actually changes the constant
  1303. into an initialized variable. That is, the value associated with the
  1304. typed-constant identifier can be changed in the program, unlike regular
  1305. constants whose value cannot be changed within the program.%@NL@%
  1306. %@NL@%
  1307. %@CR:MQP22203@%%@4@%A typed constant can be thought of as a cross between a constant and a%@EH@%
  1308. variable. A constant's value is declared but can never be changed. A
  1309. variable, on the other hand, is not declared with a predefined value, and
  1310. its value can change within the program. A typed constant is like a variable
  1311. whose predefined value is declared but which can be redefined within the
  1312. program.%@NL@%
  1313. %@NL@%
  1314. %@CR:MQP22204@%%@4@%The general syntax is shown below:%@EH@%%@NL@%
  1315. %@NL@%
  1316. %@CR:MQP22205@%%@4@%%@AB@%CONST%@AE@% %@AI@%ConstantIdentifier%@AE@% : %@AI@%TypeName%@AE@% = {%@AI@%ConstantValue%@AE@%|%@AI@%Expression%@AE@%}%@EH@%%@NL@%
  1317. %@NL@%
  1318. %@CR:MQP22206@%%@4@%Examples of typed constant declarations are given below. Note that the%@EH@%
  1319. %@AI@%ConstantValue%@AE@% or %@AI@%Expression%@AE@% assigned to the typed constant is much like a
  1320. value or expression assigned to a regular variable. Note that you use the
  1321. :%@AI@%TypeName%@AE@% to specify the type of the constant, as you would in a %@AB@%VAR%@AE@%
  1322. declaration.%@NL@%
  1323. %@NL@%
  1324. %@AS@%     CONST%@NL@%
  1325. %@NL@%
  1326. %@AS@%         max_row : Word = 10;%@NL@%
  1327. %@AS@%         max_col : Word = 10;%@NL@%
  1328. %@AS@%         table_size : Word = max_row * max_col;%@NL@%
  1329. %@NL@%
  1330. %@AS@%         prompt : STRING = 'Press any key to resume...';%@NL@%
  1331. %@AS@%         byebye : STRING = 'Thank you for using the program...';%@NL@%
  1332. %@NL@%
  1333. %@AS@%         euler_const : Real = 0.577215664901;%@NL@%
  1334. %@AS@%         { An approximation to the Euler const }%@NL@%
  1335. %@AS@%         euler_const2 : Real = 228.0 / 395.0;%@NL@%
  1336. %@NL@%
  1337. %@NL@%
  1338. %@CR:MQP23000@%%@2@%%@AB@%2.3  Simple Variables%@AE@%%@EH@%%@NL@%
  1339. %@NL@%
  1340. %@CR:MQP23001@%%@4@%While constants are identifiers that are declared and assigned a fixed%@EH@%
  1341. value, variables are identifiers that are merely declared. They are assigned
  1342. values in the main program or a subprogram. The general syntax for declaring
  1343. a variable and identifying its type is as follows:%@NL@%
  1344. %@NL@%
  1345.      %@AB@%VAR%@AE@% %@AI@%VariableName%@AE@% «, %@AI@%VariableName%@AE@%...» : %@AI@%DataType%@AE@%%@NL@%
  1346.         .%@NL@%
  1347.         .%@NL@%
  1348.         .%@NL@%
  1349. %@NL@%
  1350. %@CR:MQP23003@%%@4@%Some examples of declaring variables:%@EH@%%@NL@%
  1351. %@NL@%
  1352. %@AS@%     VAR%@NL@%
  1353. %@AS@%         { Variables declared with predefined type }%@NL@%
  1354. %@AS@%         column_index : Word;%@NL@%
  1355. %@AS@%         area, circumference : Real;%@NL@%
  1356. %@AS@%         message : STRING;%@NL@%
  1357. %@AS@%         input_character : Char;%@NL@%
  1358. %@NL@%
  1359. %@CR:MQP23004@%%@4@%Once a variable is declared, QuickPascal sets aside the required amount of%@EH@%
  1360. memory to store data associated with the variable. The amount of memory set
  1361. aside is based on the variable's data type. For example, a variable declared
  1362. with type %@AS@%STRING[40]%@AE@% gets 41 bytes of memory of which 40 bytes are available
  1363. for data (the remaining byte holds the string length); a variable with type
  1364. %@AS@%Integer%@AE@% gets 2 bytes of memory.%@NL@%
  1365. %@NL@%
  1366. %@CR:MQP23005@%%@4@%Once a variable is declared, you may assign it a value. Often you will use%@EH@%
  1367. the assignment operator (%@AB@%:=%@AE@%), which should not be confused with the equality
  1368. operator (%@AB@%=%@AE@%). The assigned value can be a constant, another variable, or an
  1369. expression.%@NL@%
  1370. %@NL@%
  1371. %@CR:MQP23006@%%@4@%The VARS.PAS program shows a simple assignment of variables. The variable%@EH@%
  1372. radius is assigned a value through user input (the %@AB@%Readln%@AE@% procedure). The
  1373. variable area is assigned the value of an expression using the assignment
  1374. operator.%@NL@%
  1375. %@NL@%
  1376. %@AS@%     PROGRAM Vars;%@NL@%
  1377. %@AS@%         { VARS.PAS: variable declaration and use }%@NL@%
  1378. %@NL@%
  1379. %@AS@%     VAR%@NL@%
  1380. %@AS@%         radius, area   :   Real;%@NL@%
  1381. %@NL@%
  1382. %@AS@%     BEGIN%@NL@%
  1383. %@AS@%         Writeln( 'Enter radius' );%@NL@%
  1384. %@AS@%         Readln( radius );%@NL@%
  1385. %@AS@%         Area := (Pi * (radius * radius));%@NL@%
  1386. %@AS@%         Writeln( 'Area of the circle = ', area:8:2 );%@NL@%
  1387. %@AS@%         Writeln;%@NL@%
  1388. %@AS@%     END.%@NL@%
  1389. %@NL@%
  1390. %@CR:MQP23007@%%@4@%Typical output from VARS.PAS looks like this:%@EH@%%@NL@%
  1391. %@NL@%
  1392.      %@AS@%Enter radius%@AE@%%@NL@%
  1393.      %@AS@%12%@AE@%%@NL@%
  1394.      %@AS@%Area of the circle =   452.39%@AE@%%@NL@%
  1395. %@NL@%
  1396. %@NL@%
  1397. %@CR:MQP24000@%%@2@%%@AB@%2.4  Pascal Operators%@AE@%%@EH@%%@NL@%
  1398. %@NL@%
  1399. %@CR:MQP24001@%%@4@%Operators let you manipulate data. Pascal operators are used to build%@EH@%
  1400. expressions. This section describes some of the operators available in
  1401. Microsoft QuickPascal. In addition to the ones discussed here, QuickPascal
  1402. supports some operators for advanced use, including bitwise and set
  1403. operators. The bitwise operators are discussed in detail in Chapter 12%@BO:   517ed@%,
  1404. "Advanced Topics." Set operators are discussed in Chapter 5%@BO:   21492@%, "User-Defined
  1405. Data Types."%@NL@%
  1406. %@NL@%
  1407. %@NL@%
  1408. %@CR:MQP24100@%%@3@%%@AB@%2.4.1  Kinds of Operators%@AE@%%@EH@%%@NL@%
  1409. %@NL@%
  1410. %@CR:MQP24101@%%@4@%QuickPascal supports the following categories of operators:%@EH@%%@NL@%
  1411. %@NL@%
  1412. %@CR:MQP24102@%  ■  Arithmetic%@NL@%
  1413.   ■  Relational%@NL@%
  1414.   ■  String%@NL@%
  1415.   ■  Address-of%@NL@%
  1416. %@NL@%
  1417. %@CR:MQP24110@%%@4@%%@AB@%2.4.1.1  Arithmetic Operators%@AE@%%@EH@%%@NL@%
  1418. %@NL@%
  1419. %@CR:MQP24111@%%@4@%Table 2.3%@BO:   11a7d@% lists the arithmetic operators, which perform numeric %@EH@%
  1420. manipulation of integer and floating-point types. While the addition (%@AB@%+%@AE@%),
  1421. subtraction (%@AB@%-%@AE@%), and multiplication (%@AB@%*%@AE@%) operators work with both integers
  1422. and floating-point types, the division (%@AB@%/%@AE@%) operator performs floating-point
  1423. division (even if the operands are integers), and the %@AB@%DIV%@AE@% and %@AB@%MOD%@AE@% operators
  1424. work with integers only.%@NL@%
  1425. %@NL@%
  1426. %@CR:MQP24112@%%@4@%While most of the operators take two operands, the unary plus and unary%@EH@%
  1427. minus operators work with one operand only.%@NL@%
  1428. %@NL@%
  1429. %@CR:MQP2T300@%%@4@%%@AB@%Table 2.3  Arithmetic Operators%@AE@%%@EH@%%@NL@%
  1430. %@NL@%
  1431.       %@AB@%Operator       Purpose%@AE@%%@NL@%
  1432.  %@NL@%
  1433.       %@AB@%+%@AE@%              Unary plus sign%@NL@%
  1434.  %@NL@%
  1435.       %@AB@%-%@AE@%              Unary minus sign%@NL@%
  1436.  %@NL@%
  1437.       %@AB@%+%@AE@%              Adds two numbers%@NL@%
  1438.  %@NL@%
  1439.       %@AB@%-%@AE@%              Subtracts two numbers%@NL@%
  1440.  %@NL@%
  1441.       %@AB@%*%@AE@%              Multiplies two numbers%@NL@%
  1442.  %@NL@%
  1443.       %@AB@%/%@AE@%              Divides two floating-point numbers%@NL@%
  1444.  %@NL@%
  1445.       %@AB@%DIV%@AE@%            Divides two integer numbers%@NL@%
  1446.  %@NL@%
  1447.       %@AB@%MOD%@AE@%            Returns the remainder of integer division%@NL@%
  1448. %@NL@%
  1449. %@NL@%
  1450. %@CR:MQP24120@%%@4@%%@AB@%2.4.1.2  Relational Operators%@AE@%%@EH@%%@NL@%
  1451. %@NL@%
  1452. %@CR:MQP24121@%%@4@%Relational operators are used to compare two operands, which may be%@EH@%
  1453. constants, variables, functions, or expressions. The operands must be of the
  1454. same or compatible types. Some useful relational operators are shown in
  1455. Table 2.4.%@NL@%
  1456. %@NL@%
  1457. %@CR:MQP2T400@%%@4@%%@AB@%Table 2.4  Relational Operators%@AE@%%@EH@%%@NL@%
  1458. %@NL@%
  1459.       %@AB@%Operator        Purpose%@AE@%%@NL@%
  1460.  %@NL@%
  1461.       %@AB@%=%@AE@%               Equal to%@NL@%
  1462.       %@AB@%<>%@AE@%              Not equal to%@NL@%
  1463.       %@AB@%>%@AE@%               Greater than%@NL@%
  1464.       %@AB@%>=%@AE@%              Greater than or equal to%@NL@%
  1465.       %@AB@%<%@AE@%               Less than%@NL@%
  1466.       %@AB@%<=%@AE@%              Less than or equal to%@NL@%
  1467. %@NL@%
  1468. %@NL@%
  1469. %@CR:MQP24130@%%@4@%%@AB@%2.4.1.3  String Operators%@AE@%%@EH@%%@NL@%
  1470. %@NL@%
  1471. %@CR:MQP24131@%%@4@%QuickPascal has one string operator, the (%@AB@%+%@AE@%) operator, for string and%@EH@%
  1472. character concatenation. Other aspects of string manipulation are performed
  1473. by predefined procedures and functions.%@NL@%
  1474. %@NL@%
  1475. %@CR:MQP24140@%%@4@%%@AB@%2.4.1.4  Address-Of Operator%@AE@%%@EH@%%@NL@%
  1476. %@NL@%
  1477. %@CR:MQP24141@%%@4@%The address-of operator (%@AB@%@%@AE@%) is used to return the address of variables,%@EH@%
  1478. routines, parameters, and so forth. The topic of pointers is covered fully
  1479. in Chapter 11%@BO:   48f3e@%.%@NL@%
  1480. %@NL@%
  1481. %@NL@%
  1482. %@CR:MQP24200@%%@3@%%@AB@%2.4.2  Operator Precedence%@AE@%%@EH@%%@NL@%
  1483. %@NL@%
  1484. %@CR:MQP24201@%%@4@%Operators in expressions are evaluated in order of their precedence. Table%@EH@%
  1485. 2.5%@BO:   12531@% lists the QuickPascal operators according to their precedence level.
  1486. Although not all of the operators shown in the table are discussed in this
  1487. section, they are in the table for the sake of completeness. For information
  1488. on operators such as %@AB@%SHL%@AE@% or %@AB@%XOR%@AE@%, see Chapter 12%@BO:   517ed@%, "Advanced Topics," or use
  1489. QP Advisor.%@NL@%
  1490. %@NL@%
  1491. %@CR:MQP2T500@%%@4@%%@AB@%Table 2.5  Operator Precedence%@AE@%%@EH@%%@NL@%
  1492. %@NL@%
  1493. %@AB@%Precedence Level      Operators                            Operator Class%@AE@%%@NL@%
  1494. %@NL@%
  1495. 1 (highest)           %@AB@%@%@AE@%, %@AB@%NOT%@AE@%                               Unary%@NL@%
  1496. 2                     %@AB@%*%@AE@%, %@AB@%/%@AE@%, %@AB@%DIV%@AE@%, %@AB@%MOD%@AE@%, %@AB@%AND%@AE@%, %@AB@%SHL%@AE@%, %@AB@%SHR%@AE@%        Multiplying%@NL@%
  1497. 3                     %@AB@%+%@AE@%, %@AB@%-%@AE@%, %@AB@%OR%@AE@%, %@AB@%XOR%@AE@%                        Adding%@NL@%
  1498. 4 (lowest)            %@AB@%=%@AE@%, %@AB@%<>%@AE@%, %@AB@%<%@AE@%, %@AB@%<=%@AE@%, %@AB@%>%@AE@%, %@AB@%>=%@AE@%, %@AB@%IN%@AE@%              Relational%@NL@%
  1499. %@NL@%
  1500. %@NL@%
  1501. %@CR:MQP24202@%%@4@%The following list interprets this table and gives examples of the use of%@EH@%
  1502. operators.%@NL@%
  1503. %@NL@%
  1504. %@CR:MQP24203@%  ■  The operation defined by the operator with highest precedence and its%@NL@%
  1505.      related operand is performed first. In the example%@NL@%
  1506. %@NL@%
  1507.         %@AS@%2 * 4 + 3%@AE@%%@NL@%
  1508. %@NL@%
  1509.      the number %@AS@%4%@AE@% is placed between two operators of different precedence.%@NL@%
  1510.      Since the (%@AB@%*%@AE@%) operator has a higher precedence, multiplication of %@AS@%2%@AE@% and%@NL@%
  1511.      %@AS@%4%@AE@% proceeds first. The addition is performed afterward.%@NL@%
  1512. %@NL@%
  1513.   ■  Operations of the same precedence level are performed from left to%@NL@%
  1514.      right. In the example%@NL@%
  1515. %@NL@%
  1516.         %@AS@%2 * 4 / 3%@AE@%%@NL@%
  1517. %@NL@%
  1518.      the number %@AS@%4%@AE@% is placed between two operators of the same precedence.%@NL@%
  1519.      Since the (%@AB@%*%@AE@%) operator appears to the left of number %@AS@%4%@AE@%, it is applied%@NL@%
  1520.      before the (%@AB@%/%@AE@%) operator.%@NL@%
  1521. %@NL@%
  1522.   ■  Parentheses are used to group operations. Expressions enclosed in%@NL@%
  1523.      parentheses are evaluated first. The most deeply nested expression is%@NL@%
  1524.      evaluated before any other. (Nested expressions are expressions within%@NL@%
  1525.      expressions.) Parentheses alter the "effective" or "working" precedence%@NL@%
  1526.      of an operator. In the example%@NL@%
  1527. %@NL@%
  1528.         %@AS@%2 / ((3 + 4) * 5)%@AE@%%@NL@%
  1529. %@NL@%
  1530.      the expression in the parentheses %@AS@%(3 + 4)%@AE@% is evaluated first, since it%@NL@%
  1531.      is the most nested expression in parentheses. The (%@AB@%*%@AE@%) operator is%@NL@%
  1532.      applied next, since it is enclosed in parentheses, giving it a higher%@NL@%
  1533.      effect precedence. Finally, the (%@AB@%/%@AE@%) operator is applied.%@NL@%
  1534. %@NL@%
  1535. %@NL@%
  1536. %@CR:MQP25000@%%@2@%%@AB@%2.5  Simple Pascal Expressions%@AE@%%@EH@%%@NL@%
  1537. %@NL@%
  1538. %@CR:MQP25001@%%@4@%Expressions are a special and very important part of any programming%@EH@%
  1539. language. They are created to evaluate data in your program. Expressions use
  1540. the operators described in Section 2.4%@BO:   11422@% and operands, which are the data
  1541. types in your program, as their components. QuickPascal supports simple and
  1542. advanced expressions.%@NL@%
  1543. %@NL@%
  1544. %@CR:MQP25002@%%@4@%This chapter briefly presents the simple expressions. Each type of%@EH@%
  1545. expression follows a syntax rule which gives its components and syntax. The
  1546. simple expressions explained in this chapter are%@NL@%
  1547. %@NL@%
  1548. %@CR:MQP25003@%  ■  Arithmetic%@NL@%
  1549. %@NL@%
  1550.   ■  String%@NL@%
  1551. %@NL@%
  1552. %@NL@%
  1553. %@CR:MQP25100@%%@3@%%@AB@%2.5.1  Arithmetic Expressions%@AE@%%@EH@%%@NL@%
  1554. %@NL@%
  1555. %@CR:MQP25101@%%@4@%Arithmetic expressions combine constants, numbers, variables, and functions%@EH@%
  1556. with arithmetic operators.%@NL@%
  1557. %@NL@%
  1558. %@CR:MQP25102@%%@4@%The syntax of an expression is%@EH@%%@NL@%
  1559. %@NL@%
  1560. %@CR:MQP25103@%%@4@%{ %@AI@%Constant%@AE@% | %@AI@%Expression%@AE@% } |%@EH@%%@NL@%
  1561. %@NL@%
  1562. %@CR:MQP25104@%%@4@%« %@AI@%Constant%@AE@% | %@AI@%Expression%@AE@% » { %@AI@%Operator%@AE@% %@AI@%Constant%@AE@% | %@AI@%Expression%@AE@% }%@EH@%%@NL@%
  1563. %@NL@%
  1564. %@CR:MQP25105@%%@4@%For example%@EH@%%@NL@%
  1565. %@NL@%
  1566. %@AS@%     (length * width)%@NL@%
  1567. %@NL@%
  1568. %@CR:MQP25106@%%@4@%Expressions combine with constants or variables and relational or assignment%@EH@%
  1569. operators to make Pascal statements:%@NL@%
  1570. %@NL@%
  1571. %@AS@%     area := (length * width)%@NL@%
  1572. %@NL@%
  1573. %@CR:MQP25107@%%@4@%In the example above, the expression %@AS@%length * width%@AE@% is evaluated, then the%@EH@%
  1574. result is stored in the variable %@AS@%area%@AE@%.%@NL@%
  1575. %@NL@%
  1576. %@CR:MQP25108@%%@4@%Expressions are evaluated according to operator precedence. Using%@EH@%
  1577. parentheses to force the correct evaluation of an expression is always a
  1578. good idea.%@NL@%
  1579. %@NL@%
  1580. %@CR:MQP25109@%%@4@%An expression may contain nested expressions, which are expressions within%@EH@%
  1581. expressions. Examples are shown below:%@NL@%
  1582. %@NL@%
  1583. %@AS@%     K := (1 + 6) DIV (55 - J);%@NL@%
  1584. %@AS@%     Z := (2 * X) + (Y / 4);%@NL@%
  1585. %@AS@%     T := (((2 * X + 2) * X - 5) * X + 1) * X - 10;%@NL@%
  1586. %@NL@%
  1587. %@NL@%
  1588. %@CR:MQP25200@%%@3@%%@AB@%2.5.2  String Expressions%@AE@%%@EH@%%@NL@%
  1589. %@NL@%
  1590. %@CR:MQP25201@%%@4@%String expressions use the (%@AB@%+%@AE@%) operator to concatenate strings and%@EH@%
  1591. characters. The general syntax rule is shown below:%@NL@%
  1592. %@NL@%
  1593. %@CR:MQP25202@%%@4@%{%@AI@%Character%@AE@% | %@AI@%String%@AE@%} + {%@AI@%Character%@AE@% | %@AI@%String%@AE@%}...%@EH@%%@NL@%
  1594. %@NL@%
  1595. %@CR:MQP25203@%%@4@%For example%@EH@%%@NL@%
  1596. %@NL@%
  1597. %@AS@%     'dog' + 'house';   { creates the word "doghouse" }%@NL@%
  1598. %@NL@%
  1599. %@CR:MQP25204@%%@4@%The (%@AB@%+%@AE@%) operator works identically to the %@AB@%Concat%@AE@% function. String and%@EH@%
  1600. character concatenation cannot build a string longer than 255 characters.%@NL@%
  1601. %@NL@%
  1602. %@NL@%
  1603. %@CR:MQP30000@%%@1@%%@AB@%Chapter 3  Procedures and Functions%@AE@%%@EH@%%@NL@%
  1604. ───────────────────────────────────────────────────────────────────────────%@NL@%
  1605. %@NL@%
  1606. %@CR:MQP30001@%%@4@%Procedures and functions allow you to write well-organized Pascal programs,%@EH@%
  1607. in which discrete tasks are done in separate, logically contained modules.
  1608. Once you understand procedures and functions, you are well on your way to
  1609. becoming a true Pascal programmer.%@NL@%
  1610. %@NL@%
  1611. %@CR:MQP30002@%%@4@%This chapter begins by discussing procedures, which are simpler and more%@EH@%
  1612. commonly used than functions. The discussion covers many topics, such as
  1613. argument passing, that are common to both procedures and functions. The
  1614. chapter ends with an explanation of functions, nested procedures, and
  1615. recursion.%@NL@%
  1616. %@NL@%
  1617. %@NL@%
  1618. %@CR:MQP31000@%%@2@%%@AB@%3.1  Overview%@AE@%%@EH@%%@NL@%
  1619. %@NL@%
  1620. %@CR:MQP31001@%%@4@%Procedures and functions let you program using a "divide and conquer"%@EH@%
  1621. approach. Instead of trying to solve every aspect of a large problem at
  1622. once, you divide it into several small problems and solve each one
  1623. separately. This strategy allows you to write clear, reliable programs that
  1624. perform different tasks in distinct, logically contained modules. In Pascal,
  1625. these modules are called procedures or functions.%@NL@%
  1626. %@NL@%
  1627. %@CR:MQP31002@%%@4@%Dividing a program into task-based modules offers several advantages:%@EH@%%@NL@%
  1628. %@NL@%
  1629. %@CR:MQP31003@%  ■  Makes programs easier to write and read. All of the statements related%@NL@%
  1630.      to a task are located in one place.%@NL@%
  1631. %@NL@%
  1632.   ■  Prevents unexpected side effects because you can use private ("local")%@NL@%
  1633.      variables that are not visible to the main program or other sections.%@NL@%
  1634. %@NL@%
  1635.   ■  Eliminates unnecessary repetition of code for frequently performed%@NL@%
  1636.      tasks.%@NL@%
  1637. %@NL@%
  1638.   ■  Simplifies debugging. Once you have debugged a procedure or function,%@NL@%
  1639.      you can use it with confidence in many different situations.%@NL@%
  1640. %@NL@%
  1641. %@CR:MQP31004@%%@4@%The distinction between procedures and functions can be summarized in a few%@EH@%
  1642. words. A procedure performs a specific task; a function performs a specific
  1643. task and also returns a value. We will return to this topic in Section 3.3%@BO:   1927a@%,
  1644. "Functions."%@NL@%
  1645. %@NL@%
  1646. %@CR:MQP31005@%%@4@%If you are familiar with Microsoft QuickBASIC, you will notice many%@EH@%
  1647. similarities in Pascal. A Pascal procedure resembles a QuickBASIC %@AB@%SUB%@AE@%
  1648. procedure, and a Pascal function is like a QuickBASIC %@AB@%FUNCTION%@AE@% procedure. If
  1649. you know the C language, you will notice that a C function combines the
  1650. qualities of Pascal procedures and functions; a C function can return a
  1651. value, or return nothing.%@NL@%
  1652. %@NL@%
  1653. %@NL@%
  1654. %@CR:MQP32000@%%@2@%%@AB@%3.2  Procedures%@AE@%%@EH@%%@NL@%
  1655. %@NL@%
  1656. %@CR:MQP32001@%%@4@%Procedures and functions are very similar──so similar, in fact, that%@EH@%
  1657. everything explained in this section applies to functions as well as
  1658. procedures. To avoid repeating the phrase "procedures and functions" with
  1659. every sentence, this section refers only to procedures. You should read it
  1660. with the understanding that these ideas also apply to functions. Section
  1661. 3.3%@BO:   1927a@%, "Functions," explains how functions differ from procedures.%@NL@%
  1662. %@NL@%
  1663. %@CR:MQP32002@%%@4@%A "procedure" is a collection of declarations and statements that performs a%@EH@%
  1664. certain task. You have already seen a few of the QuickPascal standard
  1665. procedures, such as %@AB@%Writeln%@AE@%, which writes a line. This section explains
  1666. procedures using several programs. The first example, CENTER.PAS, contains a
  1667. procedure that centers a line on the screen:%@NL@%
  1668. %@NL@%
  1669. %@AS@%     PROGRAM center;%@NL@%
  1670. %@NL@%
  1671. %@AS@%     { CENTER.PAS: Demonstrate simple procedure }%@NL@%
  1672. %@NL@%
  1673. %@AS@%     USES%@NL@%
  1674. %@AS@%         Crt;%@NL@%
  1675. %@NL@%
  1676. %@AS@%     VAR%@NL@%
  1677. %@AS@%         row   : Byte;%@NL@%
  1678. %@AS@%         title : STRING;%@NL@%
  1679. %@NL@%
  1680. %@AS@%     PROCEDURE center_line( message : STRING; line : Byte );%@NL@%
  1681. %@AS@%         BEGIN%@NL@%
  1682. %@AS@%             GotoXY( 40 - Length( message ) DIV 2, line );%@NL@%
  1683. %@AS@%             Writeln( message );%@NL@%
  1684. %@AS@%         END;%@NL@%
  1685. %@NL@%
  1686. %@AS@%     BEGIN%@NL@%
  1687. %@AS@%         row   := 2;%@NL@%
  1688. %@AS@%         title := 'Each line of text is centered.';%@NL@%
  1689. %@AS@%         ClrScr;%@NL@%
  1690. %@AS@%         center_line( title, row );%@NL@%
  1691. %@AS@%         center_line( '--------', row+1 );%@NL@%
  1692. %@AS@%         center_line( 'Microsoft QuickPascal!', row+2 );%@NL@%
  1693. %@AS@%     END.%@NL@%
  1694. %@NL@%
  1695. %@CR:MQP32003@%%@4@%The CENTER.PAS program displays these lines on the screen:%@EH@%%@NL@%
  1696. %@NL@%
  1697. %@AS@%     Each line of text is centered.%@NL@%
  1698. %@AS@%                --------%@NL@%
  1699. %@AS@%         Microsoft QuickPascal!%@NL@%
  1700. %@NL@%
  1701. %@CR:MQP32004@%%@4@%The rest of this section refers frequently to the CENTER.PAS example.%@EH@%%@NL@%
  1702. %@NL@%
  1703. %@NL@%
  1704. %@CR:MQP32100@%%@3@%%@AB@%3.2.1  Calling Procedures%@AE@%%@EH@%%@NL@%
  1705. %@NL@%
  1706. %@CR:MQP32101@%%@4@%The CENTER.PAS program uses a procedure named %@AS@%center_line%@AE@% to center a line.%@EH@%
  1707. You "call," or execute, a procedure by stating its name and by supplying any
  1708. "arguments," or data items that it might require. The %@AS@%center_line%@AE@% procedure
  1709. expects you to supply two arguments: a piece of text to print, and the
  1710. screen line on which to print it. To print the message%@NL@%
  1711. %@NL@%
  1712.      %@AS@%Vite!%@AE@%%@NL@%
  1713. %@NL@%
  1714. %@CR:MQP32102@%%@4@%on the second screen line, you would call %@AS@%center_line%@AE@% with this statement:%@EH@%%@NL@%
  1715. %@NL@%
  1716. %@AS@%     center_line( 'Vite!', 2 );%@NL@%
  1717. %@NL@%
  1718. %@CR:MQP32103@%%@4@%You list the arguments in parentheses after the procedure name, placing a%@EH@%
  1719. comma between each two arguments. Here, the first argument is the string
  1720. %@AS@%Vite!%@AE@% and the second is the number %@AS@%2%@AE@%. Later in this chapter, you will learn
  1721. how a procedure handles the arguments it receives.%@NL@%
  1722. %@NL@%
  1723. %@NL@%
  1724. %@CR:MQP32200@%%@3@%%@AB@%3.2.2  Declaring Procedures%@AE@%%@EH@%%@NL@%
  1725. %@NL@%
  1726. %@CR:MQP32201@%%@4@%A procedure "declaration" contains the complete code for the procedure. Here%@EH@%
  1727. is the procedure declaration for %@AS@%center_line%@AE@%:%@NL@%
  1728. %@NL@%
  1729. %@AS@%     PROCEDURE center_line( message : STRING; line : Byte );%@NL@%
  1730. %@AS@%         BEGIN%@NL@%
  1731. %@AS@%             GotoXY( 40 - Length( message ) DIV 2, line );%@NL@%
  1732. %@AS@%             Write( message );%@NL@%
  1733. %@AS@%         END;%@NL@%
  1734. %@NL@%
  1735. %@CR:MQP32202@%%@4@%A procedure declaration has two parts, called the "head" and the "body." A%@EH@%
  1736. procedure head consists of the %@AB@%PROCEDURE%@AE@% keyword, followed by the
  1737. procedure's name and a list of its arguments in parentheses. It ends with a
  1738. semicolon. Here is the head of the %@AS@%center_line%@AE@% procedure:%@NL@%
  1739. %@NL@%
  1740. %@AS@%     PROCEDURE center_line( message : STRING; line : Byte );%@NL@%
  1741. %@NL@%
  1742. %@CR:MQP32203@%%@4@%The list of arguments states the name and type of each argument. This%@EH@%
  1743. example states that %@AS@%center_line%@AE@% requires two arguments, one each of the data
  1744. types %@AB@%STRING%@AE@% and %@AB@%BYTE%@AE@%. The first argument is named %@AS@%message,%@AE@% and the second
  1745. argument is named %@AS@%line%@AE@%.%@NL@%
  1746. %@NL@%
  1747. %@CR:MQP32204@%%@4@%The procedure body is a statement block that contains the procedure's%@EH@%
  1748. executable statements. Like other blocks, the procedure body is enclosed in
  1749. %@AB@%BEGIN%@AE@% and %@AB@%END%@AE@%, and it ends with a semicolon. Here is the body of the
  1750. %@AS@%center_line%@AE@% procedure:%@NL@%
  1751. %@NL@%
  1752. %@AS@%     BEGIN%@NL@%
  1753. %@AS@%         GotoXY( 40 - Length( message ) DIV 2, line );%@NL@%
  1754. %@AS@%         Write( message );%@NL@%
  1755. %@AS@%     END;%@NL@%
  1756. %@NL@%
  1757. %@CR:MQP32205@%%@4@%The body of the %@AS@%center_line%@AE@% procedure contains two statements, each of which%@EH@%
  1758. calls a standard Pascal procedure. The first calls the %@AB@%GotoXY%@AE@% procedure and
  1759. the second calls %@AB@%Write%@AE@%.%@NL@%
  1760. %@NL@%
  1761. %@CR:MQP32210@%%@4@%%@AB@%Forward Declarations%@AE@%%@EH@%%@NL@%
  1762. %@NL@%
  1763. %@CR:MQP32211@%%@4@%Pascal requires that you declare an entity before using it. Before using a%@EH@%
  1764. variable, for instance, you must declare its name and type. The same rule
  1765. applies to a procedure. Before calling a procedure, you must declare it as
  1766. explained in the previous section.%@NL@%
  1767. %@NL@%
  1768. %@CR:MQP32212@%%@4@%In simple programs, such as CENTER.PAS, it's easy to satisfy the "declare%@EH@%
  1769. before calling" rule. Simply place all of your procedure declarations before
  1770. the main program body. In CENTER.PAS, the %@AS@%center_line%@AE@% procedure declaration
  1771. appears before the main program.%@NL@%
  1772. %@NL@%
  1773. %@CR:MQP32213@%%@4@%Occasionally, however, you may need to call a procedure before it has been%@EH@%
  1774. declared. This can be done by providing a "forward declaration" of the
  1775. procedure prior to the procedure call.%@NL@%
  1776. %@NL@%
  1777. %@CR:MQP32214@%%@4@%A forward declaration is identical to a procedure head, except that it%@EH@%
  1778. contains both the keyword %@AB@%FORWARD%@AE@% and a semicolon after the argument list.
  1779. For instance, the %@AS@%center_line%@AE@% procedure head looks like this%@NL@%
  1780. %@NL@%
  1781. %@AS@%     PROCEDURE center_line( message : STRING; line : Byte );%@NL@%
  1782. %@NL@%
  1783. %@CR:MQP32215@%%@4@%and its forward declaration looks like this%@EH@%%@NL@%
  1784. %@NL@%
  1785. %@AS@%     PROCEDURE center_line( message : STRING; line : Byte );%@NL@%
  1786. %@AS@%     FORWARD;%@NL@%
  1787. %@NL@%
  1788. %@CR:MQP32216@%%@4@%The forward declaration must appear before the first reference to the%@EH@%
  1789. procedure. Most programmers put forward references at or very near the
  1790. beginning of the program.%@NL@%
  1791. %@NL@%
  1792. %@NL@%
  1793. %@CR:MQP32300@%%@3@%%@AB@%3.2.3  Declaring Local Variables%@AE@%%@EH@%%@NL@%
  1794. %@NL@%
  1795. %@CR:MQP32301@%%@4@%In addition to statements, the procedure body can contain variable%@EH@%
  1796. declarations. Variables declared in a procedure are said to be "local,"
  1797. meaning they can be seen only inside the procedure. Because their visibility
  1798. is limited, local variables are less likely to be changed accidentally than
  1799. global variables.%@NL@%
  1800. %@NL@%
  1801. %@CR:MQP32302@%%@4@%The LOCAL.PAS program demonstrates local variables. It prompts you to enter%@EH@%
  1802. a number and then displays the factorial of that number. (A factorial is the
  1803. product of all the integers from 1 to a number. For instance, the factorial
  1804. of 4 is 24, the product of 1 *) 2 * 3 * 4.)%@NL@%
  1805. %@NL@%
  1806. %@AS@%     PROGRAM local_variables;%@NL@%
  1807. %@NL@%
  1808. %@AS@%     { LOCAL.PAS: Demonstrate local variables. }%@NL@%
  1809. %@NL@%
  1810. %@AS@%     VAR%@NL@%
  1811. %@AS@%         num : Byte;%@NL@%
  1812. %@NL@%
  1813. %@AS@%     PROCEDURE factor( value : Byte );%@NL@%
  1814. %@AS@%         VAR%@NL@%
  1815. %@AS@%             factorial : Real;%@NL@%
  1816. %@AS@%             count : Byte;%@NL@%
  1817. %@AS@%         BEGIN%@NL@%
  1818. %@AS@%             factorial := 1.0;%@NL@%
  1819. %@AS@%             FOR count := 1 TO value DO%@NL@%
  1820. %@AS@%             factorial := factorial * count;%@NL@%
  1821. %@AS@%             Write( 'Factorial of ', value, ' is ' );%@NL@%
  1822. %@AS@%             Writeln( factorial );%@NL@%
  1823. %@AS@%         END; { procedure factor }%@NL@%
  1824. %@NL@%
  1825. %@AS@%     BEGIN%@AE@% { main program }%@NL@%
  1826. %@AS@%         Write( 'Enter a number smaller than 34: ' );%@NL@%
  1827. %@AS@%         Readln( num );%@NL@%
  1828. %@AS@%         Factor( num );%@NL@%
  1829. %@AS@%     END.%@NL@%
  1830. %@NL@%
  1831. %@CR:MQP32303@%%@4@%Here is typical output from LOCAL.PAS:%@EH@%%@NL@%
  1832. %@NL@%
  1833.      %@AS@%Enter a number smaller than 34: 5%@AE@%%@NL@%
  1834.      %@AS@%Factorial of 5 is 1.20000000000000E+0002%@AE@%%@NL@%
  1835. %@NL@%
  1836. %@CR:MQP32304@%%@4@%The %@AS@%factor%@AE@% procedure in LOCAL.PAS appears below. It declares two local%@EH@%
  1837. variables named %@AS@%factorial%@AE@% and %@AS@%count%@AE@%:%@NL@%
  1838. %@NL@%
  1839. %@AS@%     PROCEDURE factor( value : Byte );%@NL@%
  1840. %@AS@%         VAR%@NL@%
  1841. %@AS@%             factorial : Real;%@NL@%
  1842. %@AS@%             count : Byte;%@NL@%
  1843. %@AS@%         BEGIN%@NL@%
  1844. %@AS@%             factorial := 1.0;%@NL@%
  1845. %@AS@%             FOR count := 1 TO value DO%@NL@%
  1846. %@AS@%                 factorial := factorial * count;%@NL@%
  1847. %@AS@%             Write( 'Factorial of ', value,' is ' );%@NL@%
  1848. %@AS@%             Writeln( factorial );%@NL@%
  1849. %@AS@%         END; { procedure factor }%@NL@%
  1850. %@NL@%
  1851. %@CR:MQP32305@%%@4@%Notice where local variables are declared: between the procedure's head and%@EH@%
  1852. the %@AB@%BEGIN%@AE@% keyword.%@NL@%
  1853. %@NL@%
  1854. %@CR:MQP32310@%%@4@%%@AB@%Variable Scope%@AE@%%@EH@%%@NL@%
  1855. %@NL@%
  1856. %@CR:MQP32311@%%@4@%Unlike global variables, which are declared outside any procedure and are%@EH@%
  1857. therefore visible everywhere in the program, local variables are declared
  1858. inside a procedure and are hidden from the rest of the program. If you refer
  1859. to a local variable outside the "scope," or range, where it is visible,
  1860. QuickPascal issues an error message:%@NL@%
  1861. %@NL@%
  1862.      %@AS@%Error P0032: Unknown identifier%@AE@%%@NL@%
  1863. %@NL@%
  1864. %@CR:MQP32312@%%@4@%The same message appears if you refer to a variable that has never been%@EH@%
  1865. declared. In both cases, it means the variable is not visible──and cannot be
  1866. used──in the place where the reference appears.%@NL@%
  1867. %@NL@%
  1868. %@CR:MQP32313@%%@4@%The ability to limit a variable's visibility makes it easier to write%@EH@%
  1869. reliable programs. If a variable is local, it can't be changed accidentally
  1870. by some other part of the program. Such haphazard side effects are common in
  1871. older interpreted BASIC programs, in which all variables are global.%@NL@%
  1872. %@NL@%
  1873. %@NL@%
  1874. %@CR:MQP32400@%%@3@%%@AB@%3.2.4  Passing Arguments%@AE@%%@EH@%%@NL@%
  1875. %@NL@%
  1876. %@CR:MQP32401@%%@4@%The %@AS@%Factor%@AE@% procedure in LOCAL.PAS has another local variable that hasn't%@EH@%
  1877. been mentioned yet. In addition to %@AS@%factorial%@AE@% and %@AS@%count%@AE@%, which it declares,
  1878. the procedure uses a third variable named %@AS@%value%@AE@%:%@NL@%
  1879. %@NL@%
  1880. %@AS@%     PROCEDURE Factor( value: Byte );%@NL@%
  1881. %@AS@%         VAR%@NL@%
  1882. %@AS@%             factorial : Real;%@NL@%
  1883. %@AS@%             count : Byte;%@NL@%
  1884. %@AS@%         BEGIN%@NL@%
  1885. %@AS@%             factorial := 1.0;%@NL@%
  1886. %@AS@%             FOR count := 1 TO value DO%@NL@%
  1887. %@AS@%                 factorial := factorial * count;%@NL@%
  1888. %@AS@%             Write( 'Factorial of ', value,' is ' )%@NL@%
  1889. %@AS@%             Writeln( factorial );%@NL@%
  1890. %@AS@%         END; { procedure factor }%@NL@%
  1891. %@NL@%
  1892. %@CR:MQP32402@%%@4@%The %@AS@%value%@AE@% argument, in the procedure head, is "passed" when you call the%@EH@%
  1893. %@AS@%factor%@AE@% procedure. The argument comes from a number you type in at the
  1894. keyboard. The main procedure in LOCAL.PAS stores your input in a variable
  1895. named %@AS@%num%@AE@%:%@NL@%
  1896. %@NL@%
  1897. %@AS@%     Writeln( 'Enter a number smaller than 34: ' );%@NL@%
  1898. %@AS@%     Readln( num );%@NL@%
  1899. %@NL@%
  1900. %@CR:MQP32403@%%@4@%The main program passes the value of %@AS@%num%@AE@% as an argument when it calls the%@EH@%
  1901. %@AS@%factor%@AE@% procedure:%@NL@%
  1902. %@NL@%
  1903. %@AS@%     factor( num );%@NL@%
  1904. %@NL@%
  1905. %@CR:MQP32404@%%@4@%When you list an argument in the procedure head, it becomes a local variable%@EH@%
  1906. in the procedure. Thus, the head of the %@AS@%factor%@AE@% procedure%@NL@%
  1907. %@NL@%
  1908. %@AS@%     PROCEDURE Factor( value : Byte );%@NL@%
  1909. %@NL@%
  1910. %@CR:MQP32405@%%@4@%creates a local variable named %@AS@%value%@AE@%. Inside the %@AS@%factor%@AE@% procedure, %@AS@%value%@AE@%%@EH@%
  1911. can be treated like any other local variable.%@NL@%
  1912. %@NL@%
  1913. %@CR:MQP32410@%%@4@%%@AB@%3.2.4.1  Passing by Value%@AE@%%@EH@%%@NL@%
  1914. %@NL@%
  1915. %@CR:MQP32411@%%@4@%The type of argument passing in LOCAL.PAS is called "passing by value"%@EH@%
  1916. because the procedure receives %@AI@%the value of%@AE@% the original variable, not the
  1917. variable itself. The BYVALUE.PAS program demonstrates this idea, which has
  1918. important consequences for managing variables:%@NL@%
  1919. %@NL@%
  1920. %@AS@%     PROGRAM byvalue;%@NL@%
  1921. %@NL@%
  1922. %@AS@%     { BYVALUE.PAS: Demonstrate passing by value. }%@NL@%
  1923. %@NL@%
  1924. %@AS@%     VAR%@NL@%
  1925. %@AS@%         global_var : Integer;%@NL@%
  1926. %@NL@%
  1927. %@AS@%     PROCEDURE proc( local_var : Integer );%@NL@%
  1928. %@AS@%         BEGIN%@NL@%
  1929. %@AS@%             Writeln( 'local_var = ', local_var );%@NL@%
  1930. %@AS@%             local_var := 333;%@NL@%
  1931. %@AS@%             Writeln( 'local_var = ', local_var );%@NL@%
  1932. %@AS@%         END; { procedure proc }%@NL@%
  1933. %@NL@%
  1934. %@AS@%     BEGIN { main program }%@NL@%
  1935. %@AS@%         global_var := 5;%@NL@%
  1936. %@AS@%         proc( global_var );%@NL@%
  1937. %@AS@%         Writeln( 'global_var = ', global_var );%@NL@%
  1938. %@AS@%     END.%@NL@%
  1939. %@NL@%
  1940. %@CR:MQP32412@%%@4@%Here is the output from BYVALUE.PAS:%@EH@%%@NL@%
  1941. %@NL@%
  1942.      %@AS@%local_var  = 5%@AE@%%@NL@%
  1943.      %@AS@%local_var  = 333%@AE@%%@NL@%
  1944.      %@AS@%global_var = 5%@AE@%%@NL@%
  1945. %@NL@%
  1946. %@CR:MQP32413@%%@4@%The program declares a global variable named %@AS@%global_var%@AE@% and assigns the%@EH@%
  1947. value %@AS@%5%@AE@% to %@AS@%global_var%@AE@%. The %@AS@%proc%@AE@% procedure expects you to pass one argument,
  1948. which it names %@AS@%local_var%@AE@%. The procedure prints the value of %@AS@%local_var%@AE@%
  1949. (initially, %@AS@%5%@AE@%), then changes its value to %@AS@%333%@AE@% and prints it again. After
  1950. control returns to the main program, BYVALUE.PAS prints the value of
  1951. %@AS@%global_var%@AE@%, which remains at %@AS@%5%@AE@%.%@NL@%
  1952. %@NL@%
  1953. %@CR:MQP32414@%%@4@%The %@AS@%proc%@AE@% procedure alters the value of %@AS@%local_var%@AE@%. But this change has no%@EH@%
  1954. effect on the original variable,%@AS@%global_var%@AE@%, which is not affected by
  1955. anything that happens in %@AS@%proc%@AE@%. The same is true even if both variables have
  1956. the same name (if you name both of them %@AS@%my_val%@AE@%, for instance).%@NL@%
  1957. %@NL@%
  1958. %@CR:MQP32415@%%@4@%Passing an argument by value creates a local copy of the variable in the%@EH@%
  1959. procedure. Because the procedure receives only a local copy, it can give the
  1960. argument any name, and change its value, without affecting variables
  1961. outside the procedure.%@NL@%
  1962. %@NL@%
  1963. %@CR:MQP32420@%%@4@%%@AB@%3.2.4.2  Passing by Reference%@AE@%%@EH@%%@NL@%
  1964. %@NL@%
  1965. %@CR:MQP32421@%%@4@%Sometimes, you may want a procedure to change the value of an argument. For%@EH@%
  1966. instance, say you need a procedure that swaps two variables. If you pass the
  1967. variables by value, their values change inside the swap procedure, but
  1968. remain unchanged in the rest of the program. You need a way to tell the
  1969. procedure to change the original variables, not its local copies of them.%@NL@%
  1970. %@NL@%
  1971. %@CR:MQP32422@%%@4@%Pascal offers a second passing method, called "passing by reference," for%@EH@%
  1972. just such cases. The BYREF.PAS program demonstrates this method:%@NL@%
  1973. %@NL@%
  1974. %@AS@%     PROGRAM byref;%@NL@%
  1975. %@NL@%
  1976. %@AS@%     { BYREF.PAS: Demonstrate passing by reference. }%@NL@%
  1977. %@NL@%
  1978. %@AS@%     VAR%@NL@%
  1979. %@AS@%         var1, var2 : Integer;%@NL@%
  1980. %@NL@%
  1981. %@AS@%     PROCEDURE swap_vars(VAR var1 : Integer; VAR var2 : Integer);%@NL@%
  1982. %@AS@%         VAR%@NL@%
  1983. %@AS@%             temp : Integer;%@NL@%
  1984. %@AS@%         BEGIN%@NL@%
  1985. %@AS@%             temp := var1;%@NL@%
  1986. %@AS@%             var1 := var2;%@NL@%
  1987. %@AS@%             var2 := temp;%@NL@%
  1988. %@AS@%         END; { procedure swap_vars }%@NL@%
  1989. %@NL@%
  1990. %@AS@%     BEGIN%@NL@%
  1991. %@AS@%         var1 := 55;%@NL@%
  1992. %@AS@%         var2 := 99;%@NL@%
  1993. %@AS@%         Writeln( 'var1 = ', var1, '  var2 = ', var2 );%@NL@%
  1994. %@AS@%         swap_vars( var1, var2 );%@NL@%
  1995. %@AS@%         Writeln( 'var1 = ', var1, '  var2 = ', var2 );%@NL@%
  1996. %@AS@%     END.%@NL@%
  1997. %@NL@%
  1998. %@CR:MQP32423@%%@4@%Here is the output from BYREF.PAS:%@EH@%%@NL@%
  1999. %@NL@%
  2000.      %@AS@%var1 = 55  var2 = 99%@AE@%%@NL@%
  2001.      %@AS@%var1 = 99  var2 = 55%@AE@%%@NL@%
  2002. %@NL@%
  2003. %@CR:MQP32424@%%@4@%The program declares two global variables named %@AS@%var1%@AE@% and %@AS@%var2%@AE@%, assigning%@EH@%
  2004. them the values %@AS@%55%@AE@% and %@AS@%99%@AE@%, respectively. It prints their values, calls the
  2005. %@AS@%swap_vars%@AE@% procedure, then prints their values again. The output proves that
  2006. %@AS@%swap_vars%@AE@% changes the original variables.%@NL@%
  2007. %@NL@%
  2008. %@CR:MQP32425@%%@4@%The important difference between this program and the previous example%@EH@%
  2009. appears in the %@AS@%swap_vars%@AE@% procedure head:%@NL@%
  2010. %@NL@%
  2011. %@AS@%     PROCEDURE swap_vars(VAR var1 : Integer; VAR var2: Integer);%@NL@%
  2012. %@NL@%
  2013. %@CR:MQP32426@%%@4@%Notice the %@AB@%VAR%@AE@% keyword in front of each name in the argument list. It tells%@EH@%
  2014. the %@AS@%swap_vars%@AE@% procedure to treat the argument as a variable (located
  2015. elsewhere) rather than as a value. Instead of creating a local copy of the
  2016. passed value, the procedure acts upon the variable itself.%@NL@%
  2017. %@NL@%
  2018. %@CR:MQP32427@%%@4@%The %@AS@%swap_vars%@AE@% procedure head happens to use the same names for these%@EH@%
  2019. arguments (%@AS@%var1%@AE@% and %@AS@%var2%@AE@%) in its argument list. But the result would be the
  2020. same if %@AS@%swap_vars%@AE@% used different names. Because the arguments are declared
  2021. with %@AB@%VAR%@AE@%, their names in %@AS@%swap_vars%@AE@% are synonyms for the original variables.%@NL@%
  2022. %@NL@%
  2023. %@CR:MQP32428@%%@4@%You can underscore this point by making a simple change to the previous%@EH@%
  2024. example, BYVALUE.PAS. Load the program and add %@AB@%VAR%@AE@% to the %@AS@%proc%@AE@% procedure
  2025. head:%@NL@%
  2026. %@NL@%
  2027. %@AS@%     PROCEDURE proc( VAR local_var : Integer );%@NL@%
  2028. %@NL@%
  2029. %@CR:MQP32429@%%@4@%After you make this change, the %@AS@%proc%@AE@% procedure changes the global variable%@EH@%
  2030. %@AS@%global_var%@AE@%, giving this output:%@NL@%
  2031. %@NL@%
  2032.      %@AS@%local_var = 5%@AE@%%@NL@%
  2033.      %@AS@%local_var = 333%@AE@%%@NL@%
  2034.      %@AS@%global_var = 333%@AE@%%@NL@%
  2035. %@NL@%
  2036. %@CR:MQP3242A@%%@4@%In the original BYVALUE.PAS program, the global variable %@AS@%global_var%@AE@%%@EH@%
  2037. retained the value %@AS@%5%@AE@% even though %@AS@%proc%@AE@% changed the value of %@AS@%local_var%@AE@%.
  2038. Passing %@AS@%global_var%@AE@% by reference gives %@AS@%proc%@AE@% the ability to modify %@AS@%global_var%@AE@%.%@NL@%
  2039. %@NL@%
  2040. %@CR:MQP3242B@%%@4@%When you pass an argument by reference, you must pass a variable, not a%@EH@%
  2041. value. That is, the argument must be a variable name,%@NL@%
  2042. %@NL@%
  2043. %@AS@%     swap_vars( global_1, global_2 ); { correct }%@NL@%
  2044. %@NL@%
  2045. %@CR:MQP3242C@%%@4@%not a constant,%@EH@%%@NL@%
  2046. %@NL@%
  2047. %@AS@%     swap_vars( 55, 99 ); { error! }%@NL@%
  2048. %@NL@%
  2049. %@CR:MQP3242D@%%@4@%or an expression:%@EH@%%@NL@%
  2050. %@NL@%
  2051. %@AS@%     swap_vars( 5 * 11, 93 + 6 ); { error! }%@NL@%
  2052. %@NL@%
  2053. %@CR:MQP3242E@%%@4@%It's best to pass arguments by reference only when you want the procedure to%@EH@%
  2054. change the argument. Unnecessary passing by reference creates the same
  2055. problems as the overuse of global variables.%@NL@%
  2056. %@NL@%
  2057. %@NL@%
  2058. %@CR:MQP33000@%%@2@%%@AB@%3.3  Functions%@AE@%%@EH@%%@NL@%
  2059. %@NL@%
  2060. %@CR:MQP33001@%%@4@%A function is a procedure that returns a value. Like most languages, Pascal%@EH@%
  2061. has many standard functions, such as %@AB@%Sqrt%@AE@%, which returns a square root.%@NL@%
  2062. %@NL@%
  2063. %@CR:MQP33002@%%@4@%You can think of a function as a special kind of procedure. All of the%@EH@%
  2064. concepts explained in Section 3.2%@BO:   145ab@%, "Procedures," also apply to functions.
  2065. Rather than restate everything that procedures and functions share in
  2066. common, this section explains the features that make functions different
  2067. from procedures.%@NL@%
  2068. %@NL@%
  2069. %@CR:MQP33003@%%@4@%The FUNCT.PAS program contains a simple function:%@EH@%%@NL@%
  2070. %@NL@%
  2071. %@AS@%     PROGRAM FUNCT;%@NL@%
  2072. %@NL@%
  2073. %@AS@%     { FUNCT.PAS: Demonstrate function basics. }%@NL@%
  2074. %@NL@%
  2075. %@AS@%     VAR%@NL@%
  2076. %@AS@%         num, expo, powr : Real;%@NL@%
  2077. %@NL@%
  2078. %@AS@%     FUNCTION power( base, exponent : Real ) : Real;%@NL@%
  2079. %@NL@%
  2080. %@AS@%         BEGIN%@NL@%
  2081. %@AS@%             IF (base > 0) THEN%@NL@%
  2082. %@AS@%                 Power := Exp( exponent * Ln( base ) )%@NL@%
  2083. %@AS@%             ELSE%@NL@%
  2084. %@AS@%                 Power := -1.0;%@NL@%
  2085. %@AS@%     END;%@NL@%
  2086. %@NL@%
  2087. %@AS@%     BEGIN%@NL@%
  2088. %@AS@%         Write( 'Enter a number: ' );%@NL@%
  2089. %@AS@%         Readln( num );%@NL@%
  2090. %@AS@%         Write( 'Enter an exponent: ' );%@NL@%
  2091. %@AS@%         Readln( expo );%@NL@%
  2092. %@AS@%         powr := Power( num, expo );%@NL@%
  2093. %@AS@%         Writeln( num, ' ^ ', expo, ' = ', powr );%@NL@%
  2094. %@AS@%     END.%@NL@%
  2095. %@NL@%
  2096. %@CR:MQP33004@%%@4@%The FUNCT.PAS program prompts you to enter two numbers, a base and an%@EH@%
  2097. exponent. Then it calls the %@AS@%power%@AE@% function to raise the base to the
  2098. exponent. Typical output appears below:%@NL@%
  2099. %@NL@%
  2100.     %@AS@%Enter a number: 2%@AE@%%@NL@%
  2101.     %@AS@%Enter an exponent: 8%@AE@%%@NL@%
  2102. %@NL@%
  2103.     %@AS@%2.00000000000000E+0000 ^ 8.00000000000000E+0000 = 2.56000000000000E+0002%@AE@%%@NL@%
  2104. %@NL@%
  2105. %@CR:MQP33005@%%@4@%FUNCT.PAS raises %@AS@%2%@AE@% to the eighth power, giving a result of %@AS@%256%@AE@%.%@EH@%%@NL@%
  2106. %@NL@%
  2107. %@NL@%
  2108. %@CR:MQP33100@%%@3@%%@AB@%3.3.1  Calling Functions%@AE@%%@EH@%%@NL@%
  2109. %@NL@%
  2110. %@CR:MQP33101@%%@4@%Function calls are identical to procedure calls. You state the function's%@EH@%
  2111. name, listing in parentheses any arguments that the function requires. The
  2112. only difference is in where the call can appear. A procedure call can stand
  2113. alone as a statement, but a function call, because it returns a value, must
  2114. appear in an assignment or expression.%@NL@%
  2115. %@NL@%
  2116. %@CR:MQP33102@%%@4@%The following statement from FUNCT.PAS calls the %@AS@%power%@AE@% function, assigning%@EH@%
  2117. its return value to the variable %@AS@%powr%@AE@%:%@NL@%
  2118. %@NL@%
  2119. %@AS@%     powr := power( num, expo );%@NL@%
  2120. %@NL@%
  2121. %@CR:MQP33103@%%@4@%Notice the similarity to a procedure call. The %@AS@%power%@AE@% function takes two%@EH@%
  2122. arguments, which are listed in parentheses after the function name.%@NL@%
  2123. %@NL@%
  2124. %@CR:MQP33104@%%@4@%The previous example uses the function call in an assignment. Function calls%@EH@%
  2125. can also appear in expressions:%@NL@%
  2126. %@NL@%
  2127. %@AS@%     dazzle := 12 * surprise( 730, 88 ) / 2;%@NL@%
  2128. %@NL@%
  2129. %@CR:MQP33105@%%@4@%Here, the %@AS@%surprise%@AE@% function appears as part of the expression to the right%@EH@%
  2130. of the assignment symbol.%@NL@%
  2131. %@NL@%
  2132. %@NL@%
  2133. %@CR:MQP33200@%%@3@%%@AB@%3.3.2  Returning Values from Functions%@AE@%%@EH@%%@NL@%
  2134. %@NL@%
  2135. %@CR:MQP33201@%%@4@%A function returns a value by assigning the value to its own name. In the%@EH@%
  2136. %@AS@%power%@AE@% function, for instance, this statement causes the function to return
  2137. the value %@AS@%-1.0%@AE@%:%@NL@%
  2138. %@NL@%
  2139. %@AS@%     power := -1.0;%@NL@%
  2140. %@NL@%
  2141. %@CR:MQP33202@%%@4@%The return value must match the type declared in the function head. Since%@EH@%
  2142. the %@AS@%power%@AE@% function returns a value of type %@AB@%Real%@AE@%, the above statement uses
  2143. the value %@AS@%-1.0%@AE@% (with a decimal point).%@NL@%
  2144. %@NL@%
  2145. %@NL@%
  2146. %@CR:MQP33300@%%@3@%%@AB@%3.3.3  Declaring Functions%@AE@%%@EH@%%@NL@%
  2147. %@NL@%
  2148. %@CR:MQP33301@%%@4@%Function declarations are identical to procedure declarations except that%@EH@%
  2149. you substitute %@AB@%FUNCTION%@AE@% for %@AB@%PROCEDURE%@AE@% and declare the function's return type
  2150. after the argument list. Below is the function head from FUNCT.PAS:%@NL@%
  2151. %@NL@%
  2152. %@AS@%     FUNCTION power( base, exponent : Real ) : Real;%@NL@%
  2153. %@NL@%
  2154. %@CR:MQP33302@%%@4@%Following the argument list, separated by a colon, is the identifier %@AB@%Real%@AE@%,%@EH@%
  2155. which indicates that the %@AS@%power%@AE@% function returns a value of type %@AB@%Real.%@AE@% If
  2156. %@AS@%power%@AE@% returned an integer value, you would replace the %@AB@%Real%@AE@% with%@AB@%Integer%@AE@%, and
  2157. so on.%@NL@%
  2158. %@NL@%
  2159. %@CR:MQP33303@%%@4@%Again, except for the differences noted in this section, functions are%@EH@%
  2160. identical to procedures. They can handle arguments and local variables
  2161. exactly as described in Section 3.2%@BO:   145ab@%, "Procedures."%@NL@%
  2162. %@NL@%
  2163. %@NL@%
  2164. %@CR:MQP34000@%%@2@%%@AB@%3.4  Nested Procedures%@AE@%%@EH@%%@NL@%
  2165. %@NL@%
  2166. %@CR:MQP34001@%%@4@%In addition to local variables, a procedure can declare other procedures.%@EH@%
  2167. You can "hide" one procedure declaration inside another. Like a local
  2168. variable, the hidden procedure is visible only in the procedure where it is
  2169. declared. This feature, which is unique to Pascal, allows you to limit the
  2170. visibility of a procedure (and that procedure's local variables) in the same
  2171. way you limit the visibility of local variables. Nesting applies to both
  2172. procedures and functions.%@NL@%
  2173. %@NL@%
  2174. %@CR:MQP34002@%%@4@%The HIDEPROC.PAS program demonstrates procedure nesting:%@EH@%%@NL@%
  2175. %@NL@%
  2176. %@AS@%     PROGRAM hideproc;%@NL@%
  2177. %@NL@%
  2178. %@AS@%     { HIDEPROC.PAS: Demonstrate procedure nesting. }%@NL@%
  2179. %@NL@%
  2180. %@AS@%     VAR%@NL@%
  2181. %@AS@%         globl : Integer;%@NL@%
  2182. %@NL@%
  2183. %@AS@%     PROCEDURE proc( p_parm : Integer );%@NL@%
  2184. %@NL@%
  2185. %@AS@%         VAR%@NL@%
  2186. %@AS@%             p_locl: Integer;%@NL@%
  2187. %@NL@%
  2188. %@AS@%         PROCEDURE hidden( hidn_parm : Integer );%@NL@%
  2189. %@NL@%
  2190. %@AS@%              VAR%@NL@%
  2191. %@AS@%                  hidn_locl: Integer;%@NL@%
  2192. %@NL@%
  2193. %@AS@%              BEGIN%@NL@%
  2194. %@AS@%                  Writeln( 'hidden can see: globl, p_parm, '+%@NL@%
  2195. %@AS@%                           'p_locl, hidn_parm, hidn_locl' );%@NL@%
  2196. %@AS@%              END; { hidden procedure }%@NL@%
  2197. %@NL@%
  2198. %@AS@%          BEGIN%@NL@%
  2199. %@AS@%              Writeln( 'Proc can see: globl, p_parm, p_locl' );%@NL@%
  2200. %@AS@%              hidden( 44 ); { Pass argument to hidden }%@NL@%
  2201. %@AS@%          END; { proc }%@NL@%
  2202. %@NL@%
  2203. %@AS@%     BEGIN { main program }%@NL@%
  2204. %@AS@%         Writeln( 'Main program can see: globl' );%@NL@%
  2205. %@AS@%         proc( 99 ); { Pass argument to proc  }%@NL@%
  2206. %@AS@%     END.%@NL@%
  2207. %@NL@%
  2208. %@CR:MQP34003@%%@4@%HIDEPROC.PAS produces this output:%@EH@%%@NL@%
  2209. %@NL@%
  2210.      %@AS@%Main program can see: globl%@AE@%%@NL@%
  2211.      %@AS@%Proc can see: globl, p_parm, p_locl%@AE@%%@NL@%
  2212.      %@AS@%Hidden can see: globl, p_parm, p_locl, hidn_parm, hidn_locl%@AE@%%@NL@%
  2213. %@NL@%
  2214. %@CR:MQP34004@%%@4@%The program has two procedures named %@AS@%proc%@AE@% and %@AS@%hidden%@AE@%. Because the %@AS@%hidden%@AE@%%@EH@%
  2215. procedure declaration appears in the %@AS@%proc%@AE@% declaration, %@AS@%hidden%@AE@% is visible
  2216. only inside %@AS@%proc%@AE@%.%@NL@%
  2217. %@NL@%
  2218. %@CR:MQP34005@%%@4@%The program's output shows how nesting affects variable visibility. At the%@EH@%
  2219. deepest level in HIDEPROC.PAS──inside %@AS@%hidden%@AE@%──all of the program's variables
  2220. are visible. The %@AS@%hidden%@AE@% procedure can see its own local variables, plus the
  2221. variables local to the %@AS@%proc%@AE@% procedure, plus all of the global variables. At
  2222. the next level──inside %@AS@%proc%@AE@%──visibility is more restricted. The %@AS@%proc%@AE@%
  2223. procedure can see its own local variables and the global variables, but not
  2224. the variables local to %@AS@%hidden%@AE@%. The main program has the most restricted
  2225. visibility. It can see only global variables.%@NL@%
  2226. %@NL@%
  2227. %@CR:MQP34006@%%@4@%Nesting also affects the visibility of a procedure itself. The %@AS@%hidden%@AE@%%@EH@%
  2228. procedure can be called only from the %@AS@%proc%@AE@% procedure, where it is declared.
  2229. If you call %@AS@%hidden%@AE@% from the main program, QuickPascal issues an error, just
  2230. as it would if the main program referred to one of the local variables in
  2231. %@AS@%proc%@AE@%.%@NL@%
  2232. %@NL@%
  2233. %@NL@%
  2234. %@CR:MQP35000@%%@2@%%@AB@%3.5  Recursion%@AE@%%@EH@%%@NL@%
  2235. %@NL@%
  2236. %@CR:MQP35001@%%@4@%"Recursion" is the ability of a procedure or function to call itself. The%@EH@%
  2237. primary use of recursion is in solving certain mathematical problems that
  2238. require repetitive operations.%@NL@%
  2239. %@NL@%
  2240. %@CR:MQP35002@%%@4@%The RECURSE.PAS program demonstrates recursion. It is a revision of the%@EH@%
  2241. LOCAL.PAS program that demonstrated local variables. Like its predecessor,
  2242. RECURSE.PAS computes a factorial. But instead of a loop, it uses a recursive
  2243. function named %@AS@%factor%@AE@%:%@NL@%
  2244. %@NL@%
  2245. %@AS@%     PROGRAM recurse;%@NL@%
  2246. %@NL@%
  2247. %@AS@%     { RECURSE.PAS: Demonstrate recursion. }%@NL@%
  2248. %@NL@%
  2249. %@AS@%     USES%@NL@%
  2250. %@AS@%         Crt;%@NL@%
  2251. %@NL@%
  2252. %@AS@%     VAR%@NL@%
  2253. %@AS@%         num : Byte;%@NL@%
  2254. %@AS@%         result : Real;%@NL@%
  2255. %@NL@%
  2256. %@AS@%     FUNCTION factor( value : Byte ) : Real;%@NL@%
  2257. %@AS@%         BEGIN%@NL@%
  2258. %@AS@%             IF (value > 1) THEN%@NL@%
  2259. %@AS@%                 factor := value * factor( value - 1 )%@NL@%
  2260. %@AS@%             ELSE%@NL@%
  2261. %@AS@%                 factor := 1.0;%@NL@%
  2262. %@AS@%         END; { factor }%@NL@%
  2263. %@NL@%
  2264. %@AS@%     BEGIN%@NL@%
  2265. %@AS@%         Write( 'Enter a number smaller than 34: ' );%@NL@%
  2266. %@AS@%         Readln( num );%@NL@%
  2267. %@AS@%         result := factor( num );%@NL@%
  2268. %@AS@%         Write( 'Factorial of ', num, ' is ' );%@NL@%
  2269. %@AS@%         Writeln( result );%@NL@%
  2270. %@AS@%     END.%@NL@%
  2271. %@NL@%
  2272. %@CR:MQP35003@%%@4@%The output from RECURSE.PAS and LOCAL.PAS is identical:%@EH@%%@NL@%
  2273. %@NL@%
  2274.      %@AS@%Enter a number smaller than 34: 5%@AE@%%@NL@%
  2275.      %@AS@%Factorial of 5 is 1.20000000000000E+0002%@AE@%%@NL@%
  2276. %@NL@%
  2277. %@CR:MQP35004@%%@4@%The only difference between normal functions and recursive functions is that%@EH@%
  2278. a recursive function contains a statement that calls itself. Here is the
  2279. recursive statement in RECURSE.PAS:%@NL@%
  2280. %@NL@%
  2281. %@AS@%     Factor := value * factor( value - 1 )%@NL@%
  2282. %@NL@%
  2283. %@CR:MQP35005@%%@4@%The expression on the right side of the assignment operator contains a call%@EH@%
  2284. to the %@AS@%factor%@AE@% function. The first call to %@AS@%factor%@AE@% can trigger a second call,
  2285. which can trigger a third call, and so on.%@NL@%
  2286. %@NL@%
  2287. %@CR:MQP35006@%%@4@%The %@AB@%IF%@AE@% statement at the beginning of the %@AS@%factor%@AE@% function prevents the%@EH@%
  2288. function from calling itself endlessly. Every recursive procedure and
  2289. function must include such an exit mechanism.%@NL@%
  2290. %@NL@%
  2291. %@CR:MQP35007@%%@4@%Most recursive procedures and functions exploit the fact that each%@EH@%
  2292. invocation of a procedure or function creates a new set of local variables.
  2293. Recursion can be very efficient in terms of programming time. You may be
  2294. able to solve a complex math problem with only a few lines of code. But
  2295. deeply recursive procedures can also be memory inefficient, consuming huge
  2296. amounts of memory to store local variables.%@NL@%
  2297. %@NL@%
  2298. %@NL@%
  2299. %@CR:MQP40000@%%@1@%%@AB@%Chapter 4  Controlling Program Flow%@AE@%%@EH@%%@NL@%
  2300. ───────────────────────────────────────────────────────────────────────────%@NL@%
  2301. %@NL@%
  2302. %@CR:MQP40001@%%@4@%Like other high-level languages, Pascal offers a wide variety of ways to%@EH@%
  2303. control a program's flow of execution. This chapter discusses looping
  2304. statements, which perform repetitive actions, and decision-making
  2305. statements, which transfer control based on logical tests. Before examining
  2306. those statements in detail, this chapter briefly summarizes the operators
  2307. used in logical tests.%@NL@%
  2308. %@NL@%
  2309. %@NL@%
  2310. %@CR:MQP41000@%%@2@%%@AB@%4.1  Relational and Boolean Operators%@AE@%%@EH@%%@NL@%
  2311. %@NL@%
  2312. %@CR:MQP41001@%%@4@%All of the looping and branching statements in Pascal depend on the outcome%@EH@%
  2313. of a Boolean (true or false) test. Such tests use relational and Boolean
  2314. operators, which look familiar to anyone who knows BASIC or C.%@NL@%
  2315. %@NL@%
  2316. %@CR:MQP41002@%%@4@%Even if you have never seen a line of Pascal code, you may be able to guess%@EH@%
  2317. that the statement%@NL@%
  2318. %@NL@%
  2319. %@AS@%     IF my_val = 20 THEN Writeln( 'my_val equals 20' );%@NL@%
  2320. %@NL@%
  2321. %@CR:MQP41003@%%@4@%prints the message%@EH@%%@NL@%
  2322. %@NL@%
  2323.      %@AS@%my_val equals 20%@AE@%%@NL@%
  2324. %@NL@%
  2325. %@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@%
  2326. you'll read later in this chapter, works very much like %@AB@%IF%@AE@% in BASIC and C.)%@NL@%
  2327. %@NL@%
  2328. %@CR:MQP41005@%%@4@%The example uses the equality operator (%@AB@%=%@AE@%) to compare the variable %@AS@%my_val%@AE@% to%@EH@%
  2329. the constant %@AS@%20%@AE@%. It produces a %@AB@%True%@AE@% result when %@AS@%my_val%@AE@% equals %@AS@%20%@AE@%, and a
  2330. %@AB@%False%@AE@% result in every other case.%@NL@%
  2331. %@NL@%
  2332. ───────────────────────────────────────────────────────────────────────────%@NL@%
  2333. %@AI@%NOTE%@AE@%%@NL@%
  2334.    %@AB@%True%@AE@% and %@AB@%False%@AE@% are symbolic values in Pascal. Although they are%@NL@%
  2335.    represented by actual numbers internally, you don't need to worry about%@NL@%
  2336.    what those numbers are.%@NL@%
  2337. ───────────────────────────────────────────────────────────────────────────%@NL@%
  2338. %@NL@%
  2339. %@CR:MQP41006@%%@4@%Relational operators, including the equality operator, compare two values%@EH@%
  2340. and produce a %@AB@%True%@AE@% or %@AB@%False%@AE@% result. Table 4.1 lists all of the Pascal
  2341. relational operators.%@NL@%
  2342. %@NL@%
  2343. %@CR:MQP4T100@%%@4@%%@AB@%Table 4.1  Relational Operators%@AE@%%@EH@%%@NL@%
  2344. %@NL@%
  2345.       %@AB@%Operator            Description%@AE@%%@NL@%
  2346. %@NL@%
  2347.       %@AB@%=%@AE@%                   Equal%@NL@%
  2348. %@NL@%
  2349.       %@AB@%<>%@AE@%                  Not equal%@NL@%
  2350. %@NL@%
  2351.       %@AB@%<%@AE@%                   Less than%@NL@%
  2352. %@NL@%
  2353.       %@AB@%>%@AE@%                   Greater than%@NL@%
  2354. %@NL@%
  2355.       %@AB@%<=%@AE@%                  Less than or equal%@NL@%
  2356. %@NL@%
  2357.       %@AB@%>=%@AE@%                  Greater than or equal%@NL@%
  2358. %@NL@%
  2359. %@NL@%
  2360. %@CR:MQP41007@%%@4@%A second group of operators allows you to perform Boolean logical%@EH@%
  2361. operations. They are listed in Table 4.2.%@NL@%
  2362. %@NL@%
  2363. %@CR:MQP4T200@%%@4@%%@AB@%Table 4.2  Boolean Operators%@AE@%%@EH@%%@NL@%
  2364. %@NL@%
  2365.       %@AB@%Operator            Description%@AE@%%@NL@%
  2366. %@NL@%
  2367.       %@AB@%NOT%@AE@%                 Negation%@NL@%
  2368. %@NL@%
  2369.       %@AB@%AND%@AE@%                 Logical %@AB@%AND%@AE@%%@NL@%
  2370. %@NL@%
  2371.       %@AB@%OR%@AE@%                  Logical %@AB@%OR%@AE@%%@NL@%
  2372. %@NL@%
  2373.       %@AB@%XOR%@AE@%                 Exclusive %@AB@%OR%@AE@%%@NL@%
  2374. %@NL@%
  2375. %@NL@%
  2376. %@CR:MQP41008@%%@4@%Boolean operators (except for %@AB@%NOT%@AE@%) can act on one or two values, allowing%@EH@%
  2377. more complex logical tests. For instance, the statement%@NL@%
  2378. %@NL@%
  2379. %@AS@%     IF ((my_val > 3) AND (my_val < 20)) THEN Writeln( 'Wahoo!');%@NL@%
  2380. %@NL@%
  2381. %@CR:MQP41009@%%@4@%tests two conditions instead of one. It prints the message%@EH@%%@NL@%
  2382. %@NL@%
  2383. %@AS@%     Wahoo!%@NL@%
  2384. %@NL@%
  2385. %@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@%
  2386. %@NL@%
  2387. %@CR:MQP4100B@%%@4@%Pascal provides many more operators, but these are the important ones for%@EH@%
  2388. controlling program flow. The QP Advisor contains information about all of
  2389. the QuickPascal operators.%@NL@%
  2390. %@NL@%
  2391. %@NL@%
  2392. %@CR:MQP42000@%%@2@%%@AB@%4.2  Looping Statements%@AE@%%@EH@%%@NL@%
  2393. %@NL@%
  2394. %@CR:MQP42001@%%@4@%A loop performs one of the most basic computer operations: repeating an%@EH@%
  2395. action. This section discusses the Pascal looping statements: %@AB@%WHILE%@AE@%, %@AB@%REPEAT%@AE@%,
  2396. and %@AB@%FOR%@AE@%.%@NL@%
  2397. %@NL@%
  2398. %@NL@%
  2399. %@CR:MQP42100@%%@3@%%@AB@%4.2.1  WHILE Loops%@AE@%%@EH@%%@NL@%
  2400. %@NL@%
  2401. %@CR:MQP42101@%%@4@%A %@AB@%WHILE%@AE@% loop is the simplest kind of loop. It repeats 0 or more times, as%@EH@%
  2402. long as a given condition remains true. The QWHILE.PAS program contains a
  2403. simple %@AB@%WHILE%@AE@% loop.%@NL@%
  2404. %@NL@%
  2405. %@AS@%     PROGRAM qwhile;%@NL@%
  2406. %@NL@%
  2407. %@AS@%     { QWHILE.PAS: Demonstrate WHILE loop. }%@NL@%
  2408. %@NL@%
  2409. %@AS@%     VAR%@NL@%
  2410. %@AS@%         count : Integer;%@NL@%
  2411. %@NL@%
  2412. %@AS@%     BEGIN%@NL@%
  2413. %@NL@%
  2414. %@AS@%         count := 0;%@NL@%
  2415. %@NL@%
  2416. %@AS@%         WHILE count < 10 DO%@NL@%
  2417. %@AS@%             BEGIN%@NL@%
  2418. %@AS@%             Writeln( 'count = ', count );%@NL@%
  2419. %@AS@%             count := count + 2;%@NL@%
  2420. %@AS@%             END;%@NL@%
  2421. %@NL@%
  2422. %@AS@%     END.%@NL@%
  2423. %@NL@%
  2424. %@CR:MQP42102@%%@4@%Here is the output from QWHILE.PAS:%@EH@%%@NL@%
  2425. %@NL@%
  2426.      %@AS@%count = 0%@AE@%%@NL@%
  2427.      %@AS@%count = 2%@AE@%%@NL@%
  2428.      %@AS@%count = 4%@AE@%%@NL@%
  2429.      %@AS@%count = 6%@AE@%%@NL@%
  2430.      %@AS@%count = 8%@AE@%%@NL@%
  2431. %@NL@%
  2432. %@CR:MQP42103@%%@4@%A %@AB@%WHILE%@AE@% loop begins with the %@AB@%WHILE%@AE@% keyword followed by a condition. The loop%@EH@%
  2433. repeats as long as the condition remains true. In QWHILE.PAS, the condition
  2434. is%@NL@%
  2435. %@NL@%
  2436. %@AS@%     count < 10%@NL@%
  2437. %@NL@%
  2438. %@CR:MQP42104@%%@4@%so the loop continues as long as the value of the variable %@AS@%count%@AE@% is less%@EH@%
  2439. than %@AS@%10%@AE@%. After the condition is the %@AB@%DO%@AE@% keyword followed by a "loop body,"
  2440. which can be a single statement or a statement block. In QWHILE.PAS, the
  2441. loop body is a statement block:%@NL@%
  2442. %@NL@%
  2443. %@AS@%     BEGIN%@NL@%
  2444. %@AS@%         Writeln( 'count = ', count );%@NL@%
  2445. %@AS@%         count := count + 2;%@NL@%
  2446. %@AS@%     END;%@NL@%
  2447. %@NL@%
  2448. %@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@%
  2449. loop is only one statement. This convention prevents any confusion about
  2450. where the loop body ends.%@NL@%
  2451. %@NL@%
  2452. %@CR:MQP42106@%%@4@%It's important to know that a %@AB@%WHILE%@AE@% loop tests its condition %@AI@%before%@AE@% it%@EH@%
  2453. executes the loop body. Unlike some other kinds of loops, it's possible for
  2454. a %@AB@%WHILE%@AE@% loop to skip everything in its loop body. If the test condition is
  2455. false when a %@AB@%WHILE%@AE@% loop begins, the loop body does not execute at all. For
  2456. instance, if %@AS@%count%@AE@% has the value %@AS@%10%@AE@% when the above loop begins, QWHILE.PAS
  2457. doesn't print anything.%@NL@%
  2458. %@NL@%
  2459. %@NL@%
  2460. %@CR:MQP42200@%%@3@%%@AB@%4.2.2  REPEAT Loops%@AE@%%@EH@%%@NL@%
  2461. %@NL@%
  2462. %@CR:MQP42201@%%@4@%A %@AB@%REPEAT%@AE@% loop is an inverted %@AB@%WHILE%@AE@% loop. It tests the condition %@AI@%after%@AE@% it%@EH@%
  2463. executes the loop body, and the loop repeats %@AI@%until%@AE@% the test condition
  2464. becomes true.%@NL@%
  2465. %@NL@%
  2466. %@CR:MQP42202@%%@4@%The QREPEAT.PAS program performs the same task as QWHILE.PAS, but it uses a%@EH@%
  2467. %@AB@%REPEAT%@AE@% loop instead of a %@AB@%WHILE%@AE@% loop.%@NL@%
  2468. %@NL@%
  2469. %@AS@%     PROGRAM qrepeat;%@NL@%
  2470. %@NL@%
  2471. %@AS@%     { QREPEAT.PAS: Demonstrate REPEAT loop. }%@NL@%
  2472. %@NL@%
  2473. %@AS@%     VAR%@NL@%
  2474. %@AS@%         count : Integer;%@NL@%
  2475. %@NL@%
  2476. %@AS@%     BEGIN%@NL@%
  2477. %@NL@%
  2478. %@AS@%         count := 0;%@NL@%
  2479. %@NL@%
  2480. %@AS@%         REPEAT%@NL@%
  2481. %@AS@%             Writeln( 'count = ', count );%@NL@%
  2482. %@AS@%             count := count + 2;%@NL@%
  2483. %@AS@%         UNTIL ( count > 8 );%@NL@%
  2484. %@NL@%
  2485. %@AS@%     END.%@NL@%
  2486. %@NL@%
  2487. %@CR:MQP42203@%%@4@%The output from QREPEAT.PAS and QWHILE.PAS is identical:%@EH@%%@NL@%
  2488. %@NL@%
  2489.      %@AS@%count = 0%@AE@%%@NL@%
  2490.      %@AS@%count = 2%@AE@%%@NL@%
  2491.      %@AS@%count = 4%@AE@%%@NL@%
  2492.      %@AS@%count = 6%@AE@%%@NL@%
  2493.      %@AS@%count = 8%@AE@%%@NL@%
  2494. %@NL@%
  2495. %@CR:MQP42204@%%@4@%The %@AB@%REPEAT%@AE@% loop in QREPEAT.PAS contains the same loop body as the %@AB@%WHILE%@AE@% loop%@EH@%
  2496. in QWHILE.PAS:%@NL@%
  2497. %@NL@%
  2498. %@AS@%     REPEAT%@NL@%
  2499. %@AS@%         Writeln( 'count = ', count );%@NL@%
  2500. %@AS@%         count := count + 2;%@NL@%
  2501. %@AS@%     UNTIL ( count > 8 );%@NL@%
  2502. %@NL@%
  2503. %@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@%
  2504. %@AB@%END%@AE@% keywords (although adding them does no harm). Since the loop body is
  2505. already enclosed between two keywords (%@AB@%REPEAT%@AE@% and %@AB@%UNTIL%@AE@%), there can be no
  2506. confusion about where the block begins and ends.%@NL@%
  2507. %@NL@%
  2508. %@CR:MQP42206@%%@4@%Remember that a %@AB@%REPEAT%@AE@% loop always executes the loop body at least once. If%@EH@%
  2509. %@AS@%count%@AE@% has the value %@AS@%10%@AE@% when the loop begins, QREPEAT.PAS prints%@NL@%
  2510. %@NL@%
  2511. %@AS@%     count = 10%@NL@%
  2512. %@NL@%
  2513. %@CR:MQP42207@%%@4@%even though %@AS@%10%@AE@% is clearly greater than %@AS@%8%@AE@%, the cutoff value in the test%@EH@%
  2514. condition. The value of %@AS@%count%@AE@% is not tested until after the loop body has
  2515. executed.%@NL@%
  2516. %@NL@%
  2517. %@CR:MQP42208@%%@4@%Notice that %@AB@%WHILE%@AE@% and %@AB@%REPEAT%@AE@% loops use opposite logical tests. A %@AB@%WHILE%@AE@% loop%@EH@%
  2518. continues %@AI@%as long as%@AE@% the test condition is true, but a %@AB@%REPEAT%@AE@% loop continues
  2519. %@AI@%until%@AE@% the test condition becomes true (or, to put it differently, as long as
  2520. the test condition is false). To illustrate, the %@AB@%WHILE%@AE@% loop in QWHILE.PAS
  2521. continues as long as %@AS@%count%@AE@% is less than %@AS@%10%@AE@%:%@NL@%
  2522. %@NL@%
  2523. %@AS@%     count < 10%@NL@%
  2524. %@NL@%
  2525. %@CR:MQP42209@%%@4@%However, the %@AB@%REPEAT%@AE@% loop in QREPEAT.PAS continues until %@AS@%count%@AE@% becomes%@EH@%
  2526. greater than %@AS@%8%@AE@%:%@NL@%
  2527. %@NL@%
  2528. %@AS@%     count > 8%@NL@%
  2529. %@NL@%
  2530. %@NL@%
  2531. %@CR:MQP42300@%%@3@%%@AB@%4.2.3  FOR Loops%@AE@%%@EH@%%@NL@%
  2532. %@NL@%
  2533. %@CR:MQP42301@%%@4@%%@AB@%WHILE%@AE@% and %@AB@%REPEAT%@AE@% loops are ideal for cases in which you cannot predict how%@EH@%
  2534. many repetitions are needed. A program that gets keyboard input, for
  2535. instance, might use %@AB@%REPEAT%@AE@% to repeat an action until you press a certain
  2536. key. Sometimes, however, you know in advance exactly how many repetitions
  2537. are required.%@NL@%
  2538. %@NL@%
  2539. %@CR:MQP42302@%%@4@%The %@AB@%FOR%@AE@% loop repeats a statement, or statement block, a set number of times.%@EH@%
  2540. The QFOR.PAS program contains a simple %@AB@%FOR%@AE@% loop:%@NL@%
  2541. %@NL@%
  2542. %@AS@%     PROGRAM qfor;%@NL@%
  2543. %@NL@%
  2544. %@AS@%     { QFOR.PAS: Demonstrate FOR loop. }%@NL@%
  2545. %@NL@%
  2546. %@AS@%     VAR%@NL@%
  2547. %@AS@%         count : Integer;%@NL@%
  2548. %@NL@%
  2549. %@AS@%     BEGIN%@NL@%
  2550. %@NL@%
  2551. %@AS@%         FOR count := 0 TO 10 DO%@NL@%
  2552. %@AS@%             Writeln( 'count = ', count );%@NL@%
  2553. %@NL@%
  2554. %@AS@%     END.%@NL@%
  2555. %@NL@%
  2556. %@CR:MQP42303@%%@4@%QFOR.PAS produces this output:%@EH@%%@NL@%
  2557. %@NL@%
  2558.      %@AS@%count = 0%@AE@%%@NL@%
  2559.      %@AS@%count = 1%@AE@%%@NL@%
  2560.      %@AS@%count = 2%@AE@%%@NL@%
  2561.      %@AS@%count = 3%@AE@%%@NL@%
  2562.      %@AS@%count = 4%@AE@%%@NL@%
  2563.      %@AS@%count = 5%@AE@%%@NL@%
  2564.      %@AS@%count = 6%@AE@%%@NL@%
  2565.      %@AS@%count = 7%@AE@%%@NL@%
  2566.      %@AS@%count = 8%@AE@%%@NL@%
  2567.      %@AS@%count = 9%@AE@%%@NL@%
  2568.      %@AS@%count = 10%@AE@%%@NL@%
  2569. %@NL@%
  2570. %@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@%
  2571. %@NL@%
  2572. %@AS@%     FOR count := 0 TO 10 DO%@NL@%
  2573. %@AS@%         Writeln( 'count = ', count );%@NL@%
  2574. %@NL@%
  2575. %@CR:MQP42305@%%@4@%In this example the control variable %@AS@%count%@AE@% is first set to %@AS@%0%@AE@%. Each%@EH@%
  2576. repetition executes the loop body once and adds 1 to %@AS@%count%@AE@% until %@AS@%count%@AE@%
  2577. reaches %@AS@%10%@AE@%, the terminating value.%@NL@%
  2578. %@NL@%
  2579. %@CR:MQP42306@%%@4@%%@AB@%FOR%@AE@% loops can count down as well as up. The %@AB@%TO%@AE@% keyword makes the loop count%@EH@%
  2580. up in increments of 1, and %@AB@%DOWNTO%@AE@% has the opposite effect. If you substitute
  2581. this loop in QFOR.PAS, the loop counts down from %@AS@%10%@AE@% to%@AS@%0%@AE@% in increments of 1:%@NL@%
  2582. %@NL@%
  2583. %@AS@%     FOR count := 10 DOWNTO 0 DO%@NL@%
  2584. %@AS@%         Writeln( 'count = ', count );%@NL@%
  2585. %@NL@%
  2586. %@CR:MQP42307@%%@4@%The loop body in QFOR.PAS happens to be a single statement. If the loop body%@EH@%
  2587. is a statement block, you must enclose the block with %@AB@%BEGIN%@AE@% and %@AB@%END%@AE@%
  2588. statements:%@NL@%
  2589. %@NL@%
  2590. %@AS@%     FOR count := 0 TO 10 DO%@NL@%
  2591. %@AS@%         BEGIN%@NL@%
  2592. %@AS@%         Writeln( 'count = ', count );%@NL@%
  2593. %@AS@%         Writeln( 'Another statement' );%@NL@%
  2594. %@AS@%         END;%@NL@%
  2595. %@NL@%
  2596. %@NL@%
  2597. %@CR:MQP43000@%%@2@%%@AB@%4.3  Decision-Making Statements%@AE@%%@EH@%%@NL@%
  2598. %@NL@%
  2599. %@CR:MQP43001@%%@4@%Decision-making statements allow your program to perform different actions%@EH@%
  2600. based on the outcome of a logical test. This section examines the Pascal
  2601. decision-making statements: %@AB@%IF%@AE@% and %@AB@%CASE%@AE@%.%@NL@%
  2602. %@NL@%
  2603. %@NL@%
  2604. %@CR:MQP43100@%%@3@%%@AB@%4.3.1  IF Statements%@AE@%%@EH@%%@NL@%
  2605. %@NL@%
  2606. %@CR:MQP43101@%%@4@%An %@AB@%IF%@AE@% statement consists of the %@AB@%IF%@AE@% keyword followed by a test expression and%@EH@%
  2607. the %@AB@%THEN%@AE@% keyword. After %@AB@%THEN%@AE@% is a statement or statement block. The
  2608. statement is executed if the test expression is true, or skipped if it is
  2609. false.%@NL@%
  2610. %@NL@%
  2611. %@CR:MQP43102@%%@4@%The QIF.PAS program contains a simple %@AB@%IF%@AE@% statement:%@EH@%%@NL@%
  2612. %@NL@%
  2613. %@AS@%     PROGRAM qif;%@NL@%
  2614. %@NL@%
  2615. %@AS@%     { QIF.PAS: Demonstrate IF statement.  }%@NL@%
  2616. %@NL@%
  2617. %@AS@%     VAR%@NL@%
  2618. %@AS@%         my_val : Integer;%@NL@%
  2619. %@NL@%
  2620. %@AS@%     BEGIN%@NL@%
  2621. %@NL@%
  2622. %@AS@%         my_val := 3;%@NL@%
  2623. %@NL@%
  2624. %@AS@%         IF (my_val = 3) THEN Writeln( 'my_val equals 3' );%@NL@%
  2625. %@NL@%
  2626. %@AS@%     END.%@NL@%
  2627. %@NL@%
  2628. %@CR:MQP43103@%%@4@%Here is the %@AB@%IF%@AE@% statement from QIF.PAS:%@EH@%%@NL@%
  2629. %@NL@%
  2630. %@AS@%     IF (my_val = 3) THEN Writeln( 'my_val equals 3' );%@NL@%
  2631. %@NL@%
  2632. %@CR:MQP43104@%%@4@%In this statement the test condition%@EH@%%@NL@%
  2633. %@NL@%
  2634. %@AS@%     (my_val = 3)%@NL@%
  2635. %@NL@%
  2636. %@CR:MQP43105@%%@4@%compares the variable %@AS@%my_val%@AE@% to the constant %@AS@%3%@AE@%. Since the comparison is%@EH@%
  2637. true (%@AS@%my_val%@AE@% does equal %@AS@%3%@AE@%), QIF.PAS prints:%@NL@%
  2638. %@NL@%
  2639. %@AS@%     my_val equals 3%@NL@%
  2640. %@NL@%
  2641. %@CR:MQP43106@%%@4@%The statement following %@AB@%THEN%@AE@% can be a single statement or a statement block.%@EH@%
  2642. A block must be enclosed with %@AB@%BEGIN%@AE@% and %@AB@%END%@AE@% statements:%@NL@%
  2643. %@NL@%
  2644. %@AS@%     IF (my_val = 3) THEN%@NL@%
  2645. %@AS@%         BEGIN%@NL@%
  2646. %@AS@%         Writeln( 'my_val equals 3' );%@NL@%
  2647. %@AS@%         Writeln( 'Another statement' );%@NL@%
  2648. %@AS@%         END;%@NL@%
  2649. %@NL@%
  2650. %@NL@%
  2651. %@CR:MQP43200@%%@3@%%@AB@%4.3.2  ELSE Clauses%@AE@%%@EH@%%@NL@%
  2652. %@NL@%
  2653. %@CR:MQP43201@%%@4@%The %@AB@%ELSE%@AE@% keyword allows an %@AB@%IF%@AE@% statement to perform more complex branching.%@EH@%
  2654. The QELSE.PAS program adds an %@AB@%ELSE%@AE@% clause to QIF.PAS:%@NL@%
  2655. %@NL@%
  2656. %@AS@%     PROGRAM qelse;%@NL@%
  2657. %@NL@%
  2658. %@AS@%     { QELSE.PAS: Demonstrate ELSE clause. }%@NL@%
  2659. %@NL@%
  2660. %@NL@%
  2661. %@AS@%     VAR%@NL@%
  2662. %@AS@%         my_val : Integer;%@NL@%
  2663. %@NL@%
  2664. %@AS@%     BEGIN%@NL@%
  2665. %@NL@%
  2666. %@AS@%         my_val := 555;%@NL@%
  2667. %@NL@%
  2668. %@AS@%         IF (my_val = 3) THEN%@NL@%
  2669. %@AS@%              Writeln( 'my_val equals 3' )%@NL@%
  2670. %@AS@%         ELSE%@NL@%
  2671. %@AS@%              Writeln( 'my_val does not equal 3' )%@NL@%
  2672. %@NL@%
  2673. %@AS@%     END.%@NL@%
  2674. %@NL@%
  2675. %@CR:MQP43202@%%@4@%The QELSE.PAS program contains the following %@AB@%IF...ELSE%@AE@% statement:%@EH@%%@NL@%
  2676. %@NL@%
  2677. %@AS@%     IF (my_val = 3) THEN%@NL@%
  2678. %@AS@%          Writeln( 'my_val equals 3' )%@NL@%
  2679. %@AS@%     ELSE%@NL@%
  2680. %@AS@%          Writeln( 'my_val does not equal 3' );%@NL@%
  2681. %@NL@%
  2682. %@CR:MQP43203@%%@4@%The %@AB@%ELSE%@AE@% clause allows the %@AB@%IF%@AE@% statement to take two alternate actions. The%@EH@%
  2683. %@AB@%IF%@AE@% statement prints%@NL@%
  2684. %@NL@%
  2685. %@AS@%     my_val equals 3%@NL@%
  2686. %@NL@%
  2687. %@CR:MQP43204@%%@4@%if %@AS@%my_val%@AE@% equals %@AS@%3%@AE@%, and it prints%@EH@%%@NL@%
  2688. %@NL@%
  2689. %@AS@%     my_val does not equal 3%@NL@%
  2690. %@NL@%
  2691. %@CR:MQP43205@%%@4@%in all other cases. Note that a semicolon does not precede the %@AB@%ELSE%@AE@%, because%@EH@%
  2692. %@AB@%ELSE%@AE@% is considered part of the %@AB@%IF%@AE@% statement.%@NL@%
  2693. %@NL@%
  2694. %@CR:MQP43206@%%@4@%You can nest and combine %@AB@%IF%@AE@% statements and %@AB@%ELSE%@AE@% clauses as needed. Each %@AB@%ELSE%@AE@%%@EH@%
  2695. is associated with the closest preceding %@AB@%IF%@AE@% that does not have an %@AB@%ELSE%@AE@%
  2696. already. Consider this example:%@NL@%
  2697. %@NL@%
  2698. %@AS@%     IF (my_val > 9) THEN%@NL@%
  2699. %@AS@%         IF (my_val = 10) THEN%@NL@%
  2700. %@AS@%             Writeln( 'Ten' )%@NL@%
  2701. %@AS@%         ELSE%@NL@%
  2702. %@AS@%             Writeln( 'Greater than nine, but not ten ')%@NL@%
  2703. %@AS@%     ELSE%@NL@%
  2704. %@AS@%         Writeln( 'Less than ten' );%@NL@%
  2705. %@NL@%
  2706. %@CR:MQP43207@%%@4@%The example can take three different actions. If %@AS@%my_val%@AE@% is greater then %@AS@%9%@AE@%%@EH@%
  2707. 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
  2708. %@AS@%10%@AE@%, it prints %@AS@%Greater than nine, but not ten%@AE@%. If %@AS@%my_val%@AE@% is less than or
  2709. equal to %@AS@%9%@AE@%, it prints %@AS@%Less than ten%@AE@%.%@NL@%
  2710. %@NL@%
  2711. %@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@%
  2712. applies to the surrounding %@AB@%IF%@AE@%, as shown below:%@NL@%
  2713. %@NL@%
  2714. %@AS@%     IF (my_val > 9) THEN%@NL@%
  2715. %@AS@%          BEGIN%@NL@%
  2716. %@AS@%          IF (my_val = 10) THEN%@NL@%
  2717. %@AS@%                Writeln( 'Ten' );%@NL@%
  2718. %@AS@%          END%@NL@%
  2719. %@AS@%     ELSE%@NL@%
  2720. %@AS@%          Writeln( 'Less than ten ');%@NL@%
  2721. %@NL@%
  2722. %@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@%
  2723. Without the %@AB@%BEGIN%@AE@%...%@AB@%END%@AE@% block, the %@AB@%ELSE%@AE@% clause would apply to the %@AS@%IF (my_val%@AE@%
  2724. %@AS@%= 10)%@AE@% condition, and not to %@AS@%IF (my_val%@AE@%%@AS@%> 9)%@AE@%.%@NL@%
  2725. %@NL@%
  2726. %@NL@%
  2727. %@CR:MQP43300@%%@3@%%@AB@%4.3.3  CASE Statements%@AE@%%@EH@%%@NL@%
  2728. %@NL@%
  2729. %@CR:MQP43301@%%@4@%As the previous example demonstrates, complex %@AB@%IF...ELSE%@AE@% statements can be%@EH@%
  2730. difficult to read. If all of the branches test the same value (as in the
  2731. previous example), the %@AB@%CASE%@AE@% statement provides a cleaner solution.%@NL@%
  2732. %@NL@%
  2733. %@CR:MQP43302@%%@4@%The Pascal %@AB@%CASE%@AE@% statement is similar to %@AB@%SELECT CASE%@AE@% in BASIC or the %@AB@%switch%@AE@%%@EH@%
  2734. statement in C. It can branch to several different alternatives based on the
  2735. value of a single ordinal expression test. The QCASE.PAS program contains a
  2736. simple %@AB@%CASE%@AE@% statement:%@NL@%
  2737. %@NL@%
  2738. %@AS@%     PROGRAM qcase;%@NL@%
  2739. %@NL@%
  2740. %@AS@%     { QCASE.PAS: Demonstrate CASE statement. }%@NL@%
  2741. %@NL@%
  2742. %@AS@%     VAR%@NL@%
  2743. %@AS@%         my_val : Integer;%@NL@%
  2744. %@NL@%
  2745. %@AS@%     BEGIN%@NL@%
  2746. %@NL@%
  2747. %@AS@%         my_val := 33;%@NL@%
  2748. %@NL@%
  2749. %@AS@%         CASE my_val OF%@NL@%
  2750. %@AS@%             10 : Writeln( 'Ten' );%@NL@%
  2751. %@AS@%             20 : Writeln( 'Twenty' )%@NL@%
  2752. %@AS@%             ELSE%@NL@%
  2753. %@AS@%                 Writeln( 'Not ten or twenty' );%@NL@%
  2754. %@AS@%             END;%@NL@%
  2755. %@NL@%
  2756. %@AS@%     END.%@NL@%
  2757. %@NL@%
  2758. %@CR:MQP43303@%%@4@%A %@AB@%CASE%@AE@% statement begins with the %@AB@%CASE%@AE@% keyword, followed by an ordinal%@EH@%
  2759. expression and the %@AB@%OF%@AE@% keyword. The %@AB@%CASE%@AE@% statement in QCASE.PAS tests the
  2760. value of %@AS@%my_val%@AE@%:%@NL@%
  2761. %@NL@%
  2762. %@AS@%     CASE my_val OF%@NL@%
  2763. %@NL@%
  2764. %@CR:MQP43304@%%@4@%Next comes a list of alternatives, each labeled with a constant followed by%@EH@%
  2765. a colon (a "case constant"):%@NL@%
  2766. %@NL@%
  2767. %@AS@%     10 : Writeln( 'Ten' );%@NL@%
  2768. %@AS@%     20 : Writeln( 'Twenty' );%@NL@%
  2769. %@NL@%
  2770. %@CR:MQP43305@%%@4@%The alternatives to execute can be single statements or statement blocks.%@EH@%
  2771. Each case constant in the list acts as a target. When %@AS@%my_val%@AE@% equals %@AS@%10%@AE@%,
  2772. QCASE.PAS executes the statement after the case constant%@NL@%
  2773. %@NL@%
  2774. %@AS@%     10:%@NL@%
  2775. %@NL@%
  2776. %@CR:MQP43306@%%@4@%When %@AS@%my_val%@AE@% equals %@AS@%20%@AE@%, control is transferred to the case constant%@EH@%%@NL@%
  2777. %@NL@%
  2778. %@AS@%     20:%@NL@%
  2779. %@NL@%
  2780. %@CR:MQP43307@%%@4@%When %@AS@%my_val%@AE@% doesn't match any case constant, QCASE.PAS executes the%@EH@%
  2781. statement following %@AB@%ELSE%@AE@%:%@NL@%
  2782. %@NL@%
  2783. %@AS@%     ELSE%@NL@%
  2784. %@AS@%         Writeln( 'Not ten or twenty' );%@NL@%
  2785. %@NL@%
  2786. %@CR:MQP43308@%%@4@%The %@AB@%ELSE%@AE@% clause is optional. If you omit it, and the value of the expression%@EH@%
  2787. does not match any of the %@AB@%CASE%@AE@% constants, none of the alternatives are
  2788. executed. Instead, execution proceeds with the first statement following the
  2789. %@AB@%CASE%@AE@% statements.%@NL@%
  2790. %@NL@%
  2791. %@CR:MQP43309@%%@4@%The %@AB@%CASE%@AE@% statement can use as many case constants as needed. The case%@EH@%
  2792. constant can be a single constant (as shown above), a group, or a range of
  2793. constants:%@NL@%
  2794. %@NL@%
  2795. %@AS@%     CASE my_val OF%@NL@%
  2796. %@AS@%        1600,2000 : Writeln( 'Leap century' );%@NL@%
  2797. %@AS@%        1601..1999: Writeln( 'Non-leap century' );%@NL@%
  2798. %@AS@%     END;%@NL@%
  2799. %@NL@%
  2800. %@CR:MQP4330A@%%@4@%The first case constant includes two values: %@AS@%1600%@AE@% and %@AS@%2000%@AE@%. The second%@EH@%
  2801. includes a range of 399 values: %@AS@%1601%@AE@% through %@AS@%1999%@AE@%.%@NL@%
  2802. %@NL@%
  2803. %@NL@%
  2804. %@CR:MQP50000@%%@1@%%@AB@%Chapter 5  User-Defined Data Types%@AE@%%@EH@%%@NL@%
  2805. ───────────────────────────────────────────────────────────────────────────%@NL@%
  2806. %@NL@%
  2807. %@CR:MQP50001@%%@4@%Instead of limiting a program to using only predefined data types,%@EH@%
  2808. QuickPascal allows you to create your own custom data types that are
  2809. relevant to the program at hand.%@NL@%
  2810. %@NL@%
  2811. %@CR:MQP50002@%%@4@%An ordinal data type is a collection of values where each value (except the%@EH@%
  2812. first) has a unique value that precedes it and (except for the last) a
  2813. unique value that follows it. Examples of ordinal data types are %@AB@%Boolean%@AE@%,
  2814. %@AB@%Char%@AE@%, %@AB@%Integer%@AE@%, and %@AB@%LongInt%@AE@%. With QuickPascal, you can create your own
  2815. ordinal types through the use of enumerated types and subrange types.%@NL@%
  2816. %@NL@%
  2817. %@CR:MQP50003@%%@4@%An enumerated data type has a series of unique, ordinal values defined in%@EH@%
  2818. it. You can think of it in terms of an %@AB@%Integer%@AE@%, but instead of a range of
  2819. numbers, you designate a range of your own values. A subrange data type is
  2820. created by specifying the first and last elements of an existing ordinal
  2821. type. The type may be one of the standard Pascal ordinal types, or an
  2822. enumerated type of your own creation.%@NL@%
  2823. %@NL@%
  2824. %@CR:MQP50004@%%@4@%In addition to enumerated and subrange types, you can also create a set%@EH@%
  2825. type. A set holds up to 255 unique values from an existing ordinal type.%@NL@%
  2826. %@NL@%
  2827. %@NL@%
  2828. %@CR:MQP51000@%%@2@%%@AB@%5.1  Enumerated Data Types%@AE@%%@EH@%%@NL@%
  2829. %@NL@%
  2830. %@CR:MQP51001@%%@4@%Enumerated data types consist of an ordered list of unique identifiers. The%@EH@%
  2831. identifiers can be anything from cars to days of the week. An enumerated
  2832. data type is defined simply by listing the identifiers that make up the
  2833. type.%@NL@%
  2834. %@NL@%
  2835. %@CR:MQP51002@%%@4@%The syntax for an enumerated type is%@EH@%%@NL@%
  2836. %@NL@%
  2837.      %@AB@%TYPE%@AE@% %@AI@%ListName%@AE@% = (%@AI@%Identifier%@AE@% «, %@AI@%Identifier%@AE@%...»)%@NL@%
  2838. %@NL@%
  2839. %@CR:MQP51003@%%@4@%QuickPascal assigns numbers to the identifiers in the list. The first list%@EH@%
  2840. element is assigned 0, the second is 1, and so on, up to a maximum of 65,535
  2841. values. This is the QuickPascal internal representation. You normally refer
  2842. to a value by its name.%@NL@%
  2843. %@NL@%
  2844. %@CR:MQP51004@%%@4@%An example of an enumerated data type is%@EH@%%@NL@%
  2845. %@NL@%
  2846. %@AS@%     TYPE%@NL@%
  2847. %@AS@%         japanese_cars = ( honda, isuzu, nissan, toyota );%@NL@%
  2848. %@NL@%
  2849. %@CR:MQP51005@%%@4@%The use of the values assigned to elements in enumerated lists is shown in%@EH@%
  2850. this statement:%@NL@%
  2851. %@NL@%
  2852. %@AS@%     VAR%@NL@%
  2853. %@AS@%         rental_car : japanese_cars;%@NL@%
  2854. %@AS@%     BEGIN%@NL@%
  2855. %@AS@%         rental_car := nissan;%@NL@%
  2856. %@NL@%
  2857. %@CR:MQP51006@%%@4@%This puts %@AS@%nissan%@AE@%, with a value of 2, into the variable %@AS@%rental_car%@AE@%.%@EH@%%@NL@%
  2858. %@NL@%
  2859. %@CR:MQP51007@%%@4@%There may be cases where you want the first element of a list to have a%@EH@%
  2860. non-zero value. You can accomplish this by declaring a fake identifier as
  2861. the first element:%@NL@%
  2862. %@NL@%
  2863. %@AS@%     TYPE%@NL@%
  2864. %@AS@%         place = (null, first, second, third, fourth);%@NL@%
  2865. %@NL@%
  2866. %@CR:MQP51008@%%@4@%This provides a more natural numeric ordering for the list elements.%@EH@%%@NL@%
  2867. %@NL@%
  2868. %@CR:MQP51009@%%@4@%QuickPascal provides two procedures and five functions to manipulate%@EH@%
  2869. enumerated data types. The predefined routines are %@AB@%First%@AE@%, %@AB@%Last%@AE@%, %@AB@%Succ%@AE@%, %@AB@%Pred%@AE@%,
  2870. %@AB@%Inc%@AE@%, %@AB@%Dec%@AE@%, and %@AB@%Ord%@AE@%.%@NL@%
  2871. %@NL@%
  2872. %@NL@%
  2873. %@CR:MQP51100@%%@3@%%@AB@%5.1.1  The First Function%@AE@%%@EH@%%@NL@%
  2874. %@NL@%
  2875. %@CR:MQP51101@%%@4@%The %@AB@%First%@AE@% function returns the first element of any ordinal type. The%@EH@%
  2876. function is passed an ordinal type, and returns a value of the same type.%@NL@%
  2877. %@NL@%
  2878. %@CR:MQP51102@%%@4@%The following example shows you how to use %@AB@%First%@AE@%:%@EH@%%@NL@%
  2879. %@NL@%
  2880. %@AS@%   PROGRAM enums;%@NL@%
  2881. %@NL@%
  2882. %@NL@%
  2883. %@AS@%   TYPE%@NL@%
  2884. %@AS@%       my_type = -5..5;%@NL@%
  2885. %@AS@%       greek   = (alpha, beta, gamma, delta, epsilon);%@NL@%
  2886. %@AS@%       subgreek = gamma..epsilon;%@NL@%
  2887. %@NL@%
  2888. %@NL@%
  2889. %@AS@%   BEGIN%@NL@%
  2890. %@AS@%     Writeln( 'Type ':20, 'First(Type)':20, 'Last(Type)':20);%@NL@%
  2891. %@AS@%     Writeln;%@NL@%
  2892. %@AS@%     Writeln( 'Integer':20, First( Integer ):20, Last( Integer ):20 );%@NL@%
  2893. %@AS@%     Writeln( 'LongInt':20, First( LongInt ):20, Last( LongInt ):20 );%@NL@%
  2894. %@AS@%     Writeln( 'ShortInt':20, First( ShortInt ):20, Last( ShortInt ):20 );%@NL@%
  2895. %@AS@%     Writeln( 'Word':20, First( Word ):20, Last( Word ):20 );%@NL@%
  2896. %@AS@%     Writeln( 'Char(ord)':20, Ord( First( Char ) ):20,%@NL@%
  2897. %@AS@%             Ord( Last( Char ) ):20 );%@NL@%
  2898. %@AS@%     Writeln( 'Boolean':20, First( Boolean ):20, Last( Boolean ):20 );%@NL@%
  2899. %@AS@%     Writeln( 'my_type':20, First( my_type ):20, Last( my_type ):20 );%@NL@%
  2900. %@AS@%     Writeln( 'greek(ord)':20, Ord( First( greek ) ):20,%@NL@%
  2901. %@AS@%             Ord( Last( greek ) ):20 );%@NL@%
  2902. %@AS@%     Writeln( 'subgreek(ord)':20, Ord( First( subgreek ) ):20,%@NL@%
  2903. %@AS@%             Ord( Last( subgreek ) ):20 );%@NL@%
  2904. %@NL@%
  2905. %@AS@%   END.%@NL@%
  2906. %@NL@%
  2907. %@NL@%
  2908. %@CR:MQP51200@%%@3@%%@AB@%5.1.2  The Last Function%@AE@%%@EH@%%@NL@%
  2909. %@NL@%
  2910. %@CR:MQP51201@%%@4@%The %@AB@%Last%@AE@% function returns the last element of any ordinal type. The function%@EH@%
  2911. is  passed an ordinal type, and returns a value of the same type.%@NL@%
  2912. %@NL@%
  2913. %@CR:MQP51202@%%@4@%The previous example shows how to use %@AB@%Last%@AE@%.%@EH@%%@NL@%
  2914. %@NL@%
  2915. %@NL@%
  2916. %@CR:MQP51300@%%@3@%%@AB@%5.1.3  The Succ Function%@AE@%%@EH@%%@NL@%
  2917. %@NL@%
  2918. %@CR:MQP51301@%%@4@%The %@AB@%Succ%@AE@% function returns the successor, or following element, of an%@EH@%
  2919. enumerated value.%@NL@%
  2920. %@NL@%
  2921. %@AB@%Sample Function Call                Ordinal Type               Result%@AE@%%@NL@%
  2922. %@NL@%
  2923. %@AS@%Succ(second)%@AE@%                        %@AS@%place%@AE@%                      %@AS@%third%@AE@%%@NL@%
  2924. %@NL@%
  2925. %@AS@%Succ(isuzu)%@AE@%                         %@AS@%japanese_cars%@AE@%              %@AS@%nissan%@AE@%%@NL@%
  2926. %@NL@%
  2927. %@AS@%Succ(15)%@AE@%                            %@AS@%Integer%@AE@%                    %@AS@%16%@AE@%%@NL@%
  2928. %@NL@%
  2929. %@AS@%Succ('a')%@AE@%                           %@AS@%Char%@AE@%                       %@AS@%'b'%@AE@%%@NL@%
  2930. %@NL@%
  2931. %@AS@%Succ(False)%@AE@%                         %@AS@%Boolean%@AE@%                    %@AS@%True%@AE@%%@NL@%
  2932. %@NL@%
  2933. %@CR:MQP51302@%%@4@%Both standard and user-defined ordinal types can be used with this function.%@EH@%%@NL@%
  2934. %@NL@%
  2935. %@CR:MQP51303@%%@4@%If range checking %@AB@%{$R+}%@AE@% is set, a run-time error occurs if you try to assign%@EH@%
  2936. an element beyond the last in the list. You can avoid this problem by using
  2937. the %@AB@%Last%@AE@% function to check if the element is last in the list.%@NL@%
  2938. %@NL@%
  2939. %@NL@%
  2940. %@CR:MQP51400@%%@3@%%@AB@%5.1.4  The Pred Function%@AE@%%@EH@%%@NL@%
  2941. %@NL@%
  2942. %@CR:MQP51401@%%@4@%The %@AB@%Pred%@AE@% function returns the predecessor, or preceding element, of an%@EH@%
  2943. enumerated value.%@NL@%
  2944. %@NL@%
  2945. %@AB@%Sample Function Call                Ordinal Type               Result%@AE@%%@NL@%
  2946. %@NL@%
  2947. %@AS@%Pred(isuzu)%@AE@%                         %@AS@%japanese_cars%@AE@%              %@AS@%honda%@AE@%%@NL@%
  2948. %@NL@%
  2949. %@AS@%Pred(second)%@AE@%                        %@AS@%place%@AE@%                      %@AS@%first%@AE@%%@NL@%
  2950. %@NL@%
  2951. %@AS@%Pred(12)%@AE@%                            %@AS@%Integer%@AE@%                    %@AS@%11%@AE@%%@NL@%
  2952. %@NL@%
  2953. %@AS@%Pred('b')%@AE@%                           %@AS@%Char%@AE@%                       %@AS@%'a'%@AE@%%@NL@%
  2954. %@NL@%
  2955. %@AS@%Pred(True)%@AE@%                          %@AS@%Boolean%@AE@%                    %@AS@%False%@AE@%%@NL@%
  2956. %@NL@%
  2957. %@CR:MQP51402@%%@4@%Both standard and user-defined enumerated data types can be used with this%@EH@%
  2958. function.%@NL@%
  2959. %@NL@%
  2960. %@CR:MQP51403@%%@4@%If range checking %@AB@%{$R+}%@AE@% is set, a run-time error occurs if you try to assign%@EH@%
  2961. an element preceding the first in the list. You can avoid an error by using
  2962. the %@AB@%First%@AE@% function to check if the element is first in the list.%@NL@%
  2963. %@NL@%
  2964. %@NL@%
  2965. %@CR:MQP51500@%%@3@%%@AB@%5.1.5  The Inc Procedure%@AE@%%@EH@%%@NL@%
  2966. %@NL@%
  2967. %@CR:MQP51501@%%@4@%The %@AB@%Inc%@AE@% procedure provides a shorthand form of the %@AB@%Succ%@AE@% function. Upon%@EH@%
  2968. calling the procedure, the variable it is passed is incremented by the
  2969. number of elements specified.%@NL@%
  2970. %@NL@%
  2971. %@CR:MQP51502@%%@4@%For example, instead of using %@AB@%Succ%@AE@% as follows:%@EH@%%@NL@%
  2972. %@NL@%
  2973. %@AS@%     status := Succ( status );%@NL@%
  2974. %@AS@%     status := Succ( status );%@NL@%
  2975. %@NL@%
  2976. %@CR:MQP51503@%%@4@%the %@AB@%Inc%@AE@% procedure could be used as%@EH@%%@NL@%
  2977. %@NL@%
  2978. %@AS@%     Inc( status, 2 );%@NL@%
  2979. %@NL@%
  2980. %@CR:MQP51504@%%@4@%If no increment parameter is specified, the variable is incremented by one:%@EH@%%@NL@%
  2981. %@NL@%
  2982. %@AS@%     Inc( status );%@NL@%
  2983. %@NL@%
  2984. %@CR:MQP51505@%%@4@%The %@AB@%Last%@AE@% function should be used to avoid unpredictable results when%@EH@%
  2985. incrementing elements.%@NL@%
  2986. %@NL@%
  2987. %@NL@%
  2988. %@CR:MQP51600@%%@3@%%@AB@%5.1.6  The Dec Procedure%@AE@%%@EH@%%@NL@%
  2989. %@NL@%
  2990. %@CR:MQP51601@%%@4@%The %@AB@%Dec%@AE@% procedure is an alternative to the %@AB@%Pred%@AE@% function. Upon calling the%@EH@%
  2991. procedure, the variable it is passed is decremented by the number of
  2992. elements specified.%@NL@%
  2993. %@NL@%
  2994. %@CR:MQP51602@%%@4@%For example, instead of using %@AB@%Pred%@AE@% as follows:%@EH@%%@NL@%
  2995. %@NL@%
  2996. %@AS@%     status := Pred( status );%@NL@%
  2997. %@AS@%     status := Pred( status );%@NL@%
  2998. %@NL@%
  2999. %@CR:MQP51603@%%@4@%the %@AB@%Dec%@AE@% procedure could be used as%@EH@%%@NL@%
  3000. %@NL@%
  3001. %@AS@%     Dec( status, 2 );%@NL@%
  3002. %@NL@%
  3003. %@CR:MQP51604@%%@4@%If no decrement parameter is specified, the variable is decremented by one:%@EH@%%@NL@%
  3004. %@NL@%
  3005. %@AS@%     Dec( status );%@NL@%
  3006. %@NL@%
  3007. %@CR:MQP51605@%%@4@%The %@AB@%First%@AE@% function should be used to avoid unpredictable results when%@EH@%
  3008. decrementing elements.%@NL@%
  3009. %@NL@%
  3010. %@NL@%
  3011. %@CR:MQP51700@%%@3@%%@AB@%5.1.7  The Ord Function%@AE@%%@EH@%%@NL@%
  3012. %@NL@%
  3013. %@CR:MQP51701@%%@4@%The %@AB@%Ord%@AE@% function returns the ordinal number of an enumerated element. Since%@EH@%
  3014. each enumerated element is unique, you need not mention the enumerated data
  3015. type that the element belongs to. Ordinal values start at zero.%@NL@%
  3016. %@NL@%
  3017. %@AB@%Sample Function Call                Ordinal Type               Result%@AE@%%@NL@%
  3018. %@NL@%
  3019. %@AS@%Ord(first)%@AE@%                          %@AS@%place%@AE@%                      %@AS@%1%@AE@%%@NL@%
  3020. %@NL@%
  3021. %@AS@%Ord(toyota)%@AE@%                         %@AS@%japanese_cars%@AE@%              %@AS@%3%@AE@%%@NL@%
  3022. %@NL@%
  3023. %@AS@%Ord('a')%@AE@%                            %@AS@%Char%@AE@%                       %@AS@%97%@AE@%%@NL@%
  3024. %@NL@%
  3025. %@AS@%Ord(False)%@AE@%                          %@AS@%Boolean%@AE@%                    %@AS@%0%@AE@%%@NL@%
  3026. %@NL@%
  3027. %@CR:MQP51702@%%@4@%The %@AB@%Ord%@AE@% function accepts both enumeration constants and variables. Both%@EH@%
  3028. standard and user-defined enumerated data types can be used with the
  3029. function.%@NL@%
  3030. %@NL@%
  3031. %@NL@%
  3032. %@CR:MQP52000@%%@2@%%@AB@%5.2  Subrange Types%@AE@%%@EH@%%@NL@%
  3033. %@NL@%
  3034. %@CR:MQP52001@%%@4@%Sometimes, only a few of the elements of an existing data type are needed.%@EH@%
  3035. Instead of declaring a new data type, Pascal allows you to define a subrange
  3036. of either a standard or enumerated data type.%@NL@%
  3037. %@NL@%
  3038. %@CR:MQP52002@%%@4@%For example, in a grading program, the variable %@AS@%test_score%@AE@% records grades%@EH@%
  3039. between 0 and 100. Instead of creating a new data type for the variable, an
  3040. %@AB@%Integer%@AE@% subrange is declared with a minimum value of 0 and a maximum value
  3041. of 100.%@NL@%
  3042. %@NL@%
  3043. %@CR:MQP52003@%%@4@%You can define subranges of the following ordinal types:%@EH@%%@NL@%
  3044. %@NL@%
  3045. %@CR:MQP52004@%  ■  Integers%@NL@%
  3046. %@NL@%
  3047.   ■  Characters%@NL@%
  3048. %@NL@%
  3049.   ■  Enumerations%@NL@%
  3050. %@NL@%
  3051. %@CR:MQP52005@%%@4@%To declare a subrange type, identify the %@AI@%SubrangeName%@AE@% and define the first%@EH@%
  3052. and last value in the range, connected with two dots, as shown in the syntax
  3053. below:%@NL@%
  3054. %@NL@%
  3055.      %@AI@%SubrangeName%@AE@% %@AB@%=%@AE@% %@AI@%FirstValue..LastValue%@AE@%%@NL@%
  3056. %@NL@%
  3057. %@CR:MQP52006@%%@4@%The %@AI@%FirstValue%@AE@% and %@AI@%LastValue%@AE@% must be constants of the same type, with the %@EH@%
  3058. %@AI@%FirstValue%@AE@% as a predecessor of the %@AI@%LastValue%@AE@%. That is,%@NL@%
  3059. %@NL@%
  3060.      %@CR:MQP52007@%%@AI@%Ord%@AE@%( %@AB@%FirstValue%@AE@% ) %@AI@%<= Ord%@AE@%( %@AB@%LastValue%@AE@%)%@NL@%
  3061. %@NL@%
  3062. %@CR:MQP52008@%%@4@%Subrange types serve two useful purposes:%@EH@%%@NL@%
  3063. %@NL@%
  3064. %@CR:MQP52009@%  1. If the range of a type needs to be changed, only one change in the%@NL@%
  3065.      declaration is necessary.%@NL@%
  3066. %@NL@%
  3067.   2. QuickPascal automatically checks the range assigned to variables of the%@NL@%
  3068.      subrange type, with the following limitations:%@NL@%
  3069. %@NL@%
  3070.        ■  Range checking must be turned on with the compiler directive%@NL@%
  3071.           %@AB@%{$R+}%@AE@%. This can be done at the beginning of the program, or%@NL@%
  3072.           turned on (%@AB@%{$R+}%@AE@%) and off (%@AB@%{$R-}%@AE@%) around a statement where a%@NL@%
  3073.           subrange variable is used. When range checking is on, QuickPascal%@NL@%
  3074.           generates a run-time error if a value outside of the subrange is%@NL@%
  3075.           assigned to a variable of the subrange type. See Appendix B%@BO:   857d9@%,%@NL@%
  3076.           "Compiler Directives," for more information.%@NL@%
  3077. %@NL@%
  3078.        ■  QuickPascal does range checking only in direct assignment%@NL@%
  3079.           statements. It does not check for out-of-range values in%@NL@%
  3080.           loop-control variables or %@AB@%Read%@AE@%/%@AB@%Write%@AE@% statements.%@NL@%
  3081. %@NL@%
  3082. %@NL@%
  3083. %@CR:MQP52100@%%@3@%%@AB@%5.2.1  Integer Subranges%@AE@%%@EH@%%@NL@%
  3084. %@NL@%
  3085. %@CR:MQP52101@%%@4@%Integer subranges define a range of valid integer values. Some examples of%@EH@%
  3086. simple integer subranges include%@NL@%
  3087. %@NL@%
  3088. %@AS@%     TYPE%@NL@%
  3089. %@AS@%        screen_columns = 1..80;%@NL@%
  3090. %@AS@%        die_faces      = 1..6;  { values on dice faces }%@NL@%
  3091. %@AS@%        days           = 1..31; { max. 31 in a month }%@NL@%
  3092. %@AS@%        months         = 1..12; { 12 months/year }%@NL@%
  3093. %@AS@%        years          = 1900..2099; { the years DOS knows }%@NL@%
  3094. %@AS@%        seconds        = 0..59;%@NL@%
  3095. %@AS@%        minutes        = 0..59;%@NL@%
  3096. %@AS@%        hours          = 0..23;%@NL@%
  3097. %@NL@%
  3098. %@CR:MQP52102@%%@4@%Constant identifiers can define the subranges. Examples include%@EH@%%@NL@%
  3099. %@NL@%
  3100. %@AS@%     CONST%@NL@%
  3101. %@AS@%        max_col            = 80;%@NL@%
  3102. %@AS@%        max_row            = 25; { or 43 for EGA screen }%@NL@%
  3103. %@AS@%        max_days_per_month = 31;%@NL@%
  3104. %@AS@%        months_per_year    = 12;%@NL@%
  3105. %@AS@%        min_year           = 1900;%@NL@%
  3106. %@AS@%        max_year           = 2099;%@NL@%
  3107. %@NL@%
  3108. %@AS@%     TYPE%@NL@%
  3109. %@AS@%        screen_columns = 1..max_col;%@NL@%
  3110. %@AS@%        screen_rows    = 1..max_row;%@NL@%
  3111. %@AS@%        days           = 1..max_days_per_month;%@NL@%
  3112. %@AS@%        months         = 1..months_per_year;%@NL@%
  3113. %@AS@%        years          = min_year..max_year;%@NL@%
  3114. %@NL@%
  3115. %@CR:MQP52103@%%@4@%Adding constants enhances readability and simplifies the subrange limits.%@EH@%
  3116. For example, if you are developing a program that employs EGA video, you
  3117. need to display 43 lines per screen. Variables of the %@AS@%screen_rows%@AE@% type
  3118. should fall within the 1..43 range. All that is required is to change the
  3119. constant %@AS@%max_row%@AE@% to %@AS@%43%@AE@% at one location.%@NL@%
  3120. %@NL@%
  3121. %@CR:MQP52104@%%@4@%QuickPascal permits expressions in defining ranges. The following are%@EH@%
  3122. examples of declarations that include constant expressions:%@NL@%
  3123. %@NL@%
  3124. %@AS@%     CONST%@NL@%
  3125. %@AS@%        sec_per_minute  = 60;%@NL@%
  3126. %@AS@%        minute_per_hour = 60;%@NL@%
  3127. %@AS@%        hour_per_day    = 24;%@NL@%
  3128. %@NL@%
  3129. %@AS@%     TYPE%@NL@%
  3130. %@AS@%        seconds = 0..sec_per_minute - 1;%@NL@%
  3131. %@AS@%        minutes = 0..minute_per_hour - 1;%@NL@%
  3132. %@AS@%        hours   = 0..hour_per_day - 1;%@NL@%
  3133. %@NL@%
  3134. %@NL@%
  3135. %@CR:MQP52200@%%@3@%%@AB@%5.2.2  Character Subranges%@AE@%%@EH@%%@NL@%
  3136. %@NL@%
  3137. %@CR:MQP52201@%%@4@%Character subranges define a range of acceptable %@AB@%Char%@AE@% values. Examples%@EH@%
  3138. include%@NL@%
  3139. %@NL@%
  3140. %@AS@%     TYPE%@NL@%
  3141. %@AS@%        up_case_char = 'A'..'Z';%@NL@%
  3142. %@AS@%        lo_case_char = 'a'..'z';%@NL@%
  3143. %@AS@%        digit_char   = '0'..'9';%@NL@%
  3144. %@AS@%        ctrl_char    = #0..#31;%@NL@%
  3145. %@AS@%        { range of characters after 'Z' and before 'a' }%@NL@%
  3146. %@AS@%        between_Z_a  = Succ('Z') .. Pred('a');%@NL@%
  3147. %@NL@%
  3148. %@CR:MQP52202@%%@4@%Any range of ASCII characters can be defined in a subrange. Note the use of%@EH@%
  3149. the %@AB@%Succ%@AE@% and %@AB@%Pred%@AE@% functions in the last example to define the six ASCII
  3150. characters between 'Z' and 'a'. (See the ASCII character chart in Appendix
  3151. A%@BO:   829c0@%.)%@NL@%
  3152. %@NL@%
  3153. %@NL@%
  3154. %@CR:MQP52300@%%@3@%%@AB@%5.2.3  Enumerated Subranges%@AE@%%@EH@%%@NL@%
  3155. %@NL@%
  3156. %@CR:MQP52301@%%@4@%Enumerated subranges limit the range of permissible enumerated values. An%@EH@%
  3157. example is%@NL@%
  3158. %@NL@%
  3159. %@AS@%     TYPE%@NL@%
  3160. %@AS@%        vehicles = (volkswagen, honda, toyota, corvette,%@NL@%
  3161. %@AS@%                    porsche, ferrari, suburban, blazer,%@NL@%
  3162. %@AS@%                    bronco);%@NL@%
  3163. %@NL@%
  3164. %@AS@%        economy_cars = volkswagen..toyota;%@NL@%
  3165. %@AS@%        sports_cars  = corvette..ferrari;%@NL@%
  3166. %@NL@%
  3167. %@CR:MQP52302@%%@4@%The type %@AS@%economy_cars%@AE@% is a subrange with legal values of %@AS@%volkswagen%@AE@%, %@AS@%honda%@AE@%,%@EH@%
  3168. and %@AS@%toyota%@AE@%. Similarly, the %@AS@%sports_cars%@AE@% type has only the enumerated
  3169. %@AS@%corvette%@AE@%, %@AS@%porsche%@AE@%,  and %@AS@%ferrari%@AE@% values.%@NL@%
  3170. %@NL@%
  3171. %@NL@%
  3172. %@CR:MQP53000@%%@2@%%@AB@%5.3  Sets%@AE@%%@EH@%%@NL@%
  3173. %@NL@%
  3174. %@CR:MQP53001@%%@4@%Sets are structured, user-defined data types. In mathematics, a set is an%@EH@%
  3175. unordered collection of elements. The concept of a set is the same in
  3176. QuickPascal. A set holds only unique values. For example, if A, B, and C
  3177. were contained in a set, and you added B to it, the set would still only
  3178. contain A, B, and C, not A, B, B, and C. Sets are useful for holding a
  3179. collection of attributes or determining if an element is a member of a
  3180. particular group.%@NL@%
  3181. %@NL@%
  3182. %@CR:MQP53002@%%@4@%The syntax for declaring a set is%@EH@%%@NL@%
  3183. %@NL@%
  3184.      %@AI@%SetName%@AE@% %@AB@%= SET OF%@AE@% %@AI@%OrdinalType%@AE@%%@NL@%
  3185. %@NL@%
  3186. %@CR:MQP53003@%%@4@%The argument %@AI@%OrdinalType%@AE@% is an ordered range of values. The members of the%@EH@%
  3187. %@AI@%OrdinalType%@AE@% must be all of the same type, and can be single elements or a
  3188. subrange. The %@AI@%OrdinalType%@AE@% cannot have more than 256 possible values. This
  3189. limits sets to the predefined %@AB@%Boolean%@AE@%, %@AB@%Char%@AE@%, and %@AB@%Byte%@AE@% types, and restricts
  3190. the use of %@AB@%Word%@AE@%, %@AB@%Integer%@AE@%, and %@AB@%LongInt%@AE@% types.%@NL@%
  3191. %@NL@%
  3192. %@CR:MQP53004@%%@4@%As an example, a program might declare a set of uppercase letters and vowels%@EH@%
  3193. to be%@NL@%
  3194. %@NL@%
  3195. %@AS@%     CONST%@NL@%
  3196. %@AS@%         vowels     = ['A', 'E', 'I', 'O', 'U'];%@NL@%
  3197. %@AS@%         upper_case = SET OF 'A'..'Z' = ['A'..'Z'];%@NL@%
  3198. %@NL@%
  3199. %@CR:MQP53005@%%@4@%Once you have declared a set, the operator %@AB@%IN%@AE@% can be used to test for the%@EH@%
  3200. presence or absence of a specified element. For example, in these statements%@NL@%
  3201. %@NL@%
  3202. %@AS@%     IF ch IN upper_case THEN...%@NL@%
  3203. %@AS@%     IF ch IN vowels THEN...%@NL@%
  3204. %@NL@%
  3205. %@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@%
  3206. not.%@NL@%
  3207. %@NL@%
  3208. %@NL@%
  3209. %@CR:MQP53100@%%@3@%%@AB@%5.3.1  Declaring Set Types%@AE@%%@EH@%%@NL@%
  3210. %@NL@%
  3211. %@CR:MQP53101@%%@4@%Sets can be declared with a variety of types. Included are%@EH@%%@NL@%
  3212. %@NL@%
  3213. %@CR:MQP53102@%  ■  Predefined ordinal types of %@AB@%Boolean%@AE@%, %@AB@%Char%@AE@%, and %@AB@%Byte%@AE@%%@NL@%
  3214. %@NL@%
  3215.         %@AS@%TYPE%@AE@%%@NL@%
  3216.         %@AS@%boolean_set = SET OF Boolean;%@AE@%%@NL@%
  3217.         %@AS@%char_set    = SET OF Char;%@AE@%%@NL@%
  3218.         %@AS@%byte_set    = SET OF Byte;%@AE@%%@NL@%
  3219. %@NL@%
  3220.   ■  Subranges of predefined types (either directly as the first set or%@NL@%
  3221.      indirectly as the last)%@NL@%
  3222. %@NL@%
  3223.         %@AS@%TYPE%@AE@%%@NL@%
  3224.         %@AS@%bits       = 1..7;%@AE@%%@NL@%
  3225.         %@AS@%byte_bits  = SET OF bits;%@AE@%%@NL@%
  3226.         %@AS@%up_case    = SET OF 'A'..'Z';%@AE@%%@NL@%
  3227.         %@AS@%lo_case    = SET OF 'a'..'z';%@AE@%%@NL@%
  3228. %@NL@%
  3229.   ■  Enumerated types%@NL@%
  3230. %@NL@%
  3231.         %@AS@%TYPE%@AE@%%@NL@%
  3232.         %@AS@%transportation  = (bicycle, motorcycle, car, truck,%@AE@%%@NL@%
  3233.         %@AS@%bus);%@AE@%%@NL@%
  3234.         %@AS@%four_wheels    = car..bus;%@AE@%%@NL@%
  3235.         %@AS@%trans_set      = SET OF transportation;%@AE@%%@NL@%
  3236.         %@AS@%four_wheel_set  = SET OF four_wheels;%@AE@%%@NL@%
  3237. %@NL@%
  3238.   ■  Variables%@NL@%
  3239. %@NL@%
  3240.         %@AS@%VAR%@AE@%%@NL@%
  3241.         %@AS@%fast_trans    : four_wheels;%@AE@%%@NL@%
  3242.         %@AS@%lower_letters : lo_case;%@AE@%%@NL@%
  3243.         %@AS@%num1, num2    : byte_bits;%@AE@%%@NL@%
  3244. %@NL@%
  3245.   ■  Constants and typed constants%@NL@%
  3246. %@NL@%
  3247.         %@AS@%CONST%@AE@%%@NL@%
  3248.         %@AS@%math_op     : SET OF Char = ['=', '-', '^(*)', '/'];%@AE@%%@NL@%
  3249.         %@AS@%vowels      : SET OF Char = ['A','E','I','O','U'];%@AE@%%@NL@%
  3250.         %@AS@%up_chars    : SET OF Char = ['A'..'Z'];%@AE@%%@NL@%
  3251.         %@AS@%lo_chars    : SET OF Char = ['a'..'z'];%@AE@%%@NL@%
  3252.         %@AS@%cheap_trans : SET OF transportation =%@AE@%%@NL@%
  3253.         %@AS@%[bicycle, motorcycle, bus];%@AE@%%@NL@%
  3254. %@NL@%
  3255. %@CR:MQP53103@%%@4@%Character set constants are useful in representing fixed sets of characters%@EH@%
  3256. used in menu selections. For example, if you have a menu with the following
  3257. selections:%@NL@%
  3258. %@NL@%
  3259.      %@AS@%Add    Change    Delete    Print    View    Store    Recall%@AE@%%@NL@%
  3260. %@NL@%
  3261. %@CR:MQP53104@%%@4@%where the capital letters are "hot" keys used to quickly select a menu%@EH@%
  3262. option, the corresponding typed constant would look like this:%@NL@%
  3263. %@NL@%
  3264. %@AS@%     CONST%@NL@%
  3265. %@AS@%      menu_char : SET OF Char = ['A','C','D','P','V','S','R'];%@NL@%
  3266. %@NL@%
  3267. %@NL@%
  3268. %@CR:MQP53200@%%@3@%%@AB@%5.3.2  Assigning Set Elements to Variables%@AE@%%@EH@%%@NL@%
  3269. %@NL@%
  3270. %@CR:MQP53201@%%@4@%To assign set elements to a set variable, use the square brackets:%@EH@%%@NL@%
  3271. %@NL@%
  3272.      %@CR:MQP53202@%%@AI@%SetVariable%@AE@% %@AB@%:= [%@AE@%%@AI@%SetElements%@AE@%%@AB@%]%@AE@%%@NL@%
  3273. %@NL@%
  3274. %@CR:MQP53203@%%@4@%If there are no set elements present, the set variable is assigned an empty%@EH@%
  3275. set %@AB@%(%@AE@%%@AI@%SetVariable%@AE@%%@AB@%: = [])%@AE@%. Set variables may be initialized in this way.%@NL@%
  3276. %@NL@%
  3277. %@CR:MQP53204@%%@4@%A set may be constructed from a list of single elements, a subrange, or a%@EH@%
  3278. combination of both. Examples of assigning set elements to variables are%@NL@%
  3279. %@NL@%
  3280. %@AS@%     set1 := [1, 3, 5, 7, 9];{ single elements }%@NL@%
  3281. %@AS@%     set2 := [0..7]; { subrange }%@NL@%
  3282. %@AS@%     set3 := [0..7, 14, 15, 16]; { subrange & single elements }%@NL@%
  3283. %@AS@%     char_list := ['A'..'Z','a'..'z','0'..'9'];  { subranges }%@NL@%
  3284. %@NL@%
  3285. %@NL@%
  3286. %@CR:MQP53300@%%@3@%%@AB@%5.3.3  Set Operators%@AE@%%@EH@%%@NL@%
  3287. %@NL@%
  3288. %@CR:MQP53301@%%@4@%Although individual elements of a set cannot be directly accessed, a variety%@EH@%
  3289. of operators is available to test membership and manipulate the set as a
  3290. whole.%@NL@%
  3291. %@NL@%
  3292. %@CR:MQP53302@%%@4@%These operators offer powerful and flexible methods of creating new sets%@EH@%
  3293. with elements from existing sets. Set operators supported by QuickPascal
  3294. include%@NL@%
  3295. %@NL@%
  3296. %@CR:MQP53303@%  ■  Relational operators%@NL@%
  3297. %@NL@%
  3298.   ■  %@AB@%IN%@AE@% operator%@NL@%
  3299. %@NL@%
  3300.   ■  Set-union operator%@NL@%
  3301. %@NL@%
  3302.   ■  Set-difference operator%@NL@%
  3303. %@NL@%
  3304.   ■  Set-intersection operator%@NL@%
  3305. %@NL@%
  3306. %@CR:MQP53310@%%@4@%%@AB@%5.3.3.1  Relational Operators%@AE@%%@EH@%%@NL@%
  3307. %@NL@%
  3308. %@CR:MQP53311@%%@4@%A variety of relational operators is available to test set membership. Based%@EH@%
  3309. on the condition of an expression, the operator will return %@AB@%True%@AE@% or %@AB@%False%@AE@%.%@NL@%
  3310. %@NL@%
  3311. %@CR:MQP53312@%%@4@%Table 5.1 lists the relational operators that work on sets, with %@AS@%A%@AE@% and %@AS@%B%@AE@% as%@EH@%
  3312. example sets.%@NL@%
  3313. %@NL@%
  3314. %@CR:MQP5T100@%%@4@%%@AB@%Table 5.1  Relational Operators%@AE@%%@EH@%%@NL@%
  3315. %@NL@%
  3316. %@AB@%Expression      Returns True if%@AE@%%@NL@%
  3317. %@NL@%
  3318. %@AS@%A = B%@AE@%           %@AS@%A%@AE@% and %@AS@%B%@AE@% are identical.%@NL@%
  3319. %@NL@%
  3320. %@AS@%A <> B%@AE@%          At least one element in %@AS@%A%@AE@% is%@NL@%
  3321.                 not in %@AS@%B%@AE@%, or at least one element%@NL@%
  3322.                 in %@AS@%B%@AE@% is not in  A.%@NL@%
  3323. %@NL@%
  3324. %@AS@%A <= B%@AE@%          All elements in %@AS@%A%@AE@% are in %@AS@%B%@AE@%.%@NL@%
  3325. %@NL@%
  3326. %@AS@%A >= B%@AE@%          All elements in %@AS@%B%@AE@% are in %@AS@%A%@AE@%.%@NL@%
  3327. %@NL@%
  3328. %@NL@%
  3329. %@CR:MQP53320@%%@4@%%@AB@%5.3.3.2  IN Operator%@AE@%%@EH@%%@NL@%
  3330. %@NL@%
  3331. %@CR:MQP53321@%%@4@%As previously discussed, the %@AB@%IN%@AE@% operator tests for set membership. This%@EH@%
  3332. operator returns a Boolean result indicating whether a value is a member of
  3333. the set. The tested value must be the same or of a compatible type with the
  3334. tested set's base type. The syntax is%@NL@%
  3335. %@NL@%
  3336.      %@AI@%Value%@AE@% %@AB@%IN%@AE@% %@AI@%Set%@AE@%%@NL@%
  3337. %@NL@%
  3338. %@CR:MQP53322@%%@4@%For example,%@EH@%%@NL@%
  3339. %@NL@%
  3340. %@AS@%     ch IN vowels%@NL@%
  3341. %@AS@%     'i' IN consonants%@NL@%
  3342. %@AS@%     operator IN ['+', '-', '/', '*']%@NL@%
  3343. %@NL@%
  3344. %@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@%
  3345. area represents the result of the operations on the sets.%@NL@%
  3346. %@NL@%
  3347. %@CR:MQP5f000@%%@4@%%@AB@%Figure 5.1  Set Operators%@AE@%%@EH@%%@NL@%
  3348. %@NL@%
  3349.         │        A + B         │         A - B         │         A * B         │%@NL@%
  3350.         │       (Union)        │      (Difference)     │    (Intersection)     │%@NL@%
  3351. ────────┼──────────────────────┼───────────────────────┼───────────────────────┤%@NL@%
  3352.         │┌───────────┐         │ ┌───────────┐         │ ┌───────────┐         │%@NL@%
  3353. A and B ││▒A▒▒▒▒▒▒▒▒▒│ ┌──────┐│ │▒A▒▒▒▒▒▒▒▒▒│ ┌──────┐│ │ A         │ ┌──────┐│%@NL@%
  3354.   are   ││▒▒▒▒▒▒▒▒▒▒▒│ │▒▒▒▒B▒││ │▒▒▒▒▒▒▒▒▒▒▒│ │    B ││ │           │ │    B ││%@NL@%
  3355. disjoint││▒▒▒▒▒▒▒▒▒▒▒│ │▒▒▒▒▒▒││ │▒▒▒▒▒▒▒▒▒▒▒│ │      ││ │           │ │      ││%@NL@%
  3356.  sets.  ││▒▒▒▒▒▒▒▒▒▒▒│ └──────┘│ │▒▒▒▒▒▒▒▒▒▒▒│ └──────┘│ │           │ └──────┘│%@NL@%
  3357.         │└───────────┘         │ └───────────┘         │ └───────────┘         │%@NL@%
  3358. ────────┼──────────────────────┼───────────────────────┼───────────────────────┤%@NL@%
  3359.         │  ┌───────────┐       │   ┌───────────┐       │   ┌───────────┐       │%@NL@%
  3360.    A    │  │▒A▒▒▒▒▒▒┌──┼───┐   │   │▒A▒▒▒▒▒▒┌──┼───┐   │   │ A      ┌──┼───┐   │%@NL@%
  3361.  inter- │  │▒▒▒▒▒▒▒▒│▒▒│▒B▒│   │   │▒▒▒▒▒▒▒▒│  │ B │   │   │        │▒▒│ B │   │%@NL@%
  3362.  sects  │  │▒▒▒▒▒▒▒▒│▒▒│▒▒▒│   │   │▒▒▒▒▒▒▒▒│  │   │   │   │        │▒▒│   │   │%@NL@%
  3363.    B    │  │▒▒▒▒▒▒▒▒└──┼───┘   │   │▒▒▒▒▒▒▒▒└──┼───┘   │   │        └──┼───┘   │%@NL@%
  3364.         │  └───────────┘       │   └───────────┘       │   └───────────┘       │%@NL@%
  3365. ────────┼──────────────────────┼───────────────────────┼───────────────────────┤%@NL@%
  3366.         │    ┌───────────┐     │     ┌───────────┐     │     ┌───────────┐     │%@NL@%
  3367.  B is a │    │▒A▒┌──────┐│     │     │▒A▒┌──────┐│     │     │ A ┌──────┐│     │%@NL@%
  3368.  subset │    │▒▒▒│▒▒▒▒B▒││     │     │▒▒▒│    B ││     │     │   │▒▒▒▒B▒││     │%@NL@%
  3369.   of A  │    │▒▒▒│▒▒▒▒▒▒││     │     │▒▒▒│      ││     │     │   │▒▒▒▒▒▒││     │%@NL@%
  3370.         │    │▒▒▒└──────┘│     │     │▒▒▒└──────┘│     │     │   └──────┘│     │%@NL@%
  3371.         │    └───────────┘     │     └───────────┘     │     └───────────┘     │%@NL@%
  3372. ────────┴──────────────────────┴───────────────────────┴───────────────────────┘%@NL@%
  3373. %@NL@%
  3374. %@NL@%
  3375. %@CR:MQP53330@%%@4@%%@AB@%5.3.3.3  Set-Union Operator%@AE@%%@EH@%%@NL@%
  3376. %@NL@%
  3377. %@CR:MQP53331@%%@4@%The set-union operator (+) merges two sets into a third set. If either set%@EH@%
  3378. is a subset of the other, combining the two sets results in a set that is
  3379. the same as the larger set. In the example below, two sets with unique
  3380. members are merged, resulting in a larger set:%@NL@%
  3381. %@NL@%
  3382. %@AS@%     set1 := ['A'..'Z'];%@NL@%
  3383. %@AS@%     set2 := ['a'..'z'];%@NL@%
  3384. %@AS@%     set3 := set1 + set2;%@NL@%
  3385. %@AS@%     set3 := ['A'..'Z','a'..'z']; { same as previous assignment }%@NL@%
  3386. %@NL@%
  3387. %@CR:MQP53332@%%@4@%In the next example, the two character sets have overlapping members. The%@EH@%
  3388. united set consists of %@AS@%['A'..'Z']%@AE@% with any overlapping members represented
  3389. only once.%@NL@%
  3390. %@NL@%
  3391. %@AS@%     set1 := ['A'..'L'];%@NL@%
  3392. %@AS@%     set2 := ['H'..'Z'];%@NL@%
  3393. %@AS@%     set3 := set1 + set2;%@NL@%
  3394. %@AS@%     set3 := ['A'..'Z'];{ equivalent to previous assignment }%@NL@%
  3395. %@NL@%
  3396. %@CR:MQP53333@%%@4@%The third example shows a set being united with a subset. This results in%@EH@%
  3397. %@AS@%set3%@AE@% and %@AS@%set1%@AE@% having the same members.%@NL@%
  3398. %@NL@%
  3399. %@AS@%     set1 := ['A'..'L'];%@NL@%
  3400. %@AS@%     set2 := ['F'..'J'];%@NL@%
  3401. %@AS@%     set3 := set1 + set2;%@NL@%
  3402. %@AS@%     set3 := ['A'..'L'];  { equivalent to previous assignment }%@NL@%
  3403. %@NL@%
  3404. %@CR:MQP53334@%%@4@%The union operator is also important for adding to the membership of a set.%@EH@%
  3405. In the following example, a character set is initialized and then a %@AB@%FOR%@AE@% loop
  3406. is used to add the characters %@AS@%A,B,C,D,E,F,...,%@AE@%:%@NL@%
  3407. %@NL@%
  3408. %@AS@%     set1 := []; { initialize }%@NL@%
  3409. %@AS@%     FOR ch := 'A' TO 'Z' DO%@NL@%
  3410. %@AS@%         set1 := set1 + [ch];%@NL@%
  3411. %@NL@%
  3412. %@CR:MQP53335@%%@4@%Note the presence of the set brackets around the %@AS@%ch%@AE@% variable. They are%@EH@%
  3413. required in order to make %@AS@%[ch]%@AE@% a single-element set.%@NL@%
  3414. %@NL@%
  3415. %@CR:MQP53336@%%@4@%Refer to Figure 5.1%@BO:   279a5@% for an illustration of the union operator.%@EH@%%@NL@%
  3416. %@NL@%
  3417. %@CR:MQP53340@%%@4@%%@AB@%5.3.3.4  Set-Difference Operator%@AE@%%@EH@%%@NL@%
  3418. %@NL@%
  3419. %@CR:MQP53341@%%@4@%The set-difference operator (%@AB@%-)%@AE@% creates a set that contains all of the%@EH@%
  3420. members of the first set that do not appear in the second set. For example,
  3421. in the statement%@NL@%
  3422. %@NL@%
  3423. %@AS@%     set3 := set1 - set2;%@NL@%
  3424. %@NL@%
  3425. %@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@%
  3426. %@NL@%
  3427. %@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@%
  3428. %@AS@%set2%@AE@% is a subset of %@AS@%set1%@AE@%, then %@AS@%set3%@AE@% comprises of the members of %@AS@%set1%@AE@% that
  3429. are not common to %@AS@%set2%@AE@%.%@NL@%
  3430. %@NL@%
  3431. %@CR:MQP53344@%%@4@%In the following example, the difference between two sets with unique%@EH@%
  3432. members is assigned to a third set. The resulting set has the same members
  3433. as %@AS@%set1%@AE@% since the operand sets have nothing in common:%@NL@%
  3434. %@NL@%
  3435. %@AS@%     set1 := ['A'..'Z'];%@NL@%
  3436. %@AS@%     set2 := ['a'..'z'];%@NL@%
  3437. %@AS@%     set3 := set1 - set2;%@NL@%
  3438. %@AS@%     set3 := ['A'..'Z']; { equivalent to previous assignment }%@NL@%
  3439. %@NL@%
  3440. %@CR:MQP53345@%%@4@%In the next example, the two character sets have overlapping members. The%@EH@%
  3441. resulting set is made up of %@AS@%['A'..'G']%@AE@%:%@NL@%
  3442. %@NL@%
  3443. %@AS@%     set1 := ['A'..'L'];%@NL@%
  3444. %@AS@%     set2 := ['H'..'Z'];%@NL@%
  3445. %@AS@%     set3 := set1 - set2;%@NL@%
  3446. %@AS@%     set3 := ['A'..'G']; { equivalent to previous assignment }%@NL@%
  3447. %@NL@%
  3448. %@CR:MQP53346@%%@4@%The next example shows the difference of a set with its subset. The result%@EH@%
  3449. is that %@AS@%set3%@AE@% contains %@AS@%['A'..'E']%@AE@%, the members of the first set not found in
  3450. the second one.%@NL@%
  3451. %@NL@%
  3452. %@AS@%     set1 := ['A'..'L'];%@NL@%
  3453. %@AS@%     set2 := ['F'..'J'];%@NL@%
  3454. %@AS@%     set3 := set1 - set2;%@NL@%
  3455. %@AS@%     set3 := ['A'..'E', 'K', 'L']; { equivalent to previous assignment }%@NL@%
  3456. %@NL@%
  3457. %@CR:MQP53347@%%@4@%The difference operator can also be used to strip single members from set%@EH@%
  3458. variables. The last example for the union operator can be rewritten to use
  3459. the difference operator in the following way. The character set is
  3460. initialized to %@AS@%['A'..'Z']%@AE@% and a %@AB@%FOR%@AE@% loop is used to eliminate the %@AS@%A, B, D,%@AE@%
  3461. %@AS@%F, H,%@AE@% characters and so on.%@NL@%
  3462. %@NL@%
  3463. %@AS@%     oddeven := 0;%@NL@%
  3464. %@AS@%     set1 := ['A'..'Z']; { initialize }%@NL@%
  3465. %@AS@%     FOR ch := 'B' TO 'Z' DO%@NL@%
  3466. %@AS@%         BEGIN%@NL@%
  3467. %@AS@%         IF (NOT Odd( Oddeven )) THEN%@NL@%
  3468. %@AS@%             set1 := set1 - [ch];%@NL@%
  3469. %@AS@%         Inc( Oddeven );%@NL@%
  3470. %@AS@%         END;%@NL@%
  3471. %@NL@%
  3472. %@CR:MQP53348@%%@4@%Refer to Figure 5.1%@BO:   279a5@% for an illustration of the difference operator.%@EH@%%@NL@%
  3473. %@NL@%
  3474. %@CR:MQP53350@%%@4@%%@AB@%5.3.3.5  Set-Intersection Operator%@AE@%%@EH@%%@NL@%
  3475. %@NL@%
  3476. %@CR:MQP53351@%%@4@%The set-intersection operator (%@AB@%*%@AE@%) is used to extract all of the elements%@EH@%
  3477. that are in two similarly typed sets. For example, with%@NL@%
  3478. %@NL@%
  3479. %@AS@%     set3 := set1 * set2;%@NL@%
  3480. %@NL@%
  3481. %@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@%
  3482. %@NL@%
  3483. %@CR:MQP53353@%%@4@%In the next example, the two character sets have overlapping members. The%@EH@%
  3484. intersection set is %@AS@%['H'..'L']%@AE@%:%@NL@%
  3485. %@NL@%
  3486. %@AS@%     set1 := ['A'..'L'];%@NL@%
  3487. %@AS@%     set2 := ['H'..'Z'];%@NL@%
  3488. %@AS@%     set3 := set1 * set2;%@NL@%
  3489. %@AS@%     set3 := ['H'..'L'];%@NL@%
  3490. %@NL@%
  3491. %@CR:MQP53354@%%@4@%The intersection of a set with its subset returns the members of the subset.%@EH@%
  3492. The next example shows such an operation. The result is that %@AS@%set3%@AE@% and %@AS@%set2%@AE@%
  3493. have the same members:%@NL@%
  3494. %@NL@%
  3495. %@AS@%     set1 := ['A'..'L'];%@NL@%
  3496. %@AS@%     set2 := ['F'..'J'];%@NL@%
  3497. %@AS@%     set3 := set1 * set2;%@NL@%
  3498. %@AS@%     set3 := ['F'..'J'];%@NL@%
  3499. %@NL@%
  3500. %@CR:MQP53355@%%@4@%In the following example, two sets with unique members are intersected. The%@EH@%
  3501. resulting set is empty, since the operand sets have nothing in common:%@NL@%
  3502. %@NL@%
  3503. %@AS@%     set1 := ['A'..'Z'];%@NL@%
  3504. %@AS@%     set2 := ['a'..'z'];%@NL@%
  3505. %@AS@%     set3 := set1 * set2;%@NL@%
  3506. %@AS@%     set3 := [];%@NL@%
  3507. %@NL@%
  3508. %@NL@%
  3509. %@CR:MQP60000@%%@1@%%@AB@%Chapter 6  Arrays and Records%@AE@%%@EH@%%@NL@%
  3510. ───────────────────────────────────────────────────────────────────────────%@NL@%
  3511. %@NL@%
  3512. %@CR:MQP60001@%%@4@%This chapter presents data types that hold organized collections of data in%@EH@%
  3513. a definite order.%@NL@%
  3514. %@NL@%
  3515. %@CR:MQP60002@%%@4@%An "array" is a collection of data items of the same type. Programs use%@EH@%
  3516. arrays in situations where a standard data format is repeated many times.
  3517. For example, numbers representing the Gross National Product for all the
  3518. years from 1900 to 1980 might be placed in an array.%@NL@%
  3519. %@NL@%
  3520. %@CR:MQP60003@%%@4@%A "record" is a collection of data items having different types. Programs%@EH@%
  3521. use records in situations where a variety of data have a close association.
  3522. For example, all of the information on a given employee──name, salary, and
  3523. security clearance──might be placed in a single record.%@NL@%
  3524. %@NL@%
  3525. %@CR:MQP60004@%%@4@%Finally, this chapter presents the "variant record" type, which is an%@EH@%
  3526. extension of the record type. A variant record allows you to use different
  3527. data formats to access the same area of memory, enabling you to create a
  3528. record that holds different kinds of information at different times.%@NL@%
  3529. %@NL@%
  3530. %@CR:MQP60005@%%@4@%Each of the major sections in this chapter introduces a data type, shows how%@EH@%
  3531. to declare it, then shows how to access its components.%@NL@%
  3532. %@NL@%
  3533. %@NL@%
  3534. %@CR:MQP61000@%%@2@%%@AB@%6.1  Arrays%@AE@%%@EH@%%@NL@%
  3535. %@NL@%
  3536. %@CR:MQP61001@%%@4@%An array is a collection of elements that share the same data type and a%@EH@%
  3537. common variable name. You access an element in the array by specifying the
  3538. position of the element. An integer or ordinal value indicates the position
  3539. and is called an "index."%@NL@%
  3540. %@NL@%
  3541. %@CR:MQP61002@%%@4@%Pascal lets you declare arrays of any type. You can even declare arrays of%@EH@%
  3542. arrays, which are, in essence, two-dimensional arrays. You can declare
  3543. arrays with any number of dimensions. Multidimensional arrays have many
  3544. applications and appear often in Pascal programs. For example, a program
  3545. that requires a grid will use a two-dimensional array, and a program that
  3546. maps three-dimensional space will use a three-dimensional array. The
  3547. simplest arrays are one-dimensional. They consist of a linear sequence of
  3548. elements.%@NL@%
  3549. %@NL@%
  3550. %@NL@%
  3551. %@CR:MQP61100@%%@3@%%@AB@%6.1.1  Declaring Arrays%@AE@%%@EH@%%@NL@%
  3552. %@NL@%
  3553. %@CR:MQP61101@%%@4@%In many languages (such as C), arrays must always start at a particular%@EH@%
  3554. index number (such as 0 or 1). In Pascal, however, you can define the bounds
  3555. of an array with almost any ordinal type:%@NL@%
  3556. %@NL@%
  3557.      %@AB@%ARRAY [%@AE@%%@AI@%IndexType%@AE@%%@AB@%] OF %@AE@%%@AI@%ElementType%@AE@%%@NL@%
  3558. %@NL@%
  3559. %@CR:MQP61102@%%@4@%To declare a multidimensional array, you declare an index type for each%@EH@%
  3560. dimension:%@NL@%
  3561. %@NL@%
  3562.      %@AB@%ARRAY [%@AE@%%@AI@%IndexType%@AE@%%@AB@%, %@AE@%%@AI@%IndexType%@AE@%%@AB@% ...] OF %@AE@%%@AI@%type%@AE@%%@NL@%
  3563. %@NL@%
  3564. %@CR:MQP61103@%%@4@%%@AI@%IndexType%@AE@% can be any ordinal type except %@AB@%LongInt%@AE@% or subranges of %@AB@%LongInt%@AE@%.%@EH@%
  3565. Most often, programs use subranges in array declarations. The lower and
  3566. upper bounds of the subrange give the lowest and highest index, and also
  3567. determine the size of the array. For example:%@NL@%
  3568. %@NL@%
  3569. %@AS@%     TYPE%@NL@%
  3570. %@AS@%         income_per_year = ARRAY[1977..1989] OF LongInt;%@NL@%
  3571. %@AS@%         class_size = ARRAY[1..12] OF Integer;%@NL@%
  3572. %@AS@%         grid = ARRAY[-5..5, -10..10] OF Real;%@NL@%
  3573. %@NL@%
  3574. %@CR:MQP61104@%%@4@%As you can see, even negative numbers can serve as array bounds. Because%@EH@%
  3575. Pascal is so structured, you can use many different integer subranges and
  3576. enumerated types to index arrays. For example:%@NL@%
  3577. %@NL@%
  3578. %@AS@%     TYPE%@NL@%
  3579. %@AS@%         pay = LongInt;%@NL@%
  3580. %@AS@%         rank = (private, sergeant, lt, captain, major, general);%@NL@%
  3581. %@AS@%         officers = lt..general ;%@NL@%
  3582. %@AS@%         letters = 'A'..'Z';%@NL@%
  3583. %@AS@%         my_arr = ARRAY[1..10] OF Real;%@NL@%
  3584. %@NL@%
  3585. %@AS@%     VAR%@NL@%
  3586. %@AS@%         low_pay : ARRAY[private .. sergeant] OF pay;%@NL@%
  3587. %@AS@%         high_pay : ARRAY[officers] OF pay;%@NL@%
  3588. %@AS@%         ascii_code : ARRAY[letters] OF Word;%@NL@%
  3589. %@AS@%         big_arr : ARRAY[letters] OF my_arr;%@NL@%
  3590. %@NL@%
  3591. %@CR:MQP61105@%%@4@%The last example above, %@AS@%big_arr%@AE@%, is really a two-dimensional array and is%@EH@%
  3592. equivalent to the following declaration, which specifies the ranges of the
  3593. two dimensions explicitly:%@NL@%
  3594. %@NL@%
  3595. %@AS@%     big_arr : ARRAY[letters, 1..10] OF Real;%@NL@%
  3596. %@NL@%
  3597. %@CR:MQP61106@%%@4@%Bear in mind the difference between the index type of an array and the%@EH@%
  3598. element type. The item in brackets defines the index type of the array and
  3599. is significant in the following ways:%@NL@%
  3600. %@NL@%
  3601. %@CR:MQP61107@%  ■  The index type determines the range and meaning of indexes. The next%@NL@%
  3602.      section describes how you use indexes to access elements.%@NL@%
  3603. %@NL@%
  3604.   ■  The index type determines the number of elements in the array. For%@NL@%
  3605.      example, an array with subrange %@AS@%1..500%@AE@% has 500 elements. An array with%@NL@%
  3606.      subrange %@AS@%101..103%@AE@% has three elements.%@NL@%
  3607. %@NL@%
  3608. %@CR:MQP61108@%%@4@%The elements are declared by the data type at the end of the array%@EH@%
  3609. declaration. As mentioned above, you can use any data type, including any of
  3610. the advanced data types mentioned later in this book. Each element of the
  3611. array has this element type.%@NL@%
  3612. %@NL@%
  3613. %@NL@%
  3614. %@CR:MQP61200@%%@3@%%@AB@%6.1.2  Accessing Array Elements%@AE@%%@EH@%%@NL@%
  3615. %@NL@%
  3616. %@CR:MQP61201@%%@4@%To refer to an element of an array, use the syntax%@EH@%%@NL@%
  3617. %@NL@%
  3618.      %@AI@%Name%@AE@%%@AB@% [ %@AE@%%@AI@%Index%@AE@%%@AB@% ]%@AE@%%@NL@%
  3619. %@NL@%
  3620. %@CR:MQP61202@%%@4@%in which %@AI@%Name%@AE@% is the name of the array variable, and %@AI@%Index%@AE@% has the index%@EH@%
  3621. type used to declare the array. If the index type is a subrange, %@AI@%Index%@AE@% must
  3622. fall into the specified range or the program produces errors. Consider the
  3623. following declarations:%@NL@%
  3624. %@NL@%
  3625. %@AS@%     VAR%@NL@%
  3626. %@AS@%         trio : ARRAY[1..3] OF Word;%@NL@%
  3627. %@AS@%         income : ARRAY[1980..1983] OF LongInt;%@NL@%
  3628. %@NL@%
  3629. %@CR:MQP61203@%%@4@%In the example above, the elements of %@AS@%trio%@AE@% are referred to as%@EH@%%@NL@%
  3630. %@NL@%
  3631. %@AS@%     trio[1]%@NL@%
  3632. %@AS@%     trio[2]%@NL@%
  3633. %@AS@%     trio[3]%@NL@%
  3634. %@NL@%
  3635. %@CR:MQP61204@%%@4@%The elements of %@AS@%income%@AE@% are referred to as%@EH@%%@NL@%
  3636. %@NL@%
  3637. %@AS@%     income[1980]%@NL@%
  3638. %@AS@%     income[1981]%@NL@%
  3639. %@AS@%     income[1982]%@NL@%
  3640. %@AS@%     income[1983]%@NL@%
  3641. %@NL@%
  3642. %@CR:MQP61205@%%@4@%Each of the elements above has the data type declared for the array──%@AB@%Word%@AE@% in%@EH@%
  3643. the case of %@AS@%trio%@AE@% and %@AB@%LongInt%@AE@% in the case of %@AS@%income%@AE@%. You can refer to an
  3644. element in any context that is valid for a simple variable of the same type.
  3645. You can alter an element, pass it to a procedure, or assign its value to
  3646. another variable. The following statements are all valid:%@NL@%
  3647. %@NL@%
  3648. %@AS@%     trio[1] := 50;%@NL@%
  3649. %@AS@%     trio[2] := trio[1] DIV 2;%@NL@%
  3650. %@AS@%     Writeln( ' Result is : ', trio[1] + trio[2] );%@NL@%
  3651. %@NL@%
  3652. %@CR:MQP61206@%%@4@%The array index can be a variable as well as a constant. In fact, the power%@EH@%
  3653. of arrays in programming comes largely from the use of variable indexes. The
  3654. following code uses a loop variable to efficiently initialize a large array
  3655. of random numbers:%@NL@%
  3656. %@NL@%
  3657. %@AS@%     VAR%@NL@%
  3658. %@AS@%         i : Integer;%@NL@%
  3659. %@AS@%         big_arr : ARRAY[1..1000] OF Word;%@NL@%
  3660. %@AS@%     BEGIN%@NL@%
  3661. %@AS@%         FOR i := 1 TO 1000 DO%@NL@%
  3662. %@AS@%          big_arr[i] := Random(100);%@NL@%
  3663. %@NL@%
  3664. %@CR:MQP61207@%%@4@%To refer to an element of a multidimensional array, use the syntax%@EH@%%@NL@%
  3665. %@NL@%
  3666.      %@AI@%Name%@AE@%%@AB@% [%@AE@%%@AI@%Index%@AE@%%@AB@%, %@AE@%%@AI@%Index%@AE@% ... %@AB@%]%@AE@%%@NL@%
  3667. %@NL@%
  3668. %@CR:MQP61208@%%@4@%in which each %@AI@%Index%@AE@% is of the type and range of the corresponding index in%@EH@%
  3669. the array declaration. For example, the following code uses a nested loop to
  3670. efficiently initialize a two-dimensional array of random numbers:%@NL@%
  3671. %@NL@%
  3672. %@AS@%     VAR%@NL@%
  3673. %@AS@%         i, j : Integer;%@NL@%
  3674. %@AS@%         results : ARRAY[1..max_row, 1..max_col] OF Word;%@NL@%
  3675. %@AS@%     BEGIN%@NL@%
  3676. %@AS@%         FOR i := 1 TO max_row DO%@NL@%
  3677. %@AS@%          FOR j := 1 TO max_col DO%@NL@%
  3678. %@AS@%              results[i, j] := Random(100);%@NL@%
  3679. %@NL@%
  3680. %@CR:MQP61209@%%@4@%The %@AB@%{$R+}%@AE@% directive causes the program to check for out-of-bound indexes at%@EH@%
  3681. run time. Use the %@AB@%{$R+}%@AE@% directive during program development, but you may
  3682. want to turn the directive off (%@AB@%{$R-}%@AE@%) once you finish writing and
  3683. debugging. This lets the program run faster.%@NL@%
  3684. %@NL@%
  3685. %@NL@%
  3686. %@CR:MQP61300@%%@3@%%@AB@%6.1.3  Declaring Constant Arrays%@AE@%%@EH@%%@NL@%
  3687. %@NL@%
  3688. %@CR:MQP61301@%%@4@%To declare a constant array, first define the array type, then declare the%@EH@%
  3689. array and the initial values in a %@AB@%CONST%@AE@% statement. As shown in the examples
  3690. below, follow the array type with an equal sign (%@AB@%=%@AE@%) and a list of initial
  3691. values enclosed in parentheses. Separate elements with commas.
  3692. Multidimensional arrays require additional levels of parentheses. For
  3693. example, in a two-dimensional array, place parentheses around the values for
  3694. each row.%@NL@%
  3695. %@NL@%
  3696. %@AS@%     CONST%@NL@%
  3697. %@AS@%         max_row   = 5;%@NL@%
  3698. %@AS@%         grid_size = 2;%@NL@%
  3699. %@NL@%
  3700. %@AS@%     TYPE%@NL@%
  3701. %@AS@%         small_int_arr = ARRAY[1..max_row] OF Integer;%@NL@%
  3702. %@AS@%         hex_digit_arr = ARRAY[1..16] OF Char;%@NL@%
  3703. %@NL@%
  3704. %@AS@%         grid_xy = 1..grid_size;%@NL@%
  3705. %@AS@%         char_grid_type = ARRAY[grid_xy, grid_xy] OF Char;%@NL@%
  3706. %@NL@%
  3707. %@AS@%     CONST%@NL@%
  3708. %@AS@%         topic_index : small_int_arr = ( 11, 12, 13, 14, 15 );%@NL@%
  3709. %@AS@%         hex : hex_digit_arr =%@NL@%
  3710. %@AS@%             ( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',%@NL@%
  3711. %@AS@%               'A', 'B', 'C', 'D', 'E', 'F' );%@NL@%
  3712. %@AS@%         default_state : char_grid_type =%@NL@%
  3713. %@AS@%             ( ( 'a', 'j' ), ( 'W', 'T' ) );%@NL@%
  3714. %@NL@%
  3715. %@NL@%
  3716. %@CR:MQP61400@%%@3@%%@AB@%6.1.4  Passing Arrays as Parameters%@AE@%%@EH@%%@NL@%
  3717. %@NL@%
  3718. %@CR:MQP61401@%%@4@%This section describes how to pass an entire array to a procedure or%@EH@%
  3719. function. Note that there is no restriction on how you pass individual
  3720. elements, which can be passed just like simple variables of the same type.%@NL@%
  3721. %@NL@%
  3722. %@CR:MQP61402@%%@4@%To pass an array as a parameter, first define the array as an independent%@EH@%
  3723. type. Then declare the function to take a parameter of this predefined type,
  3724. and pass a value of this same type to the function. This requirement is
  3725. necessary for Pascal to ensure that the array is passed correctly.%@NL@%
  3726. %@NL@%
  3727. %@CR:MQP61403@%%@4@%The following code illustrates how to successfully pass an array:%@EH@%%@NL@%
  3728. %@NL@%
  3729. %@AS@%     TYPE%@NL@%
  3730. %@AS@%         res_arr = ARRAY[1..20] OF Integer;%@NL@%
  3731. %@AS@%     VAR%@NL@%
  3732. %@AS@%         results : res_arr; { results is a res_arr type variable }%@NL@%
  3733. %@NL@%
  3734. %@AS@%      { =====init_arr===== }%@NL@%
  3735. %@AS@%      { init_arr accepts a variable with res_arr type and initializes it }%@NL@%
  3736. %@AS@%     PROCEDURE init_arr( VAR new_arr : res_arr );%@NL@%
  3737. %@AS@%         BEGIN%@NL@%
  3738. %@AS@%         .%@NL@%
  3739. %@AS@%         .%@NL@%
  3740. %@AS@%         .%@NL@%
  3741. %@AS@%         END;%@NL@%
  3742. %@NL@%
  3743. %@AS@%     BEGIN%@NL@%
  3744. %@AS@%         { call init_arr, passing it the results variable%@NL@%
  3745.            %@AI@%which has type res_arr%@AE@%%@NL@%
  3746.          }%@NL@%
  3747. %@AS@%         init_arr( results );%@NL@%
  3748. %@NL@%
  3749. %@CR:MQP61404@%%@4@%You don't need to predefine a string type in order to pass a string.%@EH@%
  3750. However, if the Var-String Checking option (in the dialog box for Compiler
  3751. directives in the Options menu) is in effect (the default), the length of
  3752. the string you pass must match exactly the length of the string the
  3753. procedure expects. For example, if procedure %@AS@%print_str%@AE@% is declared as%@NL@%
  3754. %@NL@%
  3755. %@AS@%     PROCEDURE print_str ( data_str : STRING[20] );%@NL@%
  3756. %@NL@%
  3757. %@CR:MQP61405@%%@4@%then you can only pass strings of type %@AS@%STRING[20]%@AE@%.%@EH@%%@NL@%
  3758. %@NL@%
  3759. %@CR:MQP61406@%%@4@%If Var-String Checking is turned off, then you can pass strings to%@EH@%
  3760. parameters without regard to length. You can also pass variables of type
  3761. %@AB@%STRING%@AE@%.%@NL@%
  3762. %@NL@%
  3763. %@CR:MQP61407@%%@4@%Like all variables, arrays can be passed by value or by reference. When you%@EH@%
  3764. pass an array by value, the entire array is copied to the stack. This can
  3765. cause you to run out of stack memory quickly if you work with large arrays.%@NL@%
  3766. %@NL@%
  3767. %@NL@%
  3768. %@CR:MQP61500@%%@3@%%@AB@%6.1.5  Using the Debugger with Arrays%@AE@%%@EH@%%@NL@%
  3769. %@NL@%
  3770. %@CR:MQP61501@%%@4@%When you want to display an array during debugging, you can specify three%@EH@%
  3771. different kinds of Watch expressions:%@NL@%
  3772. %@NL@%
  3773. %@CR:MQP61502@%  1. The entire array. You can watch all the elements of an array simply by%@NL@%
  3774.      specifying the array's name. The Watch window displays array elements%@NL@%
  3775.      as a list of comma-delimited items enclosed in parentheses. You may%@NL@%
  3776.      need to scroll through the Watch window to see all of the elements.%@NL@%
  3777. %@NL@%
  3778.   2. Specific array elements. You can watch individual elements of an array%@NL@%
  3779.      by specifying either a constant or variable as an index. If you use a%@NL@%
  3780.      variable, then QuickPascal displays a different element whenever the%@NL@%
  3781.      variable changes.%@NL@%
  3782. %@NL@%
  3783.   3. A subset of the array elements (a "subarray"). You can specify a%@NL@%
  3784.      subarray by using the following syntax:%@NL@%
  3785. %@NL@%
  3786.      %@AI@%ArrayName%@AE@%%@AB@%[%@AE@%%@AI@% Index%@AE@%%@AB@%],%@AE@% %@AI@%Number%@AE@%%@NL@%
  3787. %@NL@%
  3788.      For example, %@AS@%a[4],5%@AE@% permits you to view the subarray %@AS@%a[4]%@AE@% to %@AS@%a[9]%@AE@%. You%@NL@%
  3789.      can also use a variable as the index of the first item.%@NL@%
  3790. %@NL@%
  3791. %@NL@%
  3792. %@CR:MQP62000@%%@2@%%@AB@%6.2  Records%@AE@%%@EH@%%@NL@%
  3793. %@NL@%
  3794. %@CR:MQP62001@%%@4@%A record is a collection of variables that can have different types. Each%@EH@%
  3795. variable within the record has a name to differentiate it from other
  3796. variables in the record. This name is called a "field." To access an item in
  3797. a record, you give both the record name and the field.%@NL@%
  3798. %@NL@%
  3799. %@CR:MQP62002@%%@4@%Records are common in practical applications. For example, consider a%@EH@%
  3800. program that maintains airplane reservations. For each reservation, there
  3801. are several relevant pieces of information: customer name, flight number,
  3802. date, and time. You can combine all of this information into a single
  3803. record.%@NL@%
  3804. %@NL@%
  3805. %@CR:MQP62003@%%@4@%Although you could keep track of the different data items in separate%@EH@%
  3806. variables, placing them together in a single record makes programs easier to
  3807. write and maintain. Furthermore, as you'll see in Chapter 10%@BO:   43fd9@%, "Binary
  3808. Files," records are convenient units of data to read and write to disk.%@NL@%
  3809. %@NL@%
  3810. %@NL@%
  3811. %@CR:MQP62100@%%@3@%%@AB@%6.2.1  Declaring Records%@AE@%%@EH@%%@NL@%
  3812. %@NL@%
  3813. %@CR:MQP62101@%%@4@%Declare a record with the following syntax. The record can form part of a%@EH@%
  3814. type definition or variable declaration.%@NL@%
  3815. %@NL@%
  3816.      %@AB@%RECORD%@AE@%%@NL@%
  3817.         %@AI@%FieldDeclarations%@AE@%%@NL@%
  3818.      %@AB@%END%@AE@%%@NL@%
  3819. %@NL@%
  3820. %@CR:MQP62102@%%@4@%In the syntax display above, %@AI@%FieldDeclarations%@AE@% is a variable declaration.%@EH@%
  3821. The variable name determines the name of the %@AI@%Field%@AE@% (see examples). You must
  3822. separate each field from the next with a semicolon.%@NL@%
  3823. %@NL@%
  3824. %@CR:MQP62103@%%@4@%The following lines show some simple record type definitions:%@EH@%%@NL@%
  3825. %@NL@%
  3826. %@AS@%     TYPE%@NL@%
  3827. %@AS@%         complex = RECORD%@NL@%
  3828. %@AS@%          x_real,%@NL@%
  3829. %@AS@%          y_imag : Real;%@NL@%
  3830. %@AS@%          END;%@NL@%
  3831. %@NL@%
  3832. %@AS@%         mail_rec = RECORD%@NL@%
  3833. %@AS@%             name   : STRING[20];%@NL@%
  3834. %@AS@%             street : STRING[25];%@NL@%
  3835. %@AS@%             city   : STRING[5];%@NL@%
  3836. %@AS@%             state  : STRING[2];%@NL@%
  3837. %@AS@%             zip    : LongInt;%@NL@%
  3838. %@AS@%             END;%@NL@%
  3839. %@NL@%
  3840. %@CR:MQP62104@%%@4@%Because of the highly structured nature of Pascal, each field can have any%@EH@%
  3841. data type. A field can be an array or even another record. When a record
  3842. appears as a field within another record, it is said to be "nested." For
  3843. example, the type %@AS@%mail_list_rec%@AE@% shown below contains %@AS@%last_deleted_rec%@AE@%,
  3844. which is another record, as one of its fields.%@NL@%
  3845. %@NL@%
  3846. %@AS@%     mail_list_rec = RECORD%@NL@%
  3847. %@AS@%         num_recs : Word;%@NL@%
  3848. %@AS@%         last_update,%@NL@%
  3849. %@AS@%         last_mailing : STRING;%@NL@%
  3850. %@AS@%         last_deleted_rec : mail_rec;%@NL@%
  3851. %@AS@%         END;%@NL@%
  3852. %@NL@%
  3853. %@CR:MQP62105@%%@4@%Arrays of records are common data types. For example, the following data%@EH@%
  3854. structure creates a table of the grades of students in a math class:%@NL@%
  3855. %@NL@%
  3856. %@AS@%     TYPE%@NL@%
  3857. %@AS@%         table_rows = 1..30;%@NL@%
  3858. %@AS@%         stu_rec = RECORD%@NL@%
  3859. %@AS@%              name : STRING [20];%@NL@%
  3860. %@AS@%              test1_score,%@NL@%
  3861. %@AS@%              test2_score,%@NL@%
  3862. %@AS@%              test3_score : Word;%@NL@%
  3863. %@AS@%              grade_pt : REAL;%@NL@%
  3864. %@AS@%              END;%@NL@%
  3865. %@NL@%
  3866. %@AS@%     VAR%@NL@%
  3867. %@AS@%         table : ARRAY[table_rows] OF stu_rec;%@NL@%
  3868. %@NL@%
  3869. %@NL@%
  3870. %@CR:MQP62200@%%@3@%%@AB@%6.2.2  Accessing Record Fields%@AE@%%@EH@%%@NL@%
  3871. %@NL@%
  3872. %@CR:MQP62201@%%@4@%To access an individual field of a record, you give both the name of the%@EH@%
  3873. record variable and the name of the field:%@NL@%
  3874. %@NL@%
  3875.      %@AI@%RecordName%@AE@%%@AB@%.%@AE@%%@AI@%FieldName%@AE@%%@NL@%
  3876. %@NL@%
  3877. %@CR:MQP62202@%%@4@%The result is a data object of the type declared for the field. You can use%@EH@%
  3878. the resulting item in any context that would be valid for an ordinary
  3879. variable of the same type.%@NL@%
  3880. %@NL@%
  3881. %@CR:MQP62203@%%@4@%Consider the following record type:%@EH@%%@NL@%
  3882. %@NL@%
  3883. %@AS@%     TYPE%@NL@%
  3884. %@AS@%         mail_rec = RECORD%@NL@%
  3885. %@AS@%             name   : STRING[20];%@NL@%
  3886. %@AS@%             street : STRING[25];%@NL@%
  3887. %@AS@%             city   : STRING[5];%@NL@%
  3888. %@AS@%             state  : STRING[2];%@NL@%
  3889. %@AS@%             zip    : LongInt;%@NL@%
  3890. %@AS@%             END;%@NL@%
  3891. %@AS@%         mail_array = ARRAY [1..max_mailing] OF mail_rec;%@NL@%
  3892. %@NL@%
  3893. %@AS@%     VAR%@NL@%
  3894. %@AS@%         my_mail : mail_rec;%@NL@%
  3895. %@AS@%         mailing : mail_array;%@NL@%
  3896. %@NL@%
  3897. %@CR:MQP62204@%%@4@%The following example assigns a string to the %@AS@%name%@AE@% field of the %@AS@%my_mail%@AE@%%@EH@%
  3898. record variable declared above.%@NL@%
  3899. %@NL@%
  3900. %@AS@%     my_mail.name := 'John Doe';%@NL@%
  3901. %@NL@%
  3902. %@CR:MQP62205@%%@4@%The expression %@AS@%my_mail.name%@AE@% is a string variable that can be assigned a%@EH@%
  3903. value or passed to a function, just like any other string variable. For
  3904. example, the following statement displays the name:%@NL@%
  3905. %@NL@%
  3906. %@AS@%     Writeln( 'Addressee name is ', my_mail.name );%@NL@%
  3907. %@NL@%
  3908. %@CR:MQP62206@%%@4@%The syntax gets a little more complicated when you refer to an item within%@EH@%
  3909. the array of records. For example, the following statement initializes the
  3910. %@AS@%name%@AE@% field of the third array element:%@NL@%
  3911. %@NL@%
  3912. %@AS@%     mailing[3].name := 'Hugo Bletch';%@NL@%
  3913. %@NL@%
  3914. %@CR:MQP62207@%%@4@%Consider how Pascal analyzes this expression. You can understand any complex%@EH@%
  3915. expression by following similar logic:%@NL@%
  3916. %@NL@%
  3917. %@CR:MQP62208@%  1. The symbol %@AS@%mailing%@AE@% is declared as an array of records.%@NL@%
  3918. %@NL@%
  3919.   2. The expression %@AS@%mailing[3]%@AE@% is therefore an individual record.%@NL@%
  3920.      Specifically, it is the third record of the array.%@NL@%
  3921. %@NL@%
  3922.   3. The expression %@AS@%mailing[3].name%@AE@% refers to the %@AS@%name%@AE@% field in the third%@NL@%
  3923.      record of the array. The result is a variable of type %@AS@%STRING[20]%@AE@%.%@NL@%
  3924. %@NL@%
  3925. %@CR:MQP62209@%%@4@%The data path to an object grows as you increase the levels of nesting. For%@EH@%
  3926. example, consider the definition of the %@AS@%mail_rec%@AE@% type above plus the
  3927. following additional statements:%@NL@%
  3928. %@NL@%
  3929. %@AS@%     TYPE%@NL@%
  3930. %@AS@%         MailArr = ARRAY[1..100] OF mail_rec;%@NL@%
  3931. %@AS@%     VAR%@NL@%
  3932. %@AS@%         mailing_list  : RECORD%@NL@%
  3933. %@AS@%             title     : STRING;%@NL@%
  3934. %@AS@%             addresses : MailArr;%@NL@%
  3935. %@AS@%             END;%@NL@%
  3936. %@NL@%
  3937. %@CR:MQP6220A@%%@4@%Given these declarations, you can access an individual name field as%@EH@%%@NL@%
  3938. %@NL@%
  3939. %@AS@%     mailing_list.addresses[5].name%@NL@%
  3940. %@NL@%
  3941. %@CR:MQP6220B@%%@4@%The next section shows a technique for shortening the length of such%@EH@%
  3942. expressions.%@NL@%
  3943. %@NL@%
  3944. %@NL@%
  3945. %@CR:MQP62300@%%@3@%%@AB@%6.2.3  Using the WITH Statement to Access Fields%@AE@%%@EH@%%@NL@%
  3946. %@NL@%
  3947. %@CR:MQP62301@%%@4@%While defining the full data path in a record makes your code more readable,%@EH@%
  3948. it also increases the length of the identifiers. The QuickPascal %@AB@%WITH%@AE@%
  3949. statement enables you to omit the name of a record variable from a block of
  3950. statements. It has the following syntax:%@NL@%
  3951. %@NL@%
  3952.      %@AB@%WITH %@AE@%%@AI@%RecordName%@AE@%%@AB@% DO %@AE@%%@AI@%Statement%@AE@%%@NL@%
  3953. %@NL@%
  3954. %@CR:MQP62302@%%@4@%The %@AI@%Statement%@AE@% following %@AB@%DO%@AE@% can refer to fields in %@AI@%RecordName%@AE@% directly. For%@EH@%
  3955. example, you can assign a string to the %@AS@%name%@AE@% field of record variable
  3956. %@AS@%my_mail%@AE@% with the following statement:%@NL@%
  3957. %@NL@%
  3958. %@AS@%     WITH my_mail DO%@NL@%
  3959. %@AS@%         name := 'John Doe';%@NL@%
  3960. %@NL@%
  3961. %@CR:MQP62303@%%@4@%To follow the %@AB@%DO%@AE@% keyword with more than one statement, use a %@AB@%BEGIN%@AE@%...%@AB@%END%@AE@%%@EH@%
  3962. statement block.%@NL@%
  3963. %@NL@%
  3964. %@CR:MQP62304@%%@4@%In the case of nested records, the %@AB@%WITH%@AE@% statement may contain a record name%@EH@%
  3965. modified by a field name. Always specify the outermost record first. For
  3966. example, suppose %@AS@%name%@AE@% is a field of %@AS@%mail_rec%@AE@%, which in turn is a field of
  3967. the record variable %@AS@%mail_list_rec%@AE@%. The following statement assigns a string
  3968. to the %@AS@%name%@AE@% field:%@NL@%
  3969. %@NL@%
  3970. %@AS@%     WITH mail_list_rec.mail_rec DO%@NL@%
  3971. %@AS@%         name := 'Hugo Bletch';%@NL@%
  3972. %@NL@%
  3973. %@NL@%
  3974. %@CR:MQP62400@%%@3@%%@AB@%6.2.4  Constant Records%@AE@%%@EH@%%@NL@%
  3975. %@NL@%
  3976. %@CR:MQP62401@%%@4@%To declare a constant record, first define the record type, then declare the%@EH@%
  3977. record and the initial value in a %@AB@%CONST%@AE@% statement. The initial value of a
  3978. record consists of the following syntax:%@NL@%
  3979. %@NL@%
  3980.      %@AB@%( %@AE@%%@AI@%FieldName%@AE@%%@AB@%: %@AE@%%@AI@%Constant%@AE@%%@AB@%;%@AE@% %@AI@%FieldName%@AE@% %@AB@%: %@AE@%%@AI@%Constant%@AE@% ... %@AB@%)%@AE@%%@NL@%
  3981. %@NL@%
  3982. %@CR:MQP62402@%%@4@%The initial value for each field follows the rules for its type. For%@EH@%
  3983. example, each row of an array initializer must be enclosed in parentheses.
  3984. In the case of nested records, additional levels of parentheses and fields
  3985. are required, as shown below.%@NL@%
  3986. %@NL@%
  3987. %@AS@%     TYPE%@NL@%
  3988. %@AS@%         complex = RECORD%@NL@%
  3989. %@AS@%             x_real,%@NL@%
  3990. %@AS@%             y_imag : Real;%@NL@%
  3991. %@AS@%             END;%@NL@%
  3992. %@AS@%         square_matrix = RECORD%@NL@%
  3993. %@AS@%             mat_size    : Byte;%@NL@%
  3994. %@AS@%             imag        : complex;%@NL@%
  3995. %@AS@%             determinant : Real;%@NL@%
  3996. %@AS@%             mat_x       : ARRAY[1..3, 1..3] OF Real;%@NL@%
  3997. %@AS@%             END;%@NL@%
  3998. %@AS@%     CONST%@NL@%
  3999. %@AS@%         origin  : complex = ( x_real : 0.0; y_imag : 0.0 );%@NL@%
  4000. %@AS@%         def_mat : square_matrix = (%@NL@%
  4001. %@AS@%             mat_size    : 3;%@NL@%
  4002. %@AS@%             imag        : ( x_real : 1.0; y_imag : 1.0 );%@NL@%
  4003. %@AS@%             determinant : 0.0;%@NL@%
  4004. %@AS@%             mat_x       :%@NL@%
  4005. %@AS@%                 ( (1.0, 1.0, 1.0),%@NL@%
  4006. %@AS@%                   (2.0, 2.0, 2.0),%@NL@%
  4007. %@AS@%                   (3.0, 3.0, 3.0)%@NL@%
  4008. %@AS@%                 )%@NL@%
  4009. %@AS@%             );%@NL@%
  4010. %@NL@%
  4011. %@NL@%
  4012. %@CR:MQP62500@%%@3@%%@AB@%6.2.5  Assigning Records to Record Variables%@AE@%%@EH@%%@NL@%
  4013. %@NL@%
  4014. %@CR:MQP62501@%%@4@%Pascal supports the use of the assignment operator (%@AB@%:=%@AE@%) to assign the value%@EH@%
  4015. of one record variable to another record. You can also assign one array to
  4016. another if you declare the array type as a field within a record.%@NL@%
  4017. %@NL@%
  4018. %@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@%
  4019. use the following statement to assign one record to another:%@NL@%
  4020. %@NL@%
  4021. %@AS@%     rec_a := rec_b;%@NL@%
  4022. %@NL@%
  4023. %@CR:MQP62503@%%@4@%As a further example, assume %@AS@%matrix1%@AE@% and %@AS@%matrix2%@AE@% are both records of the%@EH@%
  4024. same type, and that this type contains an array field %@AS@%mat_x%@AE@%. You can use
  4025. the following statement to assign one array field to another:%@NL@%
  4026. %@NL@%
  4027. %@AS@%     matrix1.mat_x := matrix2.mat_x%@NL@%
  4028. %@NL@%
  4029. %@NL@%
  4030. %@CR:MQP62600@%%@3@%%@AB@%6.2.6  Using the Debugger with Records%@AE@%%@EH@%%@NL@%
  4031. %@NL@%
  4032. %@CR:MQP62601@%%@4@%The Debug window displays the fields of a record as a list of data items%@EH@%
  4033. enclosed in parentheses. Appending ",R" to the name of a watched record when
  4034. it is put into the Debug window displays the names of the fields and their
  4035. values. A colon separates the name of a field and its current value with
  4036. this display format. You may need to scroll through the window to see all of
  4037. the fields in the record.%@NL@%
  4038. %@NL@%
  4039. %@NL@%
  4040. %@CR:MQP63000@%%@2@%%@AB@%6.3  Variant Records%@AE@%%@EH@%%@NL@%
  4041. %@NL@%
  4042. %@CR:MQP63001@%%@4@%A variant record lets you provide a variety of data formats for the same%@EH@%
  4043. area of memory. Whenever you refer to the variant record, you indicate which
  4044. format to use. This capability is useful in the following situations:%@NL@%
  4045. %@NL@%
  4046. %@CR:MQP63002@%  ■  You need flexibility within a general type of record. Suppose you want%@NL@%
  4047.      to create a record type to store data on each employee in a company.%@NL@%
  4048.      You'll want certain common fields, such as name, to apply to every%@NL@%
  4049.      employee. However, you may need to store different kinds of information%@NL@%
  4050.      on different kinds of employees.%@NL@%
  4051. %@NL@%
  4052.      Variant records provide the needed flexibility. Instead of including%@NL@%
  4053.      all possible fields for all possible employees in every record (which%@NL@%
  4054.      would waste memory), you can create fields specific to each subgroup of%@NL@%
  4055.      employees.%@NL@%
  4056. %@NL@%
  4057.   ■  You want to read data in one way and write it out in another way. While%@NL@%
  4058.      this situation is comparatively rare, it offers a perfect use for%@NL@%
  4059.      variant records. For example, you can simulate the behavior of%@NL@%
  4060.      microprocessors which permit the same register to be accessed either a%@NL@%
  4061.      byte at a time or a word at a time.%@NL@%
  4062. %@NL@%
  4063. %@NL@%
  4064. %@CR:MQP63100@%%@3@%%@AB@%6.3.1  Declaring Variant Records%@AE@%%@EH@%%@NL@%
  4065. %@NL@%
  4066. %@CR:MQP63101@%%@4@%The syntax for a variant record declaration is:%@EH@%%@NL@%
  4067. %@NL@%
  4068.      %@AB@%RECORD%@AE@%%@NL@%
  4069.         %@AI@%FieldDeclarations%@AE@%%@NL@%
  4070.         %@AB@%CASE %@AE@%«%@AI@%Tag%@AE@%%@AB@%:%@AE@%»%@AI@%TagType%@AE@% %@AB@%OF%@AE@%%@NL@%
  4071.         %@AI@%CaseDeclarations%@AE@%%@NL@%
  4072.         %@AB@%END%@AE@%%@NL@%
  4073. %@NL@%
  4074. %@CR:MQP63102@%%@4@%The %@AI@%FieldDeclarations%@AE@% make up the "fixed fields" of the record and are%@EH@%
  4075. optional. The %@AI@%Tag%@AE@% is an optional field that you can use to indicate which of
  4076. the cases (data formats) is active. Each %@AI@%CaseDeclaration%@AE@% has the following
  4077. format:%@NL@%
  4078. %@NL@%
  4079.      %@AI@%CaseLabel%@AE@%%@AB@%:  (%@AE@%%@AI@%FieldDeclarations%@AE@%%@AB@%)%@AE@%%@NL@%
  4080. %@NL@%
  4081. %@CR:MQP63103@%%@4@%Separate each %@AI@%CaseDeclaration%@AE@% with a semicolon. The %@AI@%Tag%@AE@% and each %@AI@%CaseLabel%@AE@%%@EH@%
  4082. must be of the %@AI@%TagType%@AE@%, which can be any valid ordinal type (such as an
  4083. integer or user-defined type).%@NL@%
  4084. %@NL@%
  4085. %@CR:MQP63104@%%@4@%Each case declares a different series of fields. However, each case is%@EH@%
  4086. overlaid in the same area of the record. Pascal allocates enough memory for
  4087. the case that has the largest total size. This area is called the "variant
  4088. portion" of the record. One case might use this area to store a string
  4089. field. Another might use it to store floating-point fields.%@NL@%
  4090. %@NL@%
  4091. %@CR:MQP63105@%%@4@%The following example shows a variant record that models the registers of%@EH@%
  4092. the 8086 processor:%@NL@%
  4093. %@NL@%
  4094. %@AS@%     TYPE%@NL@%
  4095. %@AS@%         regtype = (reg16, reg08);%@NL@%
  4096. %@AS@%         registers86 = RECORD%@NL@%
  4097. %@AS@%          CASE Integer OF%@NL@%
  4098. %@AS@%          0 : ( ax, bx, cx, dx, si, di, bp, sp, flags : Word; );%@NL@%
  4099. %@AS@%          1 : ( al, ah, bl, bh, cl, ch, dl, dh : Byte; );%@NL@%
  4100. %@AS@%          END;%@NL@%
  4101. %@NL@%
  4102. %@CR:MQP63106@%%@4@%This type definition allows you to access the same data either as one 16-bit%@EH@%
  4103. item, such as %@AS@%ax%@AE@%, or as two 8-bit items, such as %@AS@%al%@AE@% and %@AS@%ah%@AE@%.%@NL@%
  4104. %@NL@%
  4105. %@NL@%
  4106. %@CR:MQP63200@%%@3@%%@AB@%6.3.2  Accessing Variant Record Fields%@AE@%%@EH@%%@NL@%
  4107. %@NL@%
  4108. %@CR:MQP63201@%%@4@%You access all of the fields in the record the same way, regardless of%@EH@%
  4109. whether they are fixed fields or defined within the variant portion of the
  4110. record. (Consequently, the names of all fields in both the fixed and variant
  4111. portions must be unique.) In addition, if a tag field is declared, you can
  4112. set it to indicate which case is active.%@NL@%
  4113. %@NL@%
  4114. %@CR:MQP63202@%%@4@%For example (assuming the declaration of %@AS@%registers86%@AE@% at the end of the last%@EH@%
  4115. section), the following statements load data into %@AS@%al%@AE@% and %@AS@%ah%@AE@%, and then
  4116. display %@AS@%ax%@AE@%. Note that %@AS@%ax%@AE@% contains the same data as %@AS@%al%@AE@% and %@AS@%ah%@AE@% combined.%@NL@%
  4117. %@NL@%
  4118. %@AS@%     VAR%@NL@%
  4119. %@AS@%         my_regs : registers86;%@NL@%
  4120. %@AS@%     BEGIN%@NL@%
  4121. %@AS@%         my_regs.ah := $FF;%@NL@%
  4122. %@AS@%         my_regs.al := $10;%@NL@%
  4123. %@AS@%         Writeln ('AX now contains', my_regs.ax);%@NL@%
  4124. %@NL@%
  4125. %@CR:MQP63203@%%@4@%For another example, a simplified variant record scheme for the personnel%@EH@%
  4126. system of a company might look like this:%@NL@%
  4127. %@NL@%
  4128. %@AS@%     TYPE%@NL@%
  4129. %@AS@%         clearance = (topsecret, secret, medium, low, known_spy);%@NL@%
  4130. %@AS@%         drink_type = ( martini, wine, champagne, teetotaler );%@NL@%
  4131. %@AS@%         games_type = ( tennis, squash, golf );%@NL@%
  4132. %@AS@%         title = ( secretary, engineer, exec );%@NL@%
  4133. %@NL@%
  4134. %@AS@%         emp_rec = RECORD%@NL@%
  4135. %@AS@%              name : STRING[20];%@NL@%
  4136. %@AS@%              CASE job : title OF%@NL@%
  4137. %@AS@%              secretary : ( wpm, steno : Word );%@NL@%
  4138. %@AS@%              engineer : ( security : clearance; IQ : Byte );%@NL@%
  4139. %@AS@%              exec : ( beverage : drink_type;%@NL@%
  4140. %@AS@%                    pastime : games_type;%@NL@%
  4141. %@AS@%                    washroom_code : LongInt );%@NL@%
  4142. %@AS@%              END;%@NL@%
  4143. %@AS@%     VAR%@NL@%
  4144. %@AS@%         new_emp : emp_rec;%@NL@%
  4145. %@NL@%
  4146. %@CR:MQP63204@%%@4@%The following code initializes the %@AS@%new_emp%@AE@% record variable for a recently%@EH@%
  4147. hired engineer:%@NL@%
  4148. %@NL@%
  4149. %@AS@%     new_emp.name := 'Jane Eyre';%@NL@%
  4150. %@AS@%     new_emp.job := engineer;%@NL@%
  4151. %@AS@%     new_emp.security := secret;%@NL@%
  4152. %@AS@%     new_emp.IQ := 120;%@NL@%
  4153. %@NL@%
  4154. %@CR:MQP63205@%%@4@%Now suppose that Jane Eyre is promoted into management. The old data%@EH@%
  4155. relevant to engineers (security clearance and IQ) is no longer relevant to
  4156. Jane in her new position. Fortunately, the variant record type lets you
  4157. reuse this same area of memory to put in data relevant to managers.%@NL@%
  4158. %@NL@%
  4159. %@CR:MQP63206@%%@4@%First, the program makes Jane's promotion official:%@EH@%%@NL@%
  4160. %@NL@%
  4161. %@AS@%     new_emp.job := exec;%@NL@%
  4162. %@NL@%
  4163. %@CR:MQP63207@%%@4@%The program then enters Jane's new data. To accommodate Jane's rise up the%@EH@%
  4164. corporate ladder, the program records her favorite drink, favorite pastime,
  4165. and key code for the executive washroom. This information is overwritten
  4166. onto the engineer data, which is no longer needed.%@NL@%
  4167. %@NL@%
  4168. %@AS@%     new_emp.beverage := martini;%@NL@%
  4169. %@AS@%     new_emp.pastime := tennis;%@NL@%
  4170. %@AS@%     new_emp.washroom_code := 12345007;%@NL@%
  4171. %@NL@%
  4172. %@NL@%
  4173. %@CR:MQP70000@%%@1@%%@AB@%Chapter 7  Units%@AE@%%@EH@%%@NL@%
  4174. ───────────────────────────────────────────────────────────────────────────%@NL@%
  4175. %@NL@%
  4176. %@CR:MQP70001@%%@4@%Units extend the usefulness of QuickPascal by giving your programs access to%@EH@%
  4177. additional declarations and procedures. A "unit" is defined as a related
  4178. collection of such declarations and procedures. Referencing a unit's name at
  4179. the beginning of a program gives you access to that unit's contents just as
  4180. though they were a part of standard Pascal. QuickPascal comes with several
  4181. predefined (or "standard") units, and you can also write your own.%@NL@%
  4182. %@NL@%
  4183. %@CR:MQP70002@%%@4@%This chapter explains both how to use QuickPascal standard units and how to%@EH@%
  4184. create your own units.%@NL@%
  4185. %@NL@%
  4186. %@NL@%
  4187. %@CR:MQP71000@%%@2@%%@AB@%7.1  Understanding Units%@AE@%%@EH@%%@NL@%
  4188. %@NL@%
  4189. %@CR:MQP71001@%%@4@%If you've done much programming in another language, you're probably%@EH@%
  4190. familiar with libraries. Libraries usually provide specialized routines not
  4191. normally part of the language. Pascal units work on a similar concept but
  4192. have a broader scope and application. They contain not only procedures and
  4193. functions but also variables, constants, and type declarations. In addition,
  4194. a unit can execute some code when the program starts and do anything a
  4195. program can, like open files or get user input. These are important
  4196. differences from libraries in another programming language.%@NL@%
  4197. %@NL@%
  4198. %@CR:MQP71002@%%@4@%Once you tell QuickPascal that your program uses a particular unit, you can%@EH@%
  4199. access the procedures, functions, and declarations defined in that unit just
  4200. as you would any standard procedure, function, or declaration.%@NL@%
  4201. %@NL@%
  4202. %@CR:MQP71003@%%@4@%Units effectively extend the portion of a program between the header and the%@EH@%
  4203. main program body──the area where all the declarations appear. Instead of
  4204. writing a tremendous number of declarations, procedures, and functions, you
  4205. can use a unit and get the same results.%@NL@%
  4206. %@NL@%
  4207. %@CR:MQP71004@%%@4@%If you use some of your own procedures repeatedly, you can create a custom%@EH@%
  4208. unit and make the procedures available to all your programs. And, rewriting
  4209. large programs to use units removes some of the constraints of the 64K
  4210. segment limit. Each unit gets its own segment, so creating just one unit
  4211. doubles your programming space. Programs can use up to 81 units.%@NL@%
  4212. %@NL@%
  4213. %@CR:MQP71005@%%@4@%QuickPascal standard units broaden your programs' general capabilities; the%@EH@%
  4214. custom units you write provide any specific functionality you need.%@NL@%
  4215. %@NL@%
  4216. %@NL@%
  4217. %@CR:MQP72000@%%@2@%%@AB@%7.2  Using Units in a Program%@AE@%%@EH@%%@NL@%
  4218. %@NL@%
  4219. %@CR:MQP72001@%%@4@%You access a unit by adding the %@AB@%USES%@AE@% statement and the unit's name under the%@EH@%
  4220. %@AB@%PROGRAM%@AE@% declaration. For example, the lines%@NL@%
  4221. %@NL@%
  4222. %@AS@%     USES%@NL@%
  4223. %@AS@%         Crt, Dos;%@NL@%
  4224. %@NL@%
  4225. %@CR:MQP72002@%%@4@%let you use any of the procedures defined in either the %@AS@%Crt%@AE@% or %@AS@%Dos%@AE@% units in%@EH@%
  4226. your program, just as you would any local procedure. Any variables,
  4227. constants, or types declared in the unit are available to your program. (If
  4228. you write programs that need many variables or constants, declaring them in
  4229. a custom unit can simplify your main program and make debugging easier.)%@NL@%
  4230. %@NL@%
  4231. %@CR:MQP72003@%%@4@%Here's a more complete example that shows a unit in context:%@EH@%%@NL@%
  4232. %@NL@%
  4233. %@AS@%     PROGRAM lil_unit_test;%@NL@%
  4234. %@AS@%     USES%@NL@%
  4235. %@AS@%         Crt;%@NL@%
  4236. %@NL@%
  4237. %@AS@%     BEGIN%@NL@%
  4238. %@AS@%         Write( 'Press any key to end' );%@NL@%
  4239. %@AS@%         REPEAT  UNTIL KeyPressed;%@NL@%
  4240. %@AS@%     END.%@NL@%
  4241. %@NL@%
  4242. %@CR:MQP72004@%%@4@%Once you put the unit in the %@AB@%USES%@AE@% list, you're free to use its contents just%@EH@%
  4243. like any other Pascal procedures, functions, and declarations.%@NL@%
  4244. %@NL@%
  4245. %@NL@%
  4246. %@CR:MQP73000@%%@2@%%@AB@%7.3  Standard QuickPascal Units%@AE@%%@EH@%%@NL@%
  4247. %@NL@%
  4248. %@CR:MQP73001@%%@4@%QuickPascal comes with several standard units. They enhance your control%@EH@%
  4249. over the screen and text, DOS routines, printer use, and graphics.
  4250. QuickPascal automatically inserts one other standard unit, %@AB@%System%@AE@%, into
  4251. every program you compile. It supplies all of the standard procedures and
  4252. functions.%@NL@%
  4253. %@NL@%
  4254. %@CR:MQP73002@%%@4@%QuickPascal standard units include the following:%@EH@%%@NL@%
  4255. %@NL@%
  4256. %@CR:MQP73003@%%@AB@%Unit name                   Description%@AE@%%@NL@%
  4257. %@NL@%
  4258. %@AB@%Crt%@AE@%                         Handles keyboard input, screen/window%@NL@%
  4259.                             management, color selection, and cursor control.%@NL@%
  4260. %@NL@%
  4261. %@AB@%Dos%@AE@%                         Manipulates DOS files and directories, and%@NL@%
  4262.                             performs other DOS functions.%@NL@%
  4263. %@NL@%
  4264. %@AB@%Printer%@AE@%                     Gives programs access to a printer.%@NL@%
  4265. %@NL@%
  4266. %@AB@%MSGraph%@AE@%                     Creates graphics and displays text in different%@NL@%
  4267.                             sizes and type styles.%@NL@%
  4268. %@NL@%
  4269. %@AB@%System%@AE@%                      Contains the run-time system including the%@NL@%
  4270.                             QuickPascal standard procedures and functions.%@NL@%
  4271.                             This unit is automatically used by all%@NL@%
  4272.                             QuickPascal programs; you do not need to%@NL@%
  4273.                             explicitly declare it.%@NL@%
  4274. %@NL@%
  4275. %@CR:MQP73004@%%@4@%If you consistently use procedures not available in the standard units,%@EH@%
  4276. consider creating your own unit. Like a program, a custom unit can reference
  4277. other units. Both types of units──standard and custom──add power and
  4278. flexibility to your programs.%@NL@%
  4279. %@NL@%
  4280. %@NL@%
  4281. %@CR:MQP74000@%%@2@%%@AB@%7.4  Creating Your Own Units%@AE@%%@EH@%%@NL@%
  4282. %@NL@%
  4283. %@CR:MQP74001@%%@4@%QuickPascal standard units supply most of the procedures you commonly need.%@EH@%
  4284. Yet you may need a special function repeatedly or want to initialize a large
  4285. number of variables, constants, or data types. Or you may wish to share
  4286. procedures with other programmers. In any case, a convenient solution is to
  4287. write your own unit.%@NL@%
  4288. %@NL@%
  4289. %@NL@%
  4290. %@CR:MQP74100@%%@3@%%@AB@%7.4.1  Writing a New Unit%@AE@%%@EH@%%@NL@%
  4291. %@NL@%
  4292. %@CR:MQP74101@%%@4@%QuickPascal units look similar to other Pascal programs, with the following%@EH@%
  4293. differences:%@NL@%
  4294. %@NL@%
  4295. %@CR:MQP74102@%  ■  Units begin with a different keyword.%@NL@%
  4296. %@NL@%
  4297.   ■  An %@AB@%INTERFACE%@AE@% section indicates what the program using the unit can%@NL@%
  4298.      access.%@NL@%
  4299. %@NL@%
  4300.   ■  An %@AB@%IMPLEMENTATION%@AE@% section defines any procedures and functions in your%@NL@%
  4301.      unit.%@NL@%
  4302. %@NL@%
  4303. %@CR:MQP74110@%%@4@%%@AB@%Beginning a Unit%@AE@%%@EH@%%@NL@%
  4304. %@NL@%
  4305. %@CR:MQP74111@%%@4@%Just as any program begins with the keyword %@AB@%PROGRAM%@AE@%, every unit begins with%@EH@%
  4306. a %@AB@%UNIT%@AE@% keyword:%@NL@%
  4307. %@NL@%
  4308. %@AS@%     UNIT new_unit;%@NL@%
  4309. %@NL@%
  4310. %@CR:MQP74112@%%@4@%The %@AB@%UNIT%@AE@% keyword tells QuickPascal to compile the file into a unit rather%@EH@%
  4311. than an executable program. The compiled unit receives the same name as its
  4312. source file, with the .QPU extension added. Unit source files usually keep
  4313. the .PAS extension.%@NL@%
  4314. %@NL@%
  4315. %@CR:MQP74120@%%@4@%%@AB@%Interface Portion%@AE@%%@EH@%%@NL@%
  4316. %@NL@%
  4317. %@CR:MQP74121@%%@4@%Everything in the next section, the %@AB@%INTERFACE%@AE@% portion of the unit, becomes%@EH@%
  4318. "public" information to any programs that use the unit. It includes any
  4319. units needed by this unit; the declarations of any public variables,
  4320. constants, or data types; and the calling format for any procedures or
  4321. functions (including declarations of all parameters). The actual code for
  4322. the procedures and functions comes later.%@NL@%
  4323. %@NL@%
  4324. %@CR:MQP74122@%%@4@%Consider the following sample %@AB@%INTERFACE%@AE@% section:%@EH@%%@NL@%
  4325. %@NL@%
  4326. %@AS@%     INTERFACE  { Public information }%@NL@%
  4327. %@NL@%
  4328. %@AS@%     USES%@NL@%
  4329. %@AS@%         Crt;%@NL@%
  4330. %@AS@%     CONST%@NL@%
  4331. %@AS@%         days_per_year = 365;%@NL@%
  4332. %@NL@%
  4333. %@AS@%     PROCEDURE center_line( message : STRING );%@NL@%
  4334. %@AS@%     FUNCTION cube( num : Real ) : Real;%@NL@%
  4335. %@NL@%
  4336. %@CR:MQP74123@%%@4@%These lines tell QuickPascal that this unit uses the standard %@AB@%Crt%@AE@% unit,%@EH@%
  4337. establishes the constant %@AS@%days_per_year%@AE@%, and makes one procedure
  4338. (%@AS@%center_line%@AE@%) and one function (%@AS@%cube%@AE@%) publicly available.%@NL@%
  4339. %@NL@%
  4340. %@CR:MQP74130@%%@4@%%@AB@%Implementation Portion%@AE@%%@EH@%%@NL@%
  4341. %@NL@%
  4342. %@CR:MQP74131@%%@4@%The second part of a unit, the %@AB@%IMPLEMENTATION%@AE@% portion, defines the%@EH@%
  4343. procedures given in the %@AB@%INTERFACE%@AE@% portion and any data necessary to
  4344. implement those procedures. This data may include any new definitions of
  4345. variables, constants, types, labels, and support procedures (procedures that
  4346. assist the primary procedures). The complete code for every %@AB@%PROCEDURE%@AE@% or
  4347. %@AB@%FUNCTION%@AE@% declared in the %@AB@%INTERFACE%@AE@% section must appear in the %@AB@%IMPLEMENTATION%@AE@%
  4348. section.%@NL@%
  4349. %@NL@%
  4350. %@CR:MQP74132@%%@4@%The following %@AB@%IMPLEMENTATION%@AE@% section includes both a new variable and a%@EH@%
  4351. support function:%@NL@%
  4352. %@NL@%
  4353. %@AS@%     IMPLEMENTATION%@NL@%
  4354. %@AS@%     { Private information available only to new_unit }%@NL@%
  4355. %@NL@%
  4356. %@AS@%     VAR%@NL@%
  4357. %@AS@%         back : Word;%@NL@%
  4358. %@NL@%
  4359. %@AS@%     FUNCTION  cube( num : Real ) : Real;%@NL@%
  4360. %@NL@%
  4361. %@AS@%     VAR%@NL@%
  4362. %@AS@%         temp : Real;%@NL@%
  4363. %@AS@%     BEGIN%@NL@%
  4364. %@AS@%         temp := Sqr( num );%@NL@%
  4365. %@AS@%         cube := temp * num;%@NL@%
  4366. %@AS@%     END;%@NL@%
  4367. %@NL@%
  4368. %@AS@%     FUNCTION calc_start( message : STRING ) : %@AS@%Integer;%@NL@%
  4369. %@AS@%     BEGIN%@NL@%
  4370. %@AS@%         calc_start := (80 - Length( message )) DIV 2;%@NL@%
  4371. %@AS@%     END;%@NL@%
  4372. %@NL@%
  4373. %@AS@%     PROCEDURE center_line( message : STRING );%@NL@%
  4374. %@AS@%     BEGIN%@NL@%
  4375. %@AS@%         GotoXY( calc_start( message ), WhereY );%@NL@%
  4376. %@AS@%         Writeln( message );%@NL@%
  4377. %@AS@%     END;%@NL@%
  4378. %@NL@%
  4379. %@AS@%     { Initialization part }%@NL@%
  4380. %@AS@%     BEGIN%@NL@%
  4381. %@AS@%         Writeln( 'What background color would you like ?' );%@NL@%
  4382. %@AS@%         Write( '(0..7) :' );%@NL@%
  4383. %@AS@%         Readln( back );%@NL@%
  4384. %@AS@%         TextBackground( back );%@NL@%
  4385. %@AS@%         ClrScr;%@NL@%
  4386. %@AS@%     END.%@NL@%
  4387. %@NL@%
  4388. %@CR:MQP74133@%%@4@%In QuickPascal, %@AB@%VAR%@AE@%, %@AB@%CONST%@AE@%, %@AB@%PROCEDURE%@AE@%, and %@AB@%FUNCTION%@AE@% declarations may come%@EH@%
  4389. in any order. However, you must  declare supporting procedures and
  4390. functions──in this case the %@AS@%calc_start%@AE@% function, called by the %@AS@%center_line%@AE@%
  4391. procedure──prior to calling them from within another procedure. Be sure to
  4392. include the definition for every procedure listed in the %@AB@%INTERFACE%@AE@% portion
  4393. of the program. Omitting any definition causes an %@AS@%Unsatisfied forward%@AE@%
  4394. %@AS@%reference%@AE@% error.%@NL@%
  4395. %@NL@%
  4396. %@CR:MQP74134@%%@4@%Although the compiler does not require you to list each procedure's%@EH@%
  4397. parameters (as it did in the %@AB@%INTERFACE%@AE@% portion), it is generally considered
  4398. good programming practice to do so. Keep in mind that if you do repeat the
  4399. parameters, they must exactly match the parameters listed in the %@AB@%INTERFACE%@AE@%
  4400. portion.%@NL@%
  4401. %@NL@%
  4402. %@CR:MQP74140@%%@4@%%@AB@%Viewing the Entire Unit%@AE@%%@EH@%%@NL@%
  4403. %@NL@%
  4404. %@CR:MQP74141@%%@4@%Together, the three previous examples form a complete unit. A program that%@EH@%
  4405. uses %@AS@%new_unit%@AE@% gets access to the constant %@AS@%days_per_year%@AE@%, the procedure
  4406. %@AS@%center_line%@AE@%, and the function %@AS@%cube%@AE@%. However, the program cannot access the
  4407. %@AS@%calc_start%@AE@% function or the %@AS@%temp%@AE@% variable because they appear in the
  4408. %@AB@%IMPLEMENTATION%@AE@% section; that section remains entirely "hidden" to the
  4409. program using the unit.%@NL@%
  4410. %@NL@%
  4411. %@CR:MQP74142@%%@4@%When you finish writing a unit, save the source code with the unit's name%@EH@%
  4412. and the .PAS extension. The next step, compiling the unit, is discussed in
  4413. the following section.%@NL@%
  4414. %@NL@%
  4415. %@NL@%
  4416. %@CR:MQP74200@%%@3@%%@AB@%7.4.2  Compiling a Unit%@AE@%%@EH@%%@NL@%
  4417. %@NL@%
  4418. %@CR:MQP74201@%%@4@%You compile a unit in the same manner you compile a program. Choose the%@EH@%
  4419. Compile File command on the Make menu. If your code contains errors that
  4420. prevent the unit from compiling, QuickPascal displays an error message. When
  4421. you remove the message, the cursor appears at the point QuickPascal detected
  4422. the error. Correct the error and repeat the process until the unit compiles.%@NL@%
  4423. %@NL@%
  4424. %@CR:MQP74202@%%@4@%Alternately, you can compile the main program and a new unit in one step by%@EH@%
  4425. choosing the Rebuild Main File command on the Make menu (or specify the /R
  4426. option if you compile from the QPL command line). Again, if QuickPascal
  4427. encounters any errors, the compilation halts and an error message appears.
  4428. You must compile all of the custom units a program references before you can
  4429. compile the main program.%@NL@%
  4430. %@NL@%
  4431. %@CR:MQP74203@%%@4@%Once your unit compiles properly, you can use it in any of your programs%@EH@%
  4432. just as you would use any of the standard units. If you change a program
  4433. that uses a custom unit, you need to recompile only that program (and not
  4434. the unit). However, if you change the unit itself, you may need to recompile
  4435. both the unit and the program. The Build Main File and Rebuild Main File
  4436. commands on the Make menu simplify this task.%@NL@%
  4437. %@NL@%
  4438. %@CR:MQP74204@%%@4@%The Build Main File command recompiles all the source files that changed%@EH@%
  4439. since the last Build Main File command was executed. Rebuild Main File
  4440. recompiles the program and all of its associated custom units, regardless of
  4441. whether anything changed. See the QP Advisor or "Compiling a Multiple-Module
  4442. Program" in Chapter 3 of %@AI@%Up and Running%@AE@% for a step-by-step approach to
  4443. compiling.%@NL@%
  4444. %@NL@%
  4445. %@NL@%
  4446. %@CR:MQP74300@%%@3@%%@AB@%7.4.3  Tips for Programming with Units%@AE@%%@EH@%%@NL@%
  4447. %@NL@%
  4448. %@CR:MQP74301@%%@4@%When you program with units, avoid using identifiers with the same name in%@EH@%
  4449. different units and circular references between units.%@NL@%
  4450. %@NL@%
  4451. %@CR:MQP74310@%%@4@%%@AB@%Identifiers with the Same Name%@AE@%%@EH@%%@NL@%
  4452. %@NL@%
  4453. %@CR:MQP74311@%%@4@%When two or more units contain identifiers (such as constant or procedure%@EH@%
  4454. names) that share the same name, the identifier "belongs" to the unit most
  4455. recently used. QuickPascal uses units in the order they appear in the %@AB@%USES%@AE@%
  4456. statement.%@NL@%
  4457. %@NL@%
  4458. %@CR:MQP74312@%%@4@%To avoid any confusion, you can reference an identifier in a manner similar%@EH@%
  4459. to referencing fields in records using this syntax:%@NL@%
  4460. %@NL@%
  4461.      %@AI@%UnitName%@AE@%%@AB@%.%@AE@%%@AI@%Identifier%@AE@%%@NL@%
  4462. %@NL@%
  4463. %@CR:MQP74313@%%@4@%For example, if you have a %@AS@%ClrScr%@AE@% procedure called SCRSTUFF.QPU, you can%@EH@%
  4464. reference it in your code as %@AS@%ScrStuff.ClrScr%@AE@% in a unit, and the standard
  4465. %@AB@%ClrScr%@AE@% can be referenced as %@AS@%Crt.ClrScr%@AE@%. Then the order of the units in the
  4466. %@AB@%USES%@AE@% declaration becomes irrelevant.%@NL@%
  4467. %@NL@%
  4468. %@CR:MQP74320@%%@4@%%@AB@%Circular Referencing%@AE@%%@EH@%%@NL@%
  4469. %@NL@%
  4470. %@CR:MQP74321@%%@4@%QuickPascal permits two units to reference each other. UNIT_A can use%@EH@%
  4471. UNIT_B, and UNIT_B can use UNIT_A. However, QuickPascal does not support
  4472. circular referencing between three or more units. QuickPascal won't compile
  4473. a program in which UNIT_A uses UNIT_B which uses UNIT_C which uses UNIT_A
  4474. (an A-B-C-A loop). Careful planning can avoid problems with circular
  4475. referencing.%@NL@%
  4476. %@NL@%
  4477. %@CR:MQP74322@%%@4@%The order of the units listed after the %@AB@%USES%@AE@% declaration is not important%@EH@%
  4478. unless their procedures have the same names, or the initialization code in
  4479. one unit interferes with the initialization code in another unit.%@NL@%
  4480. %@NL@%
  4481. %@NL@%
  4482. ───────────────────────────────────────────────────────────────────────────%@NL@%
  4483. %@CR:MQPP2000@%%@1@%%@AB@%Part 2  Programming Topics%@AE@%%@EH@%%@NL@%
  4484. %@NL@%
  4485. %@CR:MQPP2003@%%@4@%Part 2 of %@AI@%Pascal by Example%@AE@% assumes you either have read Part 1, "Pascal%@EH@%
  4486. Basics," or already know Pascal's basic concepts. Part 2 covers more
  4487. advanced programming concepts that give your programs additional
  4488. flexibility. Topics include enhancing keyboard and screen control, saving
  4489. and extracting data from files, and using pointers. The final chapter is
  4490. devoted entirely to advanced topics that experienced programmers may find
  4491. particularly interesting.%@NL@%
  4492. %@NL@%
  4493. %@CR:MQPP2004@%%@4@%While Part 1 was designed to be read sequentially, this part is much more%@EH@%
  4494. topical. You may read the chapters in any order. If you're using %@AI@%Pascal by%@AE@%
  4495. %@AI@%Example%@AE@% to learn Pascal, however, consider reading the chapter on text files
  4496. before you try working with binary files.%@NL@%
  4497. %@NL@%
  4498. %@NL@%
  4499. %@CR:MQP80000@%%@1@%%@AB@%Chapter 8  The Keyboard and Screen%@AE@%%@EH@%%@NL@%
  4500. ───────────────────────────────────────────────────────────────────────────%@NL@%
  4501. %@NL@%
  4502. %@CR:MQP80001@%%@4@%Virtually all programs receive or send out information in some way, perhaps%@EH@%
  4503. accepting it from the keyboard or a file, perhaps printing it to the screen
  4504. or a printer. QuickPascal supports all of the input and output features of
  4505. standard Pascal and includes a unit specifically designed to enhance your
  4506. programs' appearance and ease of use.%@NL@%
  4507. %@NL@%
  4508. %@CR:MQP80002@%%@4@%This chapter contains two parts. The first covers the basics of Pascal input%@EH@%
  4509. and output and how to format output. The second part introduces the %@AB@%Crt%@AE@% unit
  4510. and how to use it to refine control of both the keyboard and the screen.%@NL@%
  4511. %@NL@%
  4512. %@NL@%
  4513. %@CR:MQP81000@%%@2@%%@AB@%8.1  Basic Input and Output%@AE@%%@EH@%%@NL@%
  4514. %@NL@%
  4515. %@CR:MQP81001@%%@4@%Pascal provides the %@AB@%Read%@AE@% and %@AB@%Readln%@AE@% procedures for input and the %@AB@%Write%@AE@% and%@EH@%
  4516. %@AB@%Writeln%@AE@% procedures for output. These procedures can handle both single data
  4517. items and lists of items separated by commas. All four use similar syntax:%@NL@%
  4518. %@NL@%
  4519.      %@AB@%Read(%@AE@%«%@AI@%FileName%@AE@%%@AB@%,%@AE@% » %@AI@%InputVariable%@AE@%%@AB@%) %@AE@%«%@AB@%, %@AE@%%@AI@%InputVariable%@AE@%...»%@NL@%
  4520. %@NL@%
  4521. %@CR:MQP81002@%%@4@%and%@EH@%%@NL@%
  4522. %@NL@%
  4523.      %@AB@%Write(%@AE@%«%@AI@%FileName%@AE@%%@AB@%,%@AE@% » %@AI@%OutputVariable%@AE@% «%@AB@%:%@AE@% %@AI@%Width%@AE@%«:%@AI@%Decimals%@AE@%»»%@NL@%
  4524.         «%@AB@%,%@AE@%%@AI@%OutputVariable%@AE@% « %@AB@%:%@AE@%%@AI@%Width%@AE@%«%@AB@%:%@AE@%%@AI@%Decimals%@AE@%»»»%@AB@%)%@AE@%%@NL@%
  4525. %@NL@%
  4526. %@CR:MQP81003@%%@4@%where %@AI@%FileName%@AE@% optionally refers to a disk file or device (such as a printer%@EH@%
  4527. or a modem), and %@AI@%Width%@AE@% and %@AI@%Decimals%@AE@% refer to formatting information. Without
  4528. %@AI@%FileName%@AE@%, %@AB@%Read%@AE@% accepts data from the standard input device (usually the
  4529. keyboard) and %@AB@%Write%@AE@% sends data to the standard output device (usually the
  4530. screen).%@NL@%
  4531. %@NL@%
  4532. %@CR:MQP81004@%%@4@%If either %@AB@%Read%@AE@% or %@AB@%Write%@AE@% encounters an error, the program terminates with a%@EH@%
  4533. run-time error message. You can include the %@AB@%{$I-}%@AE@% compiler directive in your
  4534. program if you want your program to continue despite %@AB@%Read%@AE@% or %@AB@%Write%@AE@% run-time
  4535. errors.%@NL@%
  4536. %@NL@%
  4537. %@CR:MQP81005@%%@4@%If you choose to use the %@AB@%{$I-}%@AE@% compiler directive, you need to call the%@EH@%
  4538. function %@AB@%IOResult%@AE@% immediately after each input or output operation. The
  4539. value returned by %@AB@%IOResult%@AE@% indicates whether an error occurred. QuickPascal
  4540. ignores any input or output attempts after an error, unless you call
  4541. %@AB@%IOResult%@AE@%.%@NL@%
  4542. %@NL@%
  4543. %@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@%
  4544. statements. Section 8.2%@BO:   3a5eb@% goes into the formatting details (of %@AI@%Width%@AE@% and
  4545. %@AI@%Decimals%@AE@%). For further information on using %@AB@%Read%@AE@% and %@AB@%Write%@AE@% with data files
  4546. and other devices (by using %@AI@%FileName%@AE@%), read Chapter 9%@BO:   3efa5@%, "Text Files," and
  4547. Chapter 10, "Binary Files."%@NL@%
  4548. %@NL@%
  4549. %@NL@%
  4550. %@CR:MQP81100@%%@3@%%@AB@%8.1.1  Read and Readln Procedures%@AE@%%@EH@%%@NL@%
  4551. %@NL@%
  4552. %@CR:MQP81101@%%@4@%The %@AB@%Read%@AE@% and %@AB@%Readln%@AE@% procedures place data into one or more "input%@EH@%
  4553. variables." Most commonly, %@AB@%Read%@AE@% and %@AB@%Readln%@AE@% receive their input from the
  4554. keyboard or a data file.%@NL@%
  4555. %@NL@%
  4556. %@CR:MQP81102@%%@4@%The input variables must belong to one of the predefined data types (except%@EH@%
  4557. Boolean) or a subrange type you defined, and they must be of a type that can
  4558. accept the kind of data you're trying to read. For example, an input
  4559. variable of type %@AB@%Char%@AE@% cannot accept a %@AB@%Real%@AE@% value. See Chapter 2%@BO:    bdde@%,
  4560. "Programming Basics," for information on assigning data types.%@NL@%
  4561. %@NL@%
  4562. %@CR:MQP81103@%%@4@%%@AB@%Readln%@AE@% attempts to read data into the list of input variables. If the number%@EH@%
  4563. of data items typed on a single line exceeds the number of variables, the
  4564. additional data items are ignored. However, if %@AB@%Readln%@AE@% receives fewer data
  4565. items than the number of input variables, it expects the additional data to
  4566. appear on subsequent lines. For example, the %@AB@%Readln%@AE@% statement in the
  4567. following excerpt expects three values:%@NL@%
  4568. %@NL@%
  4569. %@AS@%     Writeln( 'For the investment what are: present value,' );%@NL@%
  4570. %@AS@%     Writeln( 'annual return, and number of years invested?' );%@NL@%
  4571. %@AS@%     Readln( present_value, rate_of_return, years_invested );%@NL@%
  4572. %@NL@%
  4573. %@CR:MQP81104@%%@4@%Suppose you run the program and in response to the prompt%@EH@%%@NL@%
  4574. %@NL@%
  4575.      %@AS@%For the investment what are: present value,%@AE@%%@NL@%
  4576.      %@AS@%annual return, and number of years invested?%@AE@%%@NL@%
  4577. %@NL@%
  4578. %@CR:MQP81105@%%@4@%you type%@EH@%%@NL@%
  4579. %@NL@%
  4580.      %@AS@%3000.00 1.05%@AE@%%@NL@%
  4581. %@NL@%
  4582. %@CR:MQP81106@%%@4@%and press ENTER. The program will then wait for you to enter the final%@EH@%
  4583. value. You must remember to use spaces, tabs, or carriage returns to
  4584. separate the values. Using commas causes a run-time error. If you're
  4585. concerned about the possibility of such errors, you can either write the
  4586. program with one %@AB@%Readln%@AE@% statement for each item entered, or read the data as
  4587. a string of text and create a procedure to separate the string into numbers.%@NL@%
  4588. %@NL@%
  4589. %@CR:MQP81107@%%@4@%The %@AB@%Read%@AE@% procedure, in contrast, reads only enough data to fill its input%@EH@%
  4590. variables. But subsequent %@AB@%Read%@AE@% or %@AB@%Readln%@AE@% procedures may get the remaining
  4591. data.%@NL@%
  4592. %@NL@%
  4593. %@CR:MQP81108@%%@4@%Suppose you rewrote the example above as%@EH@%%@NL@%
  4594. %@NL@%
  4595. %@AS@%     Writeln( 'For the investment what are: present value?' );%@NL@%
  4596. %@AS@%     Read( present_value )%@NL@%
  4597. %@AS@%     Writeln( 'the annual return?' );%@NL@%
  4598. %@AS@%     Read( rate_of_return );%@NL@%
  4599. %@AS@%     Writeln( 'and the number of years invested?' );%@NL@%
  4600. %@AS@%     Read( years_invested );%@NL@%
  4601. %@NL@%
  4602. %@CR:MQP81109@%%@4@%and ran the program with this response%@EH@%%@NL@%
  4603. %@NL@%
  4604.      %@AS@%For the investment what are: present value?%@AE@%%@NL@%
  4605.      %@AS@%3000.00 12.8 37%@AE@%%@NL@%
  4606. %@NL@%
  4607. %@CR:MQP8110A@%%@4@%The program would then accept %@AS@%3000.00%@AE@% as %@AS@%present_value%@AE@% and immediately print%@EH@%
  4608. the two remaining prompts without stopping:%@NL@%
  4609. %@NL@%
  4610.      %@AS@%the annual return?%@AE@%%@NL@%
  4611.      %@AS@%and the number of years invested?%@AE@%%@NL@%
  4612. %@NL@%
  4613. %@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@%
  4614. respectively. Unless your program performs some type of error checking,
  4615. using such a series of %@AB@%Read%@AE@% statements can potentially introduce errors.%@NL@%
  4616. %@NL@%
  4617. %@CR:MQP8110C@%%@4@%Like %@AB@%Readln%@AE@%, %@AB@%Read%@AE@% accepts all of the Pascal standard data types but inputs%@EH@%
  4618. them differently. Character data is not delimited; %@AB@%Read%@AE@% assigns any kind of
  4619. input to character variables, including carriage returns, spaces, and so on.
  4620. Strings input with %@AB@%Read%@AE@% can include any combination of ASCII text except for
  4621. a carriage return, which signifies the end of the string. For numeric data,
  4622. %@AB@%Read%@AE@% ignores any leading blanks, begins with the first number or sign (+ or
  4623. -), and continues until it reaches the next white-space character or
  4624. carriage return.%@NL@%
  4625. %@NL@%
  4626. %@NL@%
  4627. %@CR:MQP81200@%%@3@%%@AB@%8.1.2  Write and Writeln Procedures%@AE@%%@EH@%%@NL@%
  4628. %@NL@%
  4629. %@CR:MQP81201@%%@4@%The %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% procedures enable you to send variables, constants,%@EH@%
  4630. and  strings to the screen, disk files, or other output devices. The
  4631. variables or constants you use in %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% may be any of the Pascal
  4632. standard data types or a subrange of any of these types.%@NL@%
  4633. %@NL@%
  4634. %@CR:MQP81202@%%@4@%%@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% differ only in that %@AB@%Writeln%@AE@% terminates the line after%@EH@%
  4635. sending its data to the output device. Subsequent output appears on the next
  4636. line.%@NL@%
  4637. %@NL@%
  4638. %@CR:MQP81203@%%@4@%You often use the %@AB@%Write%@AE@% statement to print prompts on the screen. %@AB@%Writeln%@AE@%%@EH@%
  4639. displays full lines of text and is useful for leaving blank lines on the
  4640. screen for aesthetic purposes.%@NL@%
  4641. %@NL@%
  4642. %@CR:MQP81204@%%@4@%%@AB@%Write%@AE@% is often used with %@AB@%Read%@AE@% for simple prompt-and-reply input:%@EH@%%@NL@%
  4643. %@NL@%
  4644. %@AS@%     Write( 'Please enter two integers separated by a space: ' );%@NL@%
  4645. %@AS@%     Read( Int1, Int2 );%@NL@%
  4646. %@NL@%
  4647. %@CR:MQP81205@%%@4@%For complete lines of text and for blank lines, you might use %@AB@%Writeln%@AE@%:%@EH@%%@NL@%
  4648. %@NL@%
  4649. %@AS@%     Writeln( 'The Very Model of a Modern Major General' );%@NL@%
  4650. %@AS@%     Writeln( '========================================' );%@NL@%
  4651. %@AS@%     Writeln;%@NL@%
  4652. %@AS@%     Writeln('By Shorty Bonaparte');%@NL@%
  4653. %@NL@%
  4654. %@CR:MQP81206@%%@4@%Note that the strings of text appear at the left edge of the screen.%@EH@%%@NL@%
  4655. %@NL@%
  4656. %@CR:MQP81207@%%@4@%By themselves, %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% do not provide much numerical formatting;%@EH@%
  4657. they print numbers in a default format according to the type of variable.
  4658. For example, the output from%@NL@%
  4659. %@NL@%
  4660. %@AS@%     real_num := 3.1415;%@NL@%
  4661. %@AS@%     long_int := 1234567;%@NL@%
  4662. %@AS@%     Writeln( 'A real number prints out as ', real_num,'.' );%@NL@%
  4663. %@AS@%     Writeln( 'And a long integer prints as ', long_int,'.' );%@NL@%
  4664. %@NL@%
  4665. %@CR:MQP81208@%%@4@%looks like%@EH@%%@NL@%
  4666. %@NL@%
  4667.      %@AS@%A real number prints out as 3.14150000000154E+0000.%@AE@%%@NL@%
  4668.      %@AS@%And a long integer prints as 1234567.%@AE@%%@NL@%
  4669. %@NL@%
  4670. %@CR:MQP81209@%%@4@%The next section explains how to change these default formats.%@EH@%%@NL@%
  4671. %@NL@%
  4672. %@NL@%
  4673. %@CR:MQP81300@%%@3@%%@AB@%8.1.3  Formatted Output with Write and Writeln%@AE@%%@EH@%%@NL@%
  4674. %@NL@%
  4675. %@CR:MQP81301@%%@4@%The default numerical output format for real numbers is scientific notation.%@EH@%
  4676. For integers, the default output format is a sequence of digits. And, Pascal
  4677. normally prints strings as left justified. But %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% do allow
  4678. you to change the default formats.%@NL@%
  4679. %@NL@%
  4680. %@CR:MQP81302@%%@4@%Recall that the %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% statements follow the syntax:%@EH@%%@NL@%
  4681. %@NL@%
  4682.      %@AB@%Write(%@AE@%«%@AI@%FileName%@AE@%%@AB@%,%@AE@% » %@AI@%OutputVariable%@AE@% «%@AB@%:%@AE@% %@AI@%Width%@AE@%«%@AB@%:%@AE@%%@AI@%Decimals%@AE@%»»%@NL@%
  4683.         «%@AB@%,%@AE@%%@AI@%OutputVariable%@AE@% « %@AB@%:%@AE@%%@AI@%Width%@AE@%«%@AB@%:%@AE@%%@AI@%Decimals%@AE@%»»»%@AB@%)%@AE@%%@NL@%
  4684. %@NL@%
  4685. %@CR:MQP81303@%%@4@%The two optional fields %@AI@%Width%@AE@% and %@AI@%Decimals%@AE@% control formatting. The %@AI@%Width%@AE@%%@EH@%
  4686. field sets the maximum number of spaces available for printing the variable
  4687. called %@AI@%OutputVariable%@AE@% and indicates right or left justification by its sign
  4688. (positive for right justification, negative for left).%@NL@%
  4689. %@NL@%
  4690. %@CR:MQP81304@%%@4@%Pascal formats text and integer data in a similar fashion. These statements%@EH@%
  4691. print out the integer %@AS@%my_int%@AE@% and the string %@AS@%my_str%@AE@% in a space six columns
  4692. wide and right justified:%@NL@%
  4693. %@NL@%
  4694. %@AS@%     Writeln( my_int:6 );%@NL@%
  4695. %@AS@%     Writeln( my_str:6 );%@NL@%
  4696. %@NL@%
  4697. %@CR:MQP81305@%%@4@%If either %@AS@%my_int%@AE@% or %@AS@%my_str%@AE@% exceeds a width of six columns, QuickPascal%@EH@%
  4698. prints the entire integer or string with the default format.%@NL@%
  4699. %@NL@%
  4700. %@CR:MQP81306@%%@4@%Variables of type %@AB@%Real%@AE@% can also specify %@AI@%Decimals%@AE@%, which indicates the number%@EH@%
  4701. of digits to appear to the right of the decimal point. You cannot specify
  4702. %@AI@%Decimals%@AE@% for integers or strings.%@NL@%
  4703. %@NL@%
  4704. %@CR:MQP81307@%%@4@%The %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% procedures do not truncate strings or any type of%@EH@%
  4705. numerical data. If %@AI@%OutputVariable%@AE@% is wider than %@AI@%Width%@AE@%, %@AI@%Width%@AE@% is overridden
  4706. and the entire %@AI@%OutputVar%@AE@% is printed. For floating-point types, %@AB@%Write%@AE@% and
  4707. %@AB@%Writeln%@AE@% always print the number of decimal places specified by %@AI@%Decimals%@AE@%,
  4708. even if it means overriding the %@AI@%Width%@AE@% specification.%@NL@%
  4709. %@NL@%
  4710. %@CR:MQP81308@%%@4@%The following line right justifies a real number%@AS@%realnum%@AE@% and displays it with%@EH@%
  4711. four decimal places:%@NL@%
  4712. %@NL@%
  4713. %@AS@%     Writeln( realnum:12:4 )%@NL@%
  4714. %@NL@%
  4715. %@CR:MQP81309@%%@4@%Provided %@AS@%realnum%@AE@% contains 12 or fewer digits, the last digit lies in column%@EH@%
  4716. 12.%@NL@%
  4717. %@NL@%
  4718. %@CR:MQP8130A@%%@4@%This example%@EH@%%@NL@%
  4719. %@NL@%
  4720. %@AS@%     int_var  := 12345;%@NL@%
  4721. %@AS@%     str_var  := 'This sentence is a string.';%@NL@%
  4722. %@AS@%     real_var := 9870.65434;%@NL@%
  4723. %@NL@%
  4724. %@AS@%     Writeln( '1234567890123456789012345678901234567890 Ruler' );%@NL@%
  4725. %@AS@%     Writeln( '         10        20        30        40' );%@NL@%
  4726. %@AS@%     Writeln( int_var  : 8 );%@NL@%
  4727. %@AS@%     Writeln( int_var  : 85 );%@NL@%
  4728. %@AS@%     Writeln( str_var  : 35 );%@NL@%
  4729. %@AS@%     Writeln( str_var  : -3 );%@NL@%
  4730. %@AS@%     Writeln( real_var : -2 : 6 );%@NL@%
  4731. %@AS@%     Writeln( real_var : 14 : 2 );%@NL@%
  4732. %@NL@%
  4733. %@CR:MQP8130B@%%@4@%produces the following output:%@EH@%%@NL@%
  4734. %@NL@%
  4735.      %@AS@%1234567890123456789012345678901234567890   Ruler%@AE@%%@NL@%
  4736.               %@AS@%10        20        30        40%@AE@%%@NL@%
  4737.         %@AS@%12345%@AE@%%@NL@%
  4738.      %@AS@%12345%@AE@%%@NL@%
  4739.               %@AS@%This sentence is a string.%@AE@%%@NL@%
  4740.      %@AS@%This sentence is a string.%@AE@%%@NL@%
  4741.      %@AS@%9870.654340%@AE@%%@NL@%
  4742.             %@AS@%9870.65%@AE@%%@NL@%
  4743. %@NL@%
  4744. %@CR:MQP8130C@%%@4@%Formatting needs vary from program to program. If you frequently format your%@EH@%
  4745. data in a particular style, however, you may find it helpful to write a
  4746. procedure that automatically follows that format.%@NL@%
  4747. %@NL@%
  4748. %@NL@%
  4749. %@CR:MQP81400@%%@3@%%@AB@%8.1.4  DOS Redirection: Input and Output Files%@AE@%%@EH@%%@NL@%
  4750. %@NL@%
  4751. %@CR:MQP81401@%%@4@%A process called "DOS redirection" allows you to specify both input and%@EH@%
  4752. output files for QuickPascal programs. An input file contains responses to
  4753. all of the questions asked by the program (provided they are input with %@AB@%Read%@AE@%
  4754. or %@AB@%Readln%@AE@% statements). An output file receives all of the information
  4755. written by %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% statements that usually go to the screen.%@NL@%
  4756. %@NL@%
  4757. %@CR:MQP81410@%%@4@%%@AB@%8.1.4.1  Standard Redirection%@AE@%%@EH@%%@NL@%
  4758. %@NL@%
  4759. %@CR:MQP81411@%%@4@%Redirected programs run in a completely normal manner; they just accept%@EH@%
  4760. their input from a file instead of the keyboard, and send their output to a
  4761. file instead of the screen. You can run redirected programs only from the
  4762. DOS command line. To use redirection from within the QuickPascal
  4763. environment, you must first choose the DOS Shell command from the File menu.
  4764. The general redirection syntax is%@NL@%
  4765. %@NL@%
  4766.      %@AI@%ProgramName%@AE@% «%@AB@%<%@AE@%%@AI@%InputFile%@AE@%» %@AB@%>%@AE@%%@AI@%OutputFile%@AE@%»%@NL@%
  4767. %@NL@%
  4768. %@CR:MQP81412@%%@4@%You can include the %@AI@%InputFile%@AE@% only, the %@AI@%OutputFile%@AE@% only, or both. Both must%@EH@%
  4769. be text files. If you run with just %@AI@%InputFile%@AE@%%@NL@%
  4770. %@NL@%
  4771.      %@AI@%ProgramName%@AE@% %@AB@%<%@AE@%%@AI@%InputFile%@AE@%%@NL@%
  4772. %@NL@%
  4773. %@CR:MQP81413@%%@4@%you still see the program's queries and other output on the screen. However,%@EH@%
  4774. unless you specifically write your program to echo user input, you do not
  4775. see the input data on the screen because it comes directly from the input
  4776. file.%@NL@%
  4777. %@NL@%
  4778. %@CR:MQP81414@%%@4@%If you run %@AI@%ProgramName%@AE@% and include only the %@AI@%OutputFile%@AE@%%@EH@%%@NL@%
  4779. %@NL@%
  4780.      %@AI@%ProgramName%@AE@% %@AB@%>%@AE@%%@AI@%OutputFile%@AE@%%@NL@%
  4781. %@NL@%
  4782. %@CR:MQP81415@%%@4@%you need to know the order in which the program requires its input; all%@EH@%
  4783. output, including prompts for input, go to %@AI@%OutputFile%@AE@%. DOS creates a new
  4784. output file each time you run the program and specify %@AI@%OutputFile%@AE@%. If a file
  4785. named %@AI@%OutputFile%@AE@% already exists, the old one is erased and a new one is
  4786. created. But, if you add an additional > symbol%@NL@%
  4787. %@NL@%
  4788.      %@AI@%ProgramName%@AE@% %@AB@%>>%@AE@%%@AI@%OutputFile%@AE@%%@NL@%
  4789. %@NL@%
  4790. %@CR:MQP81416@%%@4@%DOS appends the new output to the end of the existing file named %@AI@%OutputFile%@AE@%.%@EH@%%@NL@%
  4791. %@NL@%
  4792. %@CR:MQP81417@%%@4@%For example, suppose you write a database program called%@AS@%ADDRESS.EXE%@AE@% that%@EH@%
  4793. reads employee names and returns their mailing addresses. Using Quick Pascal
  4794. or some other editor that saves text files, you can create a list of
  4795. employee names and save it as %@AS@%NAME.TXT%@AE@%. Then if you enter%@NL@%
  4796. %@NL@%
  4797.      %@AS@%ADDRESS <NAME.TXT%@AE@%%@NL@%
  4798. %@NL@%
  4799. %@CR:MQP81418@%%@4@%you can print the list of employee addresses on the screen. Entering%@EH@%%@NL@%
  4800. %@NL@%
  4801.      %@AS@%ADDRESS <NAME.TXT >ADD.TXT%@AE@%%@NL@%
  4802. %@NL@%
  4803. %@CR:MQP81419@%%@4@%creates a new file called %@AS@%ADD.TXT%@AE@% that contains the employee addresses. And,%@EH@%
  4804. if you write another input file called %@AS@%MORENAME.TXT%@AE@%, then the command%@NL@%
  4805. %@NL@%
  4806.      %@AS@%ADDRESS <MORENAME.TXT >>ADD.TXT%@AE@%%@NL@%
  4807. %@NL@%
  4808. %@CR:MQP8141A@%%@4@%adds the additional addresses to the end of the existing %@AS@%ADD.TXT%@AE@% file.%@EH@%%@NL@%
  4809. %@NL@%
  4810. %@CR:MQP81420@%%@4@%%@AB@%8.1.4.2  The Crt Unit and DOS Redirection%@AE@%%@EH@%%@NL@%
  4811. %@NL@%
  4812. %@CR:MQP81421@%%@4@%The %@AB@%Crt%@AE@% unit overrides DOS redirection. Programs with %@AB@%Crt%@AE@% in their %@AB@%USES%@AE@%%@EH@%
  4813. statements ignore input and output files.%@NL@%
  4814. %@NL@%
  4815. %@CR:MQP81422@%%@4@%If you want to run programs that use the %@AB@%Crt%@AE@% unit with input and output%@EH@%
  4816. files, you must include the following lines in your program prior to the
  4817. first input or output statement:%@NL@%
  4818. %@NL@%
  4819. %@AS@%     Assign( Input, '' );%@NL@%
  4820. %@AS@%     Reset( Input );%@NL@%
  4821. %@AS@%     Assign( Output, '' );%@NL@%
  4822. %@AS@%     Rewrite( Output );%@NL@%
  4823. %@NL@%
  4824. %@CR:MQP81423@%%@4@%The %@AB@%Crt%@AE@% unit changes the names of the standard input and output sources; the%@EH@%
  4825. four lines above reassign them to their original settings.%@NL@%
  4826. %@NL@%
  4827. %@NL@%
  4828. %@CR:MQP82000@%%@2@%%@AB@%8.2  The Crt Unit%@AE@%%@EH@%%@NL@%
  4829. %@NL@%
  4830. %@CR:MQP82001@%%@4@%If you have read Chapter 7%@BO:   31ac9@%, "Units," you're familiar with the concept of%@EH@%
  4831. units. The %@AB@%Crt%@AE@% unit is a standard unit that provides data types and
  4832. procedures for keyboard input, cursor control, screen control, and windows.
  4833. This section describes some of the variables and all of the procedures
  4834. provided in the %@AB@%Crt%@AE@% unit. You can obtain more information on each of these
  4835. variables and procedures through the on-line help system.%@NL@%
  4836. %@NL@%
  4837. %@CR:MQP82002@%%@4@%If you plan to use the %@AB@%Crt%@AE@% and %@AB@%MSGraph%@AE@% units together, be sure you read%@EH@%
  4838. Chapter 13%@BO:   5dac7@%, "Using Graphics." QuickPascal imposes some restrictions on
  4839. programs that call both the %@AB@%Crt%@AE@% and the %@AB@%MSGraph%@AE@% units.%@NL@%
  4840. %@NL@%
  4841. %@NL@%
  4842. %@CR:MQP82100@%%@3@%%@AB@%8.2.1  Using the Crt Unit%@AE@%%@EH@%%@NL@%
  4843. %@NL@%
  4844. %@CR:MQP82101@%%@4@%Many of the complete sample programs presented in this manual use the %@AB@%Crt%@AE@%%@EH@%
  4845. unit. To access its functions, procedures, variables, and constants in your
  4846. own programs, add the statement %@AS@%USES Crt;%@AE@% immediately after your program
  4847. declaration.%@NL@%
  4848. %@NL@%
  4849. %@CR:MQP82102@%%@4@%When you start a graphics program you need to tell QuickPascal how you want%@EH@%
  4850. it to display text. You pass a particular constant to the %@AS@%TextMode%@AE@% procedure
  4851. based on your desired text mode. The constants appear in Table 8.1.%@NL@%
  4852. %@NL@%
  4853. %@CR:MQP8T100@%%@4@%%@AB@%Table 8.1  Crt Text-Mode Constants%@AE@%%@EH@%%@NL@%
  4854. %@NL@%
  4855. %@AB@%Constant%@AE@%%@NL@%
  4856. %@AB@%Identifier        Value             Display%@AE@%%@NL@%
  4857. %@NL@%
  4858. %@AB@%BW40%@AE@%              0                 40 by 25 monochrome text screen%@NL@%
  4859. %@NL@%
  4860. %@AB@%BW80%@AE@%              2                 80 by 25 monochrome text screen%@NL@%
  4861. %@NL@%
  4862. %@AB@%Mono%@AE@%              7                 80 by 25 monochrome text screen%@NL@%
  4863. %@NL@%
  4864. %@AB@%CO40%@AE@%              1                 40 by 25 color text screen%@NL@%
  4865. %@NL@%
  4866. %@AB@%CO80%@AE@%              3                 80 by 25 color text screen%@NL@%
  4867. %@NL@%
  4868. %@AB@%Font8x8%@AE@%           256               EGA/VGA 43 lines%@NL@%
  4869. %@NL@%
  4870. %@CR:MQP82103@%%@4@%The %@AB@%Crt%@AE@% unit also establishes the color constants shown in Table 8.2%@BO:   3afb0@%. When%@EH@%
  4871. you print text in different colors or create windows with different colored
  4872. backgrounds, refer to the color by its value.%@NL@%
  4873. %@NL@%
  4874. %@CR:MQP8T200@%%@4@%%@AB@%Table 8.2  Crt Color Constants%@AE@%%@EH@%%@NL@%
  4875. %@NL@%
  4876. %@AB@%Color          Value     Color            Value%@AE@%%@NL@%
  4877. %@NL@%
  4878. %@AB@%Black%@AE@%          0         %@AB@%LightBlue%@AE@%        9%@NL@%
  4879. %@NL@%
  4880. %@AB@%Blue%@AE@%           1         %@AB@%LightGreen%@AE@%       10%@NL@%
  4881. %@NL@%
  4882. %@AB@%Green%@AE@%          2         %@AB@%LightCyan%@AE@%        11%@NL@%
  4883. %@NL@%
  4884. %@AB@%Cyan%@AE@%           3         %@AB@%LightRed%@AE@%         12%@NL@%
  4885. %@NL@%
  4886. %@AB@%Red%@AE@%            4         %@AB@%LightMagenta%@AE@%     13%@NL@%
  4887. %@NL@%
  4888. %@AB@%Magenta%@AE@%        5         %@AB@%Yellow%@AE@%           14%@NL@%
  4889. %@NL@%
  4890. %@AB@%Brown%@AE@%          6         %@AB@%White%@AE@%            15%@NL@%
  4891. %@NL@%
  4892. %@AB@%LightGray%@AE@%      7         %@AB@%Blink%@AE@%            128%@NL@%
  4893. %@NL@%
  4894. %@AB@%DarkGray%@AE@%       8%@NL@%
  4895. %@NL@%
  4896. %@CR:MQP82104@%%@4@%In addition to the constants, the %@AB@%Crt%@AE@% unit exports the variables listed in%@EH@%
  4897. Table 8.3%@BO:   3b42e@%. They let your programs access status and informational settings
  4898. used by QuickPascal, such as the previous video mode or current text
  4899. attributes.%@NL@%
  4900. %@NL@%
  4901. %@CR:MQP8T300@%%@4@%%@AB@%Table 8.3  Variables Provided by the Crt Unit%@AE@%%@EH@%%@NL@%
  4902. %@NL@%
  4903. %@AB@%Variable          Data Type         Purpose%@AE@%%@NL@%
  4904. %@NL@%
  4905. %@AB@%CheckBreak%@AE@%        %@AB@%Boolean%@AE@%           Indicates the state of CTRL+BREAK%@NL@%
  4906.                                     checking%@NL@%
  4907. %@NL@%
  4908. %@AB@%CheckEof%@AE@%          %@AB@%Boolean%@AE@%           Enables/disables checking for%@NL@%
  4909.                                     end-of-file character on keyboard input%@NL@%
  4910. %@NL@%
  4911. %@AB@%CheckSnow%@AE@%         %@AB@%Boolean%@AE@%           Enables/disables "snow checking" for the%@NL@%
  4912.                                     screen%@NL@%
  4913. %@NL@%
  4914. %@AB@%DirectVideo%@AE@%       %@AB@%Boolean%@AE@%           Enables/disables direct video%@NL@%
  4915.                                     output%@NL@%
  4916. %@NL@%
  4917. %@AB@%LastMode%@AE@%          %@AB@%Word%@AE@%              Saves previous video mode%@NL@%
  4918. %@NL@%
  4919. %@AB@%TextAttr%@AE@%          %@AB@%Byte%@AE@%              Contains the current text display%@NL@%
  4920.                                     attribute%@NL@%
  4921. %@NL@%
  4922. %@AB@%WindMin%@AE@%           %@AB@%Word%@AE@%              Saves the previous coordinates of the%@NL@%
  4923.                                     upper left corner of the active window%@NL@%
  4924. %@NL@%
  4925. %@AB@%WindMax%@AE@%           %@AB@%Word%@AE@%              Saves the previous coordinates of the%@NL@%
  4926.                                     lower right corner of the active window%@NL@%
  4927. %@NL@%
  4928. %@CR:MQP82105@%%@4@%The variable %@AB@%DirectVideo%@AE@% plays an important role in speeding up screen%@EH@%
  4929. output. Setting %@AB@%DirectVideo%@AE@% to %@AB@%True%@AE@% sends the output of %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@%
  4930. statements directly to your screen's memory. Unfortunately, this technique
  4931. does not work on some computer configurations. Setting %@AB@%DirectVideo%@AE@% to %@AB@%False%@AE@%,
  4932. on the other hand, employs your machine's Basic Input Output System (BIOS).
  4933. BIOS always displays correctly but works at a slower speed; experiment to
  4934. see which setting works better for your computer.%@NL@%
  4935. %@NL@%
  4936. %@CR:MQP82106@%%@4@%The %@AB@%WindMin%@AE@% and %@AB@%WindMax%@AE@% variables store the coordinates of the active%@EH@%
  4937. window. Use the predefined %@AB@%Hi%@AE@% and %@AB@%Lo%@AE@% functions to read the high and low
  4938. bytes that are packed in the %@AB@%WindMin%@AE@% or %@AB@%WindMax%@AE@% variables, as shown below:%@NL@%
  4939. %@NL@%
  4940. %@AS@%     UpperLeftX  := Lo(WindMin) + 1;%@NL@%
  4941. %@AS@%     UpperLeftY  := Hi(WindMin) + 1;%@NL@%
  4942. %@AS@%     LowerRightX := Lo(WindMax) + 1;%@NL@%
  4943. %@AS@%     LowerRightY := Hi(WindMax) + 1;%@NL@%
  4944. %@NL@%
  4945. %@CR:MQP82107@%%@4@%Table 8.4%@BO:   3bfd0@% lists all of the %@AB@%Crt%@AE@% procedures and functions; by browsing%@EH@%
  4946. through it you'll get a feel for the %@AB@%Crt%@AE@% unit. The "Purpose" column
  4947. describes what each procedure does. On-line help gives a more complete
  4948. explanation, and the sample programs show other uses of these procedures.%@NL@%
  4949. %@NL@%
  4950. %@CR:MQP8T400@%%@4@%%@AB@%Table 8.4  Procedures and Functions Provided by the Crt Unit%@AE@%%@EH@%%@NL@%
  4951. %@TH:   75   2968  2 18 17 41 @%
  4952. %@AB@%Procedure         Purpose                    Example%@AE@%
  4953.  
  4954. %@AB@%AssignCrt%@AE@%         Associates a text-file     %@AS@%AssignCrt(DataFile) ;%@AE@%
  4955.                   variable with the
  4956.                   screen
  4957.  
  4958. %@AB@%ClrEol%@AE@%            Clears to the end of       %@AS@%ClrEol;%@AE@%
  4959.                   the line
  4960.  
  4961. %@AB@%ClrScr%@AE@%            Clears the window and      %@AS@%ClrScr;%@AE@%
  4962.                   places the cursor at
  4963.                   the upper left corner
  4964.  
  4965. %@AB@%Delay%@AE@%             Delays the program for     %@AS@%Delay(1000){1 sec. };%@AE@%
  4966.                   a specified number of
  4967.                   milliseconds
  4968.  
  4969. %@AB@%DelLine%@AE@%           Removes the line at        %@AS@%DelLine;%@AE@%
  4970.                   the current cursor
  4971.                   location
  4972.  
  4973. %@AB@%GotoXY%@AE@%            Moves the cursor to        %@AS@%GotoXY( 40,25 );%@AE@%
  4974.                   the specified window
  4975.                   coordinates
  4976.  
  4977. %@AB@%HighVideo%@AE@%         Displays characters in     %@AS@%HighVideo;%@AE@%
  4978.                   high intensity
  4979.  
  4980. %@AB@%InsLine%@AE@%           Inserts an empty line      %@AS@%InsLine;%@AE@%
  4981.                   at the current cursor
  4982.                   location
  4983.  
  4984. %@AB@%KeyPressed%@AE@%        Returns %@AB@%True%@AE@% if there      %@AS@%WHILE KeyPressed DO ...%@AE@%
  4985.                   is a character in the
  4986.                   keyboard buffer
  4987.  
  4988. %@AB@%LowVideo%@AE@%          Displays characters in     %@AS@%LowVideo;%@AE@%
  4989.                   low intensity
  4990.  
  4991. %@AB@%NormVideo%@AE@%         Restores screen            %@AS@%NormVideo;%@AE@%
  4992.                   attri-butes to those
  4993.                   in effect when the
  4994.                   program started
  4995.  
  4996. %@AB@%NoSound%@AE@%           Turns the speaker off      %@AS@%NoSound;%@AE@%
  4997.  
  4998. %@AB@%ReadKey%@AE@%           Reads the next             %@AS@%akey := ReadKey;%@AE@%
  4999.                   character from the
  5000.                   keyboard buffer
  5001.                   without showing it on
  5002.                   the screen
  5003.  
  5004. %@AB@%Sound%@AE@%             Turns the speaker on       %@AS@%Sound( frequency );%@AE@%
  5005.  
  5006. %@AB@%TextBackground%@AE@%    Selects the background     %@AS@%TextBackground( Black );%@AE@%
  5007.                   color for subsequent
  5008.                   text display
  5009.  
  5010. %@AB@%TextColor%@AE@%         Selects the foreground     %@AS@%TextColor( Red );%@AE@%
  5011.                   color for subsequent
  5012.                   text display
  5013.  
  5014. %@AB@%TextMode%@AE@%          Selects the display        %@AS@%TextMode( BW80 );%@AE@%
  5015.                   mode
  5016.  
  5017. %@AB@%WhereX%@AE@%            Returns the X coor-        %@AS@%posx := WhereX;%@AE@%
  5018.                   dinate of the cursor
  5019.                   location
  5020.  
  5021. %@AB@%WhereY%@AE@%            Returns the Y coor-        %@AS@%posy := WhereY;%@AE@%
  5022.                   dinate of the cursor
  5023.                   location
  5024.  
  5025. %@AB@%Window%@AE@%            Defines a new display      %@AS@%Window( 2,2,40,10 );%@AE@%
  5026.                   window
  5027. %@TE:   75   2968  2 18 17 41 @%
  5028. %@NL@%
  5029. %@CR:MQP82200@%%@3@%%@AB@%8.2.2  Character Input%@AE@%%@EH@%%@NL@%
  5030. %@NL@%
  5031. %@CR:MQP82201@%%@4@%You can read characters from the keyboard in a couple of different ways. In%@EH@%
  5032. the case of the %@AB@%Read%@AE@% and %@AB@%Readln%@AE@% procedures, as each letter is typed in, it
  5033. is put into the input variables and displayed on the screen. The %@AB@%Crt%@AE@%
  5034. function %@AB@%ReadKey%@AE@% also reads input from the keyboard, but can read only one
  5035. character at a time; it does not display the character on the screen.%@NL@%
  5036. %@NL@%
  5037. %@CR:MQP82202@%%@4@%Although you may want to do your primary data collection with %@AB@%Read%@AE@% and%@EH@%
  5038. %@AB@%Readln%@AE@%, the %@AB@%ReadKey%@AE@% function lets you add finishing touches to your
  5039. programs. For example, the following line pauses program execution until the
  5040. user presses ENTER:%@NL@%
  5041. %@NL@%
  5042. %@AS@%     REPEAT UNTIL ReadKey = Chr( 13 );%@NL@%
  5043. %@NL@%
  5044. %@CR:MQP82203@%%@4@%%@AB@%ReadKey%@AE@% also reads function keys, cursor-control keys, control keys, and%@EH@%
  5045. alternate keys. These special keys send a sequence of characters. The first
  5046. is a null character (that is, ASCII 0). The second character is an extended
  5047. key code. (See Appendix A%@BO:   829c0@% for a table of extended key codes.)%@NL@%
  5048. %@NL@%
  5049. %@CR:MQP82204@%%@4@%The following excerpt illustrates a typical character processor for a%@EH@%
  5050. keyboard-driven program. It checks for the special character code %@AS@%#0%@AE@% and the
  5051. standard alphanumeric keys. If the first key is special, a second %@AB@%CASE%@AE@%
  5052. statement identifies which key is pressed. Once the character processor
  5053. determines the key pressed, it invokes the applicable procedure.%@NL@%
  5054. %@NL@%
  5055. %@AS@%     VAR%@NL@%
  5056. %@AS@%         done : Boolean;%@NL@%
  5057. %@AS@%         ch, ch2   : Char;%@NL@%
  5058. %@NL@%
  5059. %@AS@%     BEGIN%@NL@%
  5060. %@AS@%         done := False;%@NL@%
  5061. %@NL@%
  5062. %@AS@%         REPEAT%@NL@%
  5063. %@AS@%             ch:= ReadKey;%@NL@%
  5064. %@AS@%             CASE ch OF%@NL@%
  5065. %@AS@%                 #0: BEGIN%@NL@%
  5066. %@AS@%                     ch2:= ReadKey;%@NL@%
  5067. %@AS@%                     CASE ch2 OF%@NL@%
  5068. %@AS@%                         59:    { Got F1 key }%@NL@%
  5069. %@AS@%                             DoF1;  { F1 procedure }%@NL@%
  5070. %@AS@%                         .%@NL@%
  5071. %@AS@%                         .%@NL@%
  5072. %@AS@%                         .%@NL@%
  5073. %@AS@%                         END;{ CASE ch2 }%@NL@%
  5074. %@AS@%                     END;{ #0 }%@NL@%
  5075. %@AS@%                 '0'..'9',%@NL@%
  5076. %@AS@%                 'A'..'Z',%@NL@%
  5077. %@AS@%                 'a'..'z':%@NL@%
  5078. %@AS@%                     DoAlphaDigit( ch );  { Procedure for normal keys }%@NL@%
  5079. %@AS@%                 ELSE%@NL@%
  5080. %@AS@%                     done :=True;%@NL@%
  5081. %@AS@%                 END;%@NL@%
  5082. %@AS@%         UNTIL done;%@NL@%
  5083. %@NL@%
  5084. %@CR:MQP82205@%%@4@%The CRT1.PAS program in the QuickPascal Advisor demonstrates how to detect%@EH@%
  5085. special keys using %@AB@%ReadKey%@AE@%. You can compile and run the program, which does
  5086. the following:%@NL@%
  5087. %@NL@%
  5088. %@CR:MQP82206@%  ■  Moves the %@AS@%'o'%@AE@% character on the screen when you press the UP, DOWN,%@NL@%
  5089.      LEFT, and RIGHT arrow keys.%@NL@%
  5090. %@NL@%
  5091.   ■  Simulates a bouncing ball effect if you press the F2 function key.%@NL@%
  5092. %@NL@%
  5093.   ■  Hides the cursor.%@NL@%
  5094. %@NL@%
  5095.   ■  Exits when you press the F1 function key.%@NL@%
  5096. %@NL@%
  5097. %@CR:MQP82207@%%@4@%If you don't like the sound effects, set the constant %@AS@%music%@AE@% to %@AS@%false%@AE@%.%@EH@%%@NL@%
  5098. %@NL@%
  5099. %@CR:MQP82208@%%@4@%In the CRT1.PAS program, the %@AS@%IF%@AE@% statement%@EH@%%@NL@%
  5100. %@NL@%
  5101. %@AS@%     IF c1 = #0%@NL@%
  5102. %@NL@%
  5103. %@CR:MQP82209@%%@4@%becomes true when you press a special key. In that case, %@AB@%ReadKey%@AE@% returns two%@EH@%
  5104. characters, the first of which is always ASCII %@AS@%#0%@AE@%. The path taken through
  5105. the %@AB@%WHILE%@AE@% loops depends on which key you press.%@NL@%
  5106. %@NL@%
  5107. %@CR:MQP8220A@%%@4@%The %@AS@%cursor_off%@AE@% procedure calls BIOS to turn off the cursor. The %@AB@%Crt%@AE@%%@EH@%
  5108. procedures %@AB@%Sound%@AE@% and %@AB@%Delay%@AE@% are also used in this program. On-line help has
  5109. more information about these two procedures.%@NL@%
  5110. %@NL@%
  5111. %@NL@%
  5112. %@CR:MQP82300@%%@3@%%@AB@%8.2.3  Cursor and Screen Control%@AE@%%@EH@%%@NL@%
  5113. %@NL@%
  5114. %@CR:MQP82301@%%@4@%The %@AB@%Crt%@AE@% unit provides several procedures for screen and cursor control.%@EH@%
  5115. Their names reflect their actions: %@AB@%DelLine%@AE@%, %@AB@%HighVideo%@AE@%, %@AB@%GotoXY%@AE@%, and so on.
  5116. For more information about a specific procedure, use the QuickPascal Advisor
  5117. help.%@NL@%
  5118. %@NL@%
  5119. %@CR:MQP82302@%%@4@%This section refers you to two example programs in the QP Advisor. The%@EH@%
  5120. program CRT2.PAS uses %@AB@%Crt%@AE@% procedures to insert and delete lines, change
  5121. video intensity, and produce sound effects. The program requires very few
  5122. code lines to accomplish these tasks.%@NL@%
  5123. %@NL@%
  5124. %@CR:MQP82303@%%@4@%The CRT3.PAS program uses the %@AB@%GotoXY%@AE@% function to control the cursor. Table%@EH@%
  5125. 8.6%@BO:   3e005@% shows the %@AB@%GotoXY%@AE@% statements used to move the cursor relative to its
  5126. current position, assuming the cursor is not at the edge of a window.%@NL@%
  5127. %@NL@%
  5128. %@CR:MQP8T600@%%@4@%%@AB@%Table 8.6  Statement Effects%@AE@%%@EH@%%@NL@%
  5129. %@NL@%
  5130. %@AB@%Example                         Description%@AE@%%@NL@%
  5131. %@NL@%
  5132. %@AS@%GotoXY( WhereX-1, WhereY )%@AE@%      Moves one character to the left%@NL@%
  5133. %@NL@%
  5134. %@AS@%GotoXY( WhereX+1, WhereY )%@AE@%      Moves one character to the right%@NL@%
  5135. %@NL@%
  5136. %@AS@%GotoXY( WhereX, WhereY-1 )%@AE@%      Moves up one line%@NL@%
  5137. %@NL@%
  5138. %@AS@%GotoXY( WhereX, WhereY+1 )%@AE@%      Moves down one line%@NL@%
  5139. %@NL@%
  5140. %@AS@%GotoXY( 1, WhereY )%@AE@%             Moves to the beginning of the current line%@NL@%
  5141. %@NL@%
  5142. %@AS@%GotoXY(80, WhereY)%@AE@%              Moves to the end of the current line%@NL@%
  5143. %@NL@%
  5144. %@CR:MQP82304@%%@4@%The CRT3.PAS program prompts you to type a character and then "bounces" that%@EH@%
  5145. character around the screen. The character changes direction and beeps when
  5146. it reaches the edge of the screen. The character's speed increases each time
  5147. the character changes direction. When it reaches a maximum speed, the
  5148. character slows back down to its original speed.%@NL@%
  5149. %@NL@%
  5150. %@NL@%
  5151. %@CR:MQP82400@%%@3@%%@AB@%8.2.4  Using Windows%@AE@%%@EH@%%@NL@%
  5152. %@NL@%
  5153. %@CR:MQP82401@%%@4@%The %@AB@%Crt%@AE@% unit provides easy control of text windows. The %@AB@%Window%@AE@% procedure%@EH@%
  5154. allows you to define a new active area of the screen.%@NL@%
  5155. %@NL@%
  5156. %@CR:MQP82402@%%@4@%%@AB@%Window%@AE@% accepts row and column coordinates for the upper left and lower right%@EH@%
  5157. corners of the new window. These coordinates must be integers of type %@AB@%Byte%@AE@%.
  5158. The rows range from 1-25 (or 1-43 or 1-50, depending on the text mode) and
  5159. the columns range from 1-80.%@NL@%
  5160. %@NL@%
  5161. %@CR:MQP82403@%%@4@%The %@AB@%Window%@AE@% procedure is analogous to choosing the size of a piece of paper%@EH@%
  5162. to draw on; the coordinates you pass to the procedure tell QuickPascal how
  5163. big to make the piece of paper. For example, the following statement defines
  5164. the entire screen area:%@NL@%
  5165. %@NL@%
  5166. %@AS@%     Window( 1, 1, 25, 80 );%@NL@%
  5167. %@NL@%
  5168. %@CR:MQP82404@%%@4@%Many applications use the top and bottom lines of the screen to display a%@EH@%
  5169. menu or help text. To exclude these lines from the active screen area, use%@NL@%
  5170. %@NL@%
  5171. %@AS@%     Window( 1, 2, 24, 80 );%@NL@%
  5172. %@NL@%
  5173. %@CR:MQP82405@%%@4@%If you write an application that draws a frame around the screen, you may%@EH@%
  5174. want to use the following statement to reduce the active screen area:%@NL@%
  5175. %@NL@%
  5176. %@AS@%     Window( 2, 2, 24, 79 );%@NL@%
  5177. %@NL@%
  5178. %@CR:MQP82406@%%@4@%When you create a new window, the upper left corner of the display area is%@EH@%
  5179. (1, 1). Thus,%@AB@%GotoXY%@AE@%(1, 1) moves the cursor to the upper left corner of the
  5180. active window, regardless of window size and location. %@AB@%GotoXY%@AE@% is analogous
  5181. to setting your pen down at a specific place on the piece of paper. %@AB@%WhereX%@AE@%
  5182. and %@AB@%WhereY%@AE@% return you to your current location.%@NL@%
  5183. %@NL@%
  5184. %@CR:MQP82407@%%@4@%Choose the foreground and background colors for the active window with the%@EH@%
  5185. %@AB@%TextColor%@AE@% and %@AB@%TextBackground%@AE@% procedures. To continue the earlier comparison,
  5186. %@AB@%TextColor%@AE@% lets you select your pen's color and %@AB@%TextBackground%@AE@% selects the
  5187. color of the piece of paper. Note that after changing the background color,
  5188. you must clear the screen to see the new color. Clearing the screen resets
  5189. the cursor to (1, 1).%@NL@%
  5190. %@NL@%
  5191. %@CR:MQP82408@%%@4@%The program CRT4.PAS shows how these procedures work (although you need a%@EH@%
  5192. color monitor to see the colors). It illustrates%@NL@%
  5193. %@NL@%
  5194. %@CR:MQP82409@%  ■  Windows that move while keeping their size fixed%@NL@%
  5195. %@NL@%
  5196.   ■  Windows that simultaneously move and change sizes%@NL@%
  5197. %@NL@%
  5198.   ■  Screen and cursor control of text within a window%@NL@%
  5199. %@NL@%
  5200. %@CR:MQP8240A@%%@4@%CRT4.PAS gives you an idea of what you can do with windows. With a few%@EH@%
  5201. similar lines of code, you can improve your screen's visual impact and add
  5202. clarity and emphasis to your programs.%@NL@%
  5203. %@NL@%
  5204. %@NL@%
  5205. %@CR:MQP90000@%%@1@%%@AB@%Chapter 9  Text Files%@AE@%%@EH@%%@NL@%
  5206. ───────────────────────────────────────────────────────────────────────────%@NL@%
  5207. %@NL@%
  5208. %@CR:MQP90001@%%@4@%Text files store data as lines of ASCII characters. The lines do not have to%@EH@%
  5209. be the same length. Each line terminates with an end-of-line character
  5210. (carriage return). Any text editor or word processor that reads ASCII files
  5211. can edit these files, including the QuickPascal environment.%@NL@%
  5212. %@NL@%
  5213. %@CR:MQP90002@%%@4@%Pascal writes and reads text files sequentially, in much the same way an%@EH@%
  5214. audio cassette player records or plays back a tape. Adding basic file input
  5215. and output (I/O) capabilities to your programs lets you store and retrieve
  5216. data from this "tape" for both long- and short-term use.%@NL@%
  5217. %@NL@%
  5218. %@CR:MQP90003@%%@4@%This chapter covers how to name, open, read, write, and close a file, and%@EH@%
  5219. how to redirect text information between your disk, screen, and printer. It
  5220. also lists the standard procedures used to work with text files.%@NL@%
  5221. %@NL@%
  5222. %@NL@%
  5223. %@CR:MQP91000@%%@2@%%@AB@%9.1  Working with Text Files%@AE@%%@EH@%%@NL@%
  5224. %@NL@%
  5225. %@CR:MQP91001@%%@4@%Working with text files means taking a few straightforward actions:%@EH@%%@NL@%
  5226. %@NL@%
  5227. %@CR:MQP91002@%  ■  Declaring a file variable and a file name%@NL@%
  5228. %@NL@%
  5229.   ■  Creating a new file or opening an existing one%@NL@%
  5230. %@NL@%
  5231.   ■  Writing or appending data to a file%@NL@%
  5232. %@NL@%
  5233.   ■  Reading data from a file%@NL@%
  5234. %@NL@%
  5235.   ■  Closing a file%@NL@%
  5236. %@NL@%
  5237. %@CR:MQP91003@%%@4@%The following sections address these steps in detail.%@EH@%%@NL@%
  5238. %@NL@%
  5239. %@CR:MQP91004@%%@4@%As a general introduction, look at the following sample program:%@EH@%%@NL@%
  5240. %@NL@%
  5241. %@AS@%     PROGRAM filetest;%@NL@%
  5242. %@AS@%     VAR%@NL@%
  5243. %@AS@%         datafile : Text;%@NL@%
  5244. %@AS@%         i        : Integer;%@NL@%
  5245. %@NL@%
  5246. %@AS@%     BEGIN%@NL@%
  5247. %@AS@%         Assign( datafile, 'RAN_DATA.DAT' );%@NL@%
  5248. %@AS@%         Rewrite( datafile );%@NL@%
  5249. %@NL@%
  5250. %@AS@%         FOR i := 1 TO 100 DO%@NL@%
  5251. %@AS@%             BEGIN%@NL@%
  5252. %@AS@%             Writeln( datafile, Random(50) );%@NL@%
  5253. %@AS@%             END;%@NL@%
  5254. %@NL@%
  5255. %@AS@%         Close( datafile );%@NL@%
  5256. %@AS@%     END.%@NL@%
  5257. %@NL@%
  5258. %@CR:MQP91005@%%@4@%The rest of this chapter frequently refers back to this example.%@EH@%%@NL@%
  5259. %@NL@%
  5260. %@NL@%
  5261. %@CR:MQP91100@%%@3@%%@AB@%9.1.1  Declaring a File Variable and File Name%@AE@%%@EH@%%@NL@%
  5262. %@NL@%
  5263. %@CR:MQP91101@%%@4@%Declaring a file variable means telling QuickPascal how you want to refer to%@EH@%
  5264. the file from within the program. It is the variable name by which the
  5265. program knows the file. You declare it in the same way you would declare any
  5266. other text variable:%@NL@%
  5267. %@NL@%
  5268.      %@AB@%VAR%@AE@% %@NL@%
  5269.      %@AI@%FileVar%@AE@%%@AB@% : Text%@AE@%%@NL@%
  5270. %@NL@%
  5271. %@CR:MQP91102@%%@4@%When you later read or write information to the file, you refer to the file%@EH@%
  5272. by the name you give %@AI@%FileVar%@AE@%. For example,%@NL@%
  5273. %@NL@%
  5274. %@AS@%     VAR datafile : Text;%@NL@%
  5275. %@NL@%
  5276. %@CR:MQP91103@%%@4@%creates a file variable with the name %@AS@%datafile%@AE@%.%@EH@%%@NL@%
  5277. %@NL@%
  5278. %@CR:MQP91104@%%@4@%QuickPascal also needs to know what name you want to assign to the text file%@EH@%
  5279. that is saved on the disk. The %@AB@%Assign%@AE@% procedure associates the file variable
  5280. with the disk file name:%@NL@%
  5281. %@NL@%
  5282.      %@AB@%Assign (%@AE@%%@AI@%FileVar%@AE@%%@AB@%,%@AE@% %@AI@%FileName%@AE@%%@AB@%)%@AE@%%@NL@%
  5283. %@NL@%
  5284. %@CR:MQP91105@%%@4@%QuickPascal accepts this assignment as meaning, "Whenever I say to read or%@EH@%
  5285. write to the file variable %@AI@%FileVar%@AE@%, send the information to the disk file
  5286. with the name %@AI@%FileName%@AE@%." You can make the two names similar, but keep in
  5287. mind that %@AI@%FileName%@AE@% must follow the DOS file-naming conventions. For
  5288. instance,%@NL@%
  5289. %@NL@%
  5290. %@AS@%     Assign( datafile, 'RAN_DATA.DAT' );%@NL@%
  5291. %@NL@%
  5292. %@CR:MQP91106@%%@4@%equates the file variable %@AS@%datafile%@AE@% with the disk file %@AS@%RAN_DATA.DAT%@AE@%.%@EH@%%@NL@%
  5293. %@NL@%
  5294. %@CR:MQP91107@%%@4@%For more versatility, you can use a string variable in place of a literal%@EH@%
  5295. string such as %@AS@%'RAN_DATA.DAT'%@AE@%. Using a string variable allows your program
  5296. to prompt for a file name. For example,%@NL@%
  5297. %@NL@%
  5298. %@AS@%     VAR%@NL@%
  5299. %@AS@%         datafile : Text;%@NL@%
  5300. %@AS@%         filename : String;%@NL@%
  5301. %@NL@%
  5302. %@AS@%     BEGIN%@NL@%
  5303. %@AS@%         Write('Enter name of data file to open: ');%@NL@%
  5304. %@AS@%         Readln( filename );%@NL@%
  5305. %@AS@%         Assign( datafile, filename );%@NL@%
  5306. %@AS@%         Reset( datafile );%@NL@%
  5307. %@AS@%         .%@NL@%
  5308. %@AS@%         .%@NL@%
  5309. %@AS@%         .%@NL@%
  5310. %@NL@%
  5311. %@NL@%
  5312. %@CR:MQP91200@%%@3@%%@AB@%9.1.2  Opening a Text File%@AE@%%@EH@%%@NL@%
  5313. %@NL@%
  5314. %@CR:MQP91201@%%@4@%With the file variable and the file name both assigned, you can either%@EH@%
  5315. create (and then open) a new file or open an existing one.%@NL@%
  5316. %@NL@%
  5317. %@CR:MQP91210@%%@4@%%@AB@%9.1.2.1  Opening a New Text File%@AE@%%@EH@%%@NL@%
  5318. %@NL@%
  5319. %@CR:MQP91211@%%@4@%The standard procedure %@AB@%Rewrite%@AE@% creates and opens a new text file. It uses%@EH@%
  5320. the general syntax:%@NL@%
  5321. %@NL@%
  5322.      %@AB@%Rewrite(%@AE@%%@AI@%FileVar%@AE@%%@AB@%)%@AE@%%@NL@%
  5323. %@NL@%
  5324. %@CR:MQP91212@%%@4@%The example program at the beginning of the chapter creates and opens a new%@EH@%
  5325. text file with the line:%@NL@%
  5326. %@NL@%
  5327. %@AS@%     Rewrite( datafile );%@NL@%
  5328. %@NL@%
  5329. %@CR:MQP91213@%%@4@%Since the %@AB@%Assign%@AE@% procedure associated the file variable %@AS@%datafile%@AE@% with the%@EH@%
  5330. name %@AS@%RAN_DATA.DAT%@AE@%, this %@AB@%Rewrite%@AE@% statement creates a new file on the disk
  5331. also called %@AS@%RAN_DATA.DAT%@AE@%.%@NL@%
  5332. %@NL@%
  5333. %@CR:MQP91214@%%@4@%Note that if a file already exists with the same name, %@AB@%Rewrite%@AE@% destroys the%@EH@%
  5334. old file. So, it's best to use only file names you know are "safe," or have
  5335. your program ask the user to confirm the name selected.%@NL@%
  5336. %@NL@%
  5337. %@CR:MQP91215@%%@4@%Once you open a new file, you can immediately write new text to it.%@EH@%%@NL@%
  5338. %@NL@%
  5339. %@CR:MQP91220@%%@4@%%@AB@%9.1.2.2  Opening an Existing Text File%@AE@%%@EH@%%@NL@%
  5340. %@NL@%
  5341. %@CR:MQP91221@%%@4@%You can perform both read and write operations with an existing text file.%@EH@%
  5342. Keep in mind, however, that trying to open a nonexistent file causes a "File
  5343. not found" run-time error. A short procedure that verifies the existence of
  5344. the file could save you some time.%@NL@%
  5345. %@NL@%
  5346. %@CR:MQP91222@%%@4@%To open files for reading data, use the %@AB@%Reset%@AE@% procedure:%@EH@%%@NL@%
  5347. %@NL@%
  5348.      %@AB@%Reset(%@AE@%%@AI@%FileVar%@AE@%%@AB@%)%@AE@%%@NL@%
  5349. %@NL@%
  5350. %@CR:MQP91223@%%@4@%For example, to open the file named %@AS@%RAN_DATA.DAT%@AE@% created by this chapter's%@EH@%
  5351. example program, you would use%@NL@%
  5352. %@NL@%
  5353. %@AS@%     Reset( datafile );%@NL@%
  5354. %@NL@%
  5355. %@CR:MQP91224@%%@4@%%@AB@%Reset%@AE@% opens the file and moves the "file pointer" (an internal bookmark that%@EH@%
  5356. tells the program where it is in the file) to the first character in the
  5357. file, ready to begin reading.%@NL@%
  5358. %@NL@%
  5359. %@CR:MQP91225@%%@4@%If you want to add text to the end of an existing file, open the file with%@EH@%
  5360. the %@AB@%Append%@AE@% procedure:%@NL@%
  5361. %@NL@%
  5362.      %@AB@%Append(%@AE@%%@AI@%FileVar%@AE@%%@AB@%)%@AE@%%@NL@%
  5363. %@NL@%
  5364. %@CR:MQP91226@%%@4@%To append data to the %@AS@%RAN_DATA.DAT%@AE@% file, type in:%@EH@%%@NL@%
  5365. %@NL@%
  5366. %@AS@%     Append( datafile );%@NL@%
  5367. %@NL@%
  5368. %@CR:MQP91227@%%@4@%This opens the file and sets the file pointer to the end of the file. Text%@EH@%
  5369. that is currently in the file remains unaltered.%@NL@%
  5370. %@NL@%
  5371. %@CR:MQP91228@%%@4@%Once you open a file, you can immediately read text from it or write new%@EH@%
  5372. text to it.%@NL@%
  5373. %@NL@%
  5374. %@NL@%
  5375. %@CR:MQP91300@%%@3@%%@AB@%9.1.3  Writing Text to a File%@AE@%%@EH@%%@NL@%
  5376. %@NL@%
  5377. %@CR:MQP91301@%%@4@%You write to a text file in much the same way as you write to the screen.%@EH@%
  5378. You still use the %@AB@%Write%@AE@% or %@AB@%Writeln%@AE@% procedure and any of its standard
  5379. formatting codes, but you specify the file variable as well.%@NL@%
  5380. %@NL@%
  5381. %@CR:MQP91302@%%@4@%In the example at the beginning of this chapter, the loop%@EH@%%@NL@%
  5382. %@NL@%
  5383. %@AS@%     FOR i := 1 TO 100 DO%@NL@%
  5384. %@AS@%        BEGIN%@NL@%
  5385. %@AS@%        Writeln( datafile, Random(50) );%@NL@%
  5386. %@AS@%        END;%@NL@%
  5387. %@NL@%
  5388. %@CR:MQP91303@%%@4@%sends %@AS@%100%@AE@% random integers to the %@AS@%RAN_DATA.DAT%@AE@% text file specified by the%@EH@%
  5389. %@AS@%datafile%@AE@% file variable.%@NL@%
  5390. %@NL@%
  5391. %@CR:MQP91304@%%@4@%You can just as easily write text or formatted numbers to the file, but%@EH@%
  5392. remember that even formatted numbers are stored in the file as text. Any
  5393. acceptable form of %@AB@%Write%@AE@% or %@AB@%Writeln%@AE@% can send data to a text file.%@NL@%
  5394. %@NL@%
  5395. %@NL@%
  5396. %@CR:MQP91400@%%@3@%%@AB@%9.1.4  Reading Text from a File%@AE@%%@EH@%%@NL@%
  5397. %@NL@%
  5398. %@CR:MQP91401@%%@4@%Use the %@AB@%Read%@AE@% or %@AB@%Readln%@AE@% procedure to read data from an open text file,%@EH@%
  5399. specifying the file variable. For example,%@NL@%
  5400. %@NL@%
  5401. %@AS@%     Readln( datafile, line_o_text );%@NL@%
  5402. %@NL@%
  5403. %@CR:MQP91402@%%@4@%reads a line of text from the text file associated with the variable%@EH@%
  5404. %@AS@%datafile%@AE@% into the string %@AS@%line_o_text%@AE@%. %@AB@%Read%@AE@% has the same effect but reads one
  5405. variable at a time rather than an entire line.%@NL@%
  5406. %@NL@%
  5407. %@CR:MQP91403@%%@4@%In the example at the beginning of this chapter, with the %@AB@%FOR%@AE@% loop, the%@EH@%
  5408. program creates a file called %@AS@%RAN_DATA.DAT%@AE@% filled with 100 random numbers
  5409. between 0 and 50 (some numbers appear more than once). You could write a
  5410. nearly identical program to read the data back from the file by altering the
  5411. loop to%@NL@%
  5412. %@NL@%
  5413. %@AS@%     FOR i := 1 TO 100 DO%@NL@%
  5414. %@AS@%         BEGIN%@NL@%
  5415. %@AS@%         Readln( datafile, random_number_string );%@NL@%
  5416. %@AS@%         END;%@NL@%
  5417. %@NL@%
  5418. %@CR:MQP91404@%%@4@%%@AB@%Readln%@AE@% replaces %@AB@%Writeln%@AE@%, and you must declare %@AS@%random_number_string%@AE@% as a%@EH@%
  5419. variable of type %@AB@%STRING%@AE@%. (You would also need to open the file for reading
  5420. with %@AB@%Reset%@AE@% rather than writing.) To change %@AS@%random_number_string%@AE@% back into
  5421. numerical data, you need to add%@NL@%
  5422. %@NL@%
  5423. %@AS@%     Val( random_number_string, ran_num, errpos )%@NL@%
  5424. %@NL@%
  5425. %@CR:MQP91405@%%@4@%after the %@AB@%Readln%@AE@% procedure. (You would also need to declare %@AS@%ran_num%@AE@% and%@EH@%
  5426. %@AS@%errpos%@AE@% as integers.) In cases where you don't know the length of a file in
  5427. advance, you can use a loop that checks for the end of the file with the %@AB@%Eof%@AE@%
  5428. function. For example, if you didn't know the length of the %@AS@%RAN_DATA.DAT%@AE@%
  5429. file, you could rewrite the previous loop as%@NL@%
  5430. %@NL@%
  5431. %@AS@%     WHILE NOT Eof( datafile ) DO%@NL@%
  5432. %@AS@%         BEGIN%@NL@%
  5433. %@AS@%         Readln( datafile, random_number_string );%@NL@%
  5434. %@AS@%         Writeln( random_number_string );%@NL@%
  5435. %@AS@%         END;%@NL@%
  5436. %@NL@%
  5437. %@CR:MQP91406@%%@4@%%@AB@%Eof%@AE@% returns a Boolean result. It returns %@AB@%False%@AE@% as you read through the%@EH@%
  5438. contents of a file and %@AB@%True%@AE@% after you read the file's last entry. The
  5439. end-of-line function, %@AB@%Eoln%@AE@%, works in a similar manner, but returns True when
  5440. you reach the end of a line.%@NL@%
  5441. %@NL@%
  5442. %@NL@%
  5443. %@CR:MQP91500@%%@3@%%@AB@%9.1.5  Closing a Text File%@AE@%%@EH@%%@NL@%
  5444. %@NL@%
  5445. %@CR:MQP91501@%%@4@%You need to close a file when you finish working with it. All files close%@EH@%
  5446. with the same instruction:%@NL@%
  5447. %@NL@%
  5448.      %@AB@%Close(%@AE@%%@AI@%FileVar%@AE@%%@AB@%)%@AE@%%@NL@%
  5449. %@NL@%
  5450. %@CR:MQP91502@%%@4@%where %@AI@%FileVar%@AE@% specifies an open file.%@EH@%%@NL@%
  5451. %@NL@%
  5452. %@CR:MQP91503@%%@4@%Trying to close a file that is not open causes a run-time error. However,%@EH@%
  5453. unless you use a number of similarly named file variables, the compiler
  5454. usually catches potential errors as either undefined variables (often caused
  5455. by typing mistakes) or type mismatches (caused by placing a non-%@AB@%Text%@AE@%
  5456. variable in the place of a file variable).%@NL@%
  5457. %@NL@%
  5458. %@CR:MQP91504@%%@4@%For example, trying to compile the program from the beginning of this%@EH@%
  5459. chapter with the line%@NL@%
  5460. %@NL@%
  5461. %@AS@%     Close( datfile );  { 'datafile' misspelled }%@NL@%
  5462. %@NL@%
  5463. %@CR:MQP91505@%%@4@%results in an %@AS@%Unknown identifier%@AE@% compiler error.%@EH@%%@NL@%
  5464. %@NL@%
  5465. %@CR:MQP91506@%%@4@%QuickPascal automatically closes any text files still open when a program%@EH@%
  5466. ends.%@NL@%
  5467. %@NL@%
  5468. %@NL@%
  5469. %@CR:MQP92000@%%@2@%%@AB@%9.2  Increasing the Speed for Input and Output%@AE@%%@EH@%%@NL@%
  5470. %@NL@%
  5471. %@CR:MQP92001@%%@4@%The run-time system employs a buffer that temporarily collects text during%@EH@%
  5472. %@AB@%Read%@AE@% and %@AB@%Write%@AE@% operations to text files. By default, the run-time system
  5473. uses a 128-byte buffer.%@NL@%
  5474. %@NL@%
  5475. %@CR:MQP92002@%%@4@%Larger buffers enhance the speed of I/O-intensive programs, but tend not to%@EH@%
  5476. affect programs with moderate or low levels of I/O activity. The larger the
  5477. buffer, the greater the speed. However, unless your programs bog down due to
  5478. I/O operations specifically, the default buffer size usually suffices. Keep
  5479. in mind that while increasing the buffer size can speed up a program, it
  5480. also increases the program's size.%@NL@%
  5481. %@NL@%
  5482. %@CR:MQP92003@%%@4@%The standard procedure %@AB@%SetTextBuf%@AE@% lets you allocate different buffer sizes.%@EH@%
  5483. It uses the general syntax%@NL@%
  5484. %@NL@%
  5485.      %@AB@%SetTextBuf(%@AE@%%@AI@%FileVar%@AE@%%@AB@%,%@AE@% %@AI@%Buffer%@AE@%«%@AB@%, %@AE@%%@AI@%Size%@AE@%»%@AB@%)%@AE@%%@NL@%
  5486. %@NL@%
  5487. %@CR:MQP92004@%%@4@%where %@AI@%Buffer%@AE@% refers to a variable to use as the buffer and %@AI@%Size%@AE@% optionally%@EH@%
  5488. indicates the size of the buffer in bytes. You can declare %@AI@%Buffer%@AE@% as any
  5489. type of variable, but you usually use an array of type %@AB@%Char%@AE@%. For example, if
  5490. you wanted to increase the buffer size of the program presented earlier, you
  5491. could rewrite the beginning as%@NL@%
  5492. %@NL@%
  5493. %@AS@%     PROGRAM filetest;%@NL@%
  5494. %@AS@%     VAR%@NL@%
  5495. %@AS@%         datafile : Text;%@NL@%
  5496. %@AS@%         i        : Integer;%@NL@%
  5497. %@AS@%         buffer   : ARRAY[1..2048] OF Char;%@NL@%
  5498. %@NL@%
  5499. %@AS@%     BEGIN%@NL@%
  5500. %@AS@%         Assign( datafile, 'RAN_DATA.DAT' );%@NL@%
  5501. %@AS@%         Rewrite( datafile );%@NL@%
  5502. %@AS@%         SetTextBuf( datafile, buffer );%@NL@%
  5503. %@AS@%         .%@NL@%
  5504. %@AS@%         .%@NL@%
  5505. %@AS@%         .%@NL@%
  5506. %@NL@%
  5507. %@CR:MQP92005@%%@4@%This call to %@AB@%SetTextBuf%@AE@% provides a large array for intermediate storage.%@EH@%
  5508. It's something of an overkill for a group of 100 random integers (based on
  5509. the rest of the example), but would work well for reading or writing large
  5510. text files.%@NL@%
  5511. %@NL@%
  5512. ───────────────────────────────────────────────────────────────────────────%@NL@%
  5513. %@AI@%WARNING%@AE@%%@NL@%
  5514.    Buffer allocation must occur before or immediately after you open the%@NL@%
  5515.    text file. Changing the file buffer size after I/O operations have%@NL@%
  5516.    already occurred can lead to data loss.%@NL@%
  5517. ───────────────────────────────────────────────────────────────────────────%@NL@%
  5518. %@NL@%
  5519. %@NL@%
  5520. %@CR:MQP93000@%%@2@%%@AB@%9.3  Redirecting Text Output%@AE@%%@EH@%%@NL@%
  5521. %@NL@%
  5522. %@CR:MQP93001@%%@4@%QuickPascal lets you access a number of standard DOS devices (such as a%@EH@%
  5523. printer and the screen) by specifying the device as an output file name. For
  5524. example, by reassigning the file variable, the same %@AB@%Writeln%@AE@% statement could
  5525. send text data to a disk file, the printer, or the screen.%@NL@%
  5526. %@NL@%
  5527. %@CR:MQP93002@%%@4@%DOS devices use predefined names. The two most common are the printer name,%@EH@%
  5528. PRN (assumed to connect to the LPT1 port), and the screen name, CON (short
  5529. for "console"). Data sent to a device goes to the appropriate computer port.%@NL@%
  5530. %@NL@%
  5531. %@CR:MQP93003@%%@4@%To see how reassignment works, consider a program that, at the end of a%@EH@%
  5532. particularly grueling data-generating session, presents the user with a
  5533. choice of sending the data to the printer, console, or file. Based on the
  5534. selection, the program assigns a file variable to the appropriate device or
  5535. text file.%@NL@%
  5536. %@NL@%
  5537. %@CR:MQP93004@%%@4@%If %@AS@%OutFileVar%@AE@% is the file variable, choosing the printer leads to the%@EH@%
  5538. assignment%@NL@%
  5539. %@NL@%
  5540. %@AS@%     Assign( OutFileVar, 'PRN' );%@NL@%
  5541. %@NL@%
  5542. %@CR:MQP93005@%%@4@%to direct the output to the printer. (You could also get the same effect by%@EH@%
  5543. using the %@AB@%Printer%@AE@% unit and substituting %@AS@%LST%@AE@% for the file variable. %@AB@%Printer%@AE@%
  5544. provides the %@AS@%LST%@AE@% text file variable already opened on the LPT1 printer
  5545. port.)%@NL@%
  5546. %@NL@%
  5547. %@CR:MQP93006@%%@4@%Similarly,%@EH@%%@NL@%
  5548. %@NL@%
  5549. %@AS@%     Assign( OutFileVar, 'CON' );%@NL@%
  5550. %@NL@%
  5551. %@CR:MQP93007@%%@4@%and%@EH@%%@NL@%
  5552. %@NL@%
  5553. %@AS@%     Assign( OutFileVar, NewFile );%@NL@%
  5554. %@NL@%
  5555. %@CR:MQP93008@%%@4@%direct the output to the screen and a disk file, respectively. (%@AS@%NewFile%@AE@%%@EH@%
  5556. must be declared as a string, and must contain the name of the new disk
  5557. file.)%@NL@%
  5558. %@NL@%
  5559. %@CR:MQP93009@%%@4@%The file variable %@AS@%OutFileVar%@AE@% now refers to the correct output location,%@EH@%
  5560. regardless of whether that output is the printer, screen, or a new text
  5561. file. The program opens the device or file with%@NL@%
  5562. %@NL@%
  5563. %@AS@%     Rewrite( OutFileVar );%@NL@%
  5564. %@NL@%
  5565. %@CR:MQP9300A@%%@4@%sends the data to the file with%@EH@%%@NL@%
  5566. %@NL@%
  5567. %@AS@%     Writeln( OutFileVar, TextOut );%@NL@%
  5568. %@NL@%
  5569. %@CR:MQP9300B@%%@4@%and closes the file when finished with%@EH@%%@NL@%
  5570. %@NL@%
  5571. %@AS@%     Close( OutFileVar );%@NL@%
  5572. %@NL@%
  5573. %@CR:MQP9300C@%%@4@%With some planning, the same section of program code can perform three%@EH@%
  5574. different functions: print data, send to the screen, or send to a file. The
  5575. only difference is the file name assigned to the file variable. In the
  5576. example above, a %@AB@%CASE%@AE@% statement, or similar decision-making structure, would
  5577. assign an appropriate file-name variable based on the user's menu selection.%@NL@%
  5578. %@NL@%
  5579. %@NL@%
  5580. %@CR:MQP94000@%%@2@%%@AB@%9.4  Standard Procedures and Functions for Input and Output%@AE@%%@EH@%%@NL@%
  5581. %@NL@%
  5582. %@CR:MQP94001@%%@4@%A number of the QuickPascal standard procedures and functions apply to all%@EH@%
  5583. types of data files──text, typed, and untyped. Table 9.1%@BO:   43776@% summarizes those
  5584. procedures and functions available to all file types.%@NL@%
  5585. %@NL@%
  5586. %@CR:MQP9T100@%%@4@%%@AB@%Table 9.1  Standard Procedures and Functions for All File Types%@AE@%%@EH@%%@NL@%
  5587. %@NL@%
  5588. %@AB@%Routine           Purpose%@AE@%%@NL@%
  5589. %@NL@%
  5590. %@AB@%Assign%@AE@%            Associates a file buffer with a filename%@NL@%
  5591. %@NL@%
  5592. %@AB@%Close%@AE@%             Closes the file buffer%@NL@%
  5593. %@NL@%
  5594. %@AB@%Eof%@AE@%               Returns the end-of-file status%@NL@%
  5595. %@NL@%
  5596. %@AB@%Erase%@AE@%             Deletes a file%@NL@%
  5597. %@NL@%
  5598. %@AB@%IOResult%@AE@%          Returns the error status of the last I/O%@NL@%
  5599. %@NL@%
  5600. %@AB@%Read%@AE@%              Reads one or more elements from a file%@NL@%
  5601. %@NL@%
  5602. %@AB@%Rename%@AE@%            Renames a file%@NL@%
  5603. %@NL@%
  5604. %@AB@%Reset%@AE@%             Opens an existing file%@NL@%
  5605. %@NL@%
  5606. %@AB@%Rewrite%@AE@%           Creates and opens a new file, after closing and erasing%@NL@%
  5607.                   any file with the same name%@NL@%
  5608. %@NL@%
  5609. %@AB@%Write%@AE@%             Writes one or more elements to a file%@NL@%
  5610.  
  5611. %@CR:MQP94002@%%@4@%Several other standard procedures and functions apply only to text files.%@EH@%
  5612. They appear in Table 9.2%@BO:   43bda@% below.%@NL@%
  5613. %@NL@%
  5614. %@CR:MQP9T200@%%@4@%%@AB@%Table 9.2  Standard Procedures and Functions for Text Files%@AE@%%@EH@%%@NL@%
  5615. %@NL@%
  5616. %@AB@%Routine           Purpose%@AE@%%@NL@%
  5617. %@NL@%
  5618. %@AB@%Append%@AE@%            Opens an existing text file for adding more text to the%@NL@%
  5619.                   end of the file%@NL@%
  5620. %@NL@%
  5621. %@AB@%Eoln%@AE@%              Returns the end-of-line status%@NL@%
  5622. %@NL@%
  5623. %@AB@%Flush%@AE@%             Clears the text buffer%@NL@%
  5624. %@NL@%
  5625. %@AB@%Readln%@AE@%            Reads one or more data items, one line at a time%@NL@%
  5626. %@NL@%
  5627. %@AB@%SeekEof%@AE@%           Returns the end-of-file status, ignoring any blanks, tabs,%@NL@%
  5628.                   and end-of-line markers%@NL@%
  5629. %@NL@%
  5630. %@AB@%SeekEoln%@AE@%          Returns the end-of-line status, ignoring any blanks and%@NL@%
  5631.                   tabs%@NL@%
  5632. %@NL@%
  5633. %@AB@%SetTextBuf%@AE@%        Assigns a text file I/O buffer%@NL@%
  5634. %@NL@%
  5635. %@AB@%Writeln%@AE@%           Writes one or more data items and appends an end-of-line%@NL@%
  5636.                   marker%@NL@%
  5637. %@NL@%
  5638. %@NL@%
  5639. %@CR:MQPA0000@%%@1@%%@AB@%Chapter 10  Binary Files%@AE@%%@EH@%%@NL@%
  5640. ───────────────────────────────────────────────────────────────────────────%@NL@%
  5641. %@NL@%
  5642. %@CR:MQPA0001@%%@4@%A binary file contains program data stored on disk. Each item in a binary%@EH@%
  5643. file is stored in the same binary representation used by a QuickPascal
  5644. program. Binary files provide optimal storage of numbers, Booleans, and
  5645. enumerated types. For example, to store the integer 21,000 in a text file,
  5646. you write a string of at least five characters to disk. To store the number
  5647. in a binary file, you write just two bytes. However, you cannot display a
  5648. binary file directly or view it with a word processor.%@NL@%
  5649. %@NL@%
  5650. %@CR:MQPA0002@%%@4@%You access each binary file as either a typed file or an untyped file:%@EH@%%@NL@%
  5651. %@NL@%
  5652. %@CR:MQPA0003@%  ■  A "typed file" contains a series of discrete units called%@NL@%
  5653.      "components." Each component must have the same type, which can be%@NL@%
  5654.      almost any data type supported by QuickPascal but is typically a%@NL@%
  5655.      record.%@NL@%
  5656. %@NL@%
  5657.   ■  An "untyped file"  is treated as a raw, unstructured series of bytes.%@NL@%
  5658.      None of the text-oriented read and write functions is available.%@NL@%
  5659.      Typically, programs use untyped files for large block operations such%@NL@%
  5660.      as copying an entire file to another. Any file can be declared as an%@NL@%
  5661.      untyped file.%@NL@%
  5662. %@NL@%
  5663. %@NL@%
  5664. %@CR:MQPA1000@%%@2@%%@AB@%10.1  Typed Files%@AE@%%@EH@%%@NL@%
  5665. %@NL@%
  5666. %@CR:MQPA1001@%%@4@%Like an array, a typed file is a series of components all having the same%@EH@%
  5667. type. Unlike an array, a typed file has no definite size. A file starts at
  5668. length zero and automatically grows as you append data. Furthermore, files
  5669. serve as permanent records that exist after the program terminates.%@NL@%
  5670. %@NL@%
  5671. %@CR:MQPA1002@%%@4@%In essence, typed files are formatted data files. The format is determined%@EH@%
  5672. by the component type, which you should choose carefully to solve a given
  5673. programming task. For example, to implement an airline reservation system,
  5674. you would set up a record type to store all of the needed data for one
  5675. reservation. Then you might create a file made up of these records. Every
  5676. program in the system must use this same record type to correctly read the
  5677. file.%@NL@%
  5678. %@NL@%
  5679. %@CR:MQPA1003@%%@4@%The structure of a typed file supports random access. For example, in a file%@EH@%
  5680. of records, you can directly access record 367 without having to read
  5681. through the first 366.%@NL@%
  5682. %@NL@%
  5683. %@NL@%
  5684. %@CR:MQPA1100@%%@3@%%@AB@%10.1.1  Declaring Typed Files%@AE@%%@EH@%%@NL@%
  5685. %@NL@%
  5686. %@CR:MQPA1101@%%@4@%Not surprisingly, the syntax for defining a typed file is similar to that%@EH@%
  5687. for arrays:%@NL@%
  5688. %@NL@%
  5689.      %@AB@%FILE OF %@AE@%%@AI@%ComponentType%@AE@%%@NL@%
  5690. %@NL@%
  5691. %@CR:MQPA1102@%%@4@%In the syntax display above, %@AI@%ComponentType%@AE@% can be any valid data type, with%@EH@%
  5692. one restriction: the component type cannot be a file type or a type that
  5693. contains a file type. Thus, files of arrays are legal, as are arrays of
  5694. files. However, a file of arrays of files is illegal.%@NL@%
  5695. %@NL@%
  5696. %@CR:MQPA1103@%%@4@%The component type is frequently a record. (In fact, other programming%@EH@%
  5697. languages often use the term "record" to refer to a component of a file.)
  5698. For example, you might define a record type to hold a name and phone number
  5699. for one person. To create a permanent list of phone numbers for many people,
  5700. you could create a file made up of these records.%@NL@%
  5701. %@NL@%
  5702. %@CR:MQPA1104@%%@4@%The following code shows examples of valid file types:%@EH@%%@NL@%
  5703. %@NL@%
  5704. %@AS@%     TYPE%@NL@%
  5705. %@AS@%         phonerec = RECORD%@NL@%
  5706. %@AS@%             name          : STRING[20];%@NL@%
  5707. %@AS@%             long_distance : Boolean;%@NL@%
  5708. %@AS@%             phone         : LongInt;%@NL@%
  5709. %@AS@%             END;%@NL@%
  5710. %@NL@%
  5711. %@AS@%         phone_list = FILE OF phonerec;%@NL@%
  5712. %@AS@%         math_file = FILE OF ARRAY[1..10] OF Real;%@NL@%
  5713. %@AS@%     VAR%@NL@%
  5714. %@AS@%         master_list   : ARRAY[1..20] OF phone_list;%@NL@%
  5715. %@AS@%         celebs        : phone_list;%@NL@%
  5716. %@AS@%         lucky_numbers : FILE OF Integer;%@NL@%
  5717. %@NL@%
  5718. %@NL@%
  5719. %@CR:MQPA1200@%%@3@%%@AB@%10.1.2  Accessing Data in a Typed File%@AE@%%@EH@%%@NL@%
  5720. %@NL@%
  5721. %@CR:MQPA1201@%%@4@%After declaring a file variable, you may assign it to a physical disk file%@EH@%
  5722. with the %@AB@%Assign%@AE@% procedure, as described in the last chapter. Then you can
  5723. open the file for writing (with %@AB@%Rewrite%@AE@%) or for both reading and writing
  5724. (with %@AB@%Reset%@AE@%).%@NL@%
  5725. %@NL@%
  5726. %@CR:MQPA1202@%%@4@%For example, the following code declares a file of integers, assigns the%@EH@%
  5727. file variable to the disk file MYFILE.DAT (in the root directory of drive
  5728. C:), and then opens the file for reading and writing:%@NL@%
  5729. %@NL@%
  5730. %@AS@%     VAR%@NL@%
  5731. %@AS@%         intfile : FILE OF Integer;%@NL@%
  5732. %@AS@%     BEGIN%@NL@%
  5733. %@AS@%         Assign( intfile, 'C:\MYFILE.DAT' );%@NL@%
  5734. %@AS@%         Reset( intfile );%@NL@%
  5735. %@NL@%
  5736. %@CR:MQPA1203@%%@4@%After you open the file, you can read and write any number of components%@EH@%
  5737. sequentially with the %@AB@%Read%@AE@% and %@AB@%Write%@AE@% procedures. (The next section shows how
  5738. to use random access.) These procedures work with both text files and typed
  5739. files, and take the same syntax in either case. But with typed files, each
  5740. item you read or write must be a variable of the component type.%@NL@%
  5741. %@NL@%
  5742. %@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@%
  5743. variables, you can read or write the file as follows:%@NL@%
  5744. %@NL@%
  5745. %@AS@%     Write( int_file, a,b,c );  { Write a, b, c to the file }%@NL@%
  5746. %@AS@%     Read( int_file, n );       { Read next integer in file }%@NL@%
  5747. %@NL@%
  5748. %@CR:MQPA1205@%%@4@%The %@AB@%Read%@AE@% and %@AB@%Write%@AE@% procedures do not do any text formatting when used with%@EH@%
  5749. typed files. In the example above, the procedures read and write the numeric
  5750. value of the integers directly to and from the disk. If %@AS@%int_file%@AE@% were a text
  5751. file, the %@AB@%Read%@AE@% procedure would translate the numbers to character strings
  5752. before writing them.%@NL@%
  5753. %@NL@%
  5754. %@CR:MQPA1206@%%@4@%As you read components of a file, use the %@AB@%Eof%@AE@% function or %@AB@%FileSize%@AE@% function%@EH@%
  5755. (described below) to make sure you don't read past the end of the file. The
  5756. %@AB@%Eof%@AE@% function returns %@AB@%True%@AE@% if the last read operation took you beyond the end
  5757. of the file.%@NL@%
  5758. %@NL@%
  5759. %@CR:MQPA1207@%%@4@%You can use a number of other procedures with typed files, including the%@EH@%
  5760. procedures listed in Table 9.1%@BO:   43776@% in Chapter 9, "Text Files." In addition, you
  5761. can use those listed below.%@NL@%
  5762. %@NL@%
  5763. %@CR:MQPA1208@%%@AB@%Procedure                  Description     %@AE@%%@NL@%
  5764. %@NL@%
  5765. %@AB@%FilePos%@AE@%                     Takes a file variable as a parameter, and%@NL@%
  5766.                             returns the current file position (in terms of%@NL@%
  5767.                             components or blocks)%@NL@%
  5768. %@NL@%
  5769. %@AB@%FileSize%@AE@%                    Takes a file variable as a parameter, and%@NL@%
  5770.                             returns the size of the file in bytes; result%@NL@%
  5771.                             has type %@AB@%LongInt%@AE@%%@NL@%
  5772. %@NL@%
  5773. %@AB@%Seek%@AE@%                        Takes a file variable and a long integer as%@NL@%
  5774.                             parameters, and moves the file position to the%@NL@%
  5775.                             component or block designated by the integer%@NL@%
  5776. %@NL@%
  5777. %@AB@%Truncate%@AE@%                    Takes a file variable as a parameter, and%@NL@%
  5778.                             truncates the file at the current file position%@NL@%
  5779. %@NL@%
  5780. %@CR:MQPA1209@%%@4@%The %@AB@%FilePos%@AE@% and %@AB@%Seek%@AE@% procedures let you treat a binary file as a%@EH@%
  5781. random-access file, and the next section provides more detail on how to use
  5782. them. Note that you do not have to treat a typed file as strictly a
  5783. sequential or random-access file. You can use any combination of functions
  5784. supported for the file type.%@NL@%
  5785. %@NL@%
  5786. %@NL@%
  5787. %@CR:MQPA1300@%%@3@%%@AB@%10.1.3  Using Random Access%@AE@%%@EH@%%@NL@%
  5788. %@NL@%
  5789. %@CR:MQPA1301@%%@4@%You can use random-access procedures with any typed file. "Random access" is%@EH@%
  5790. the capability to read or write components to any place in the file and in
  5791. any order.%@NL@%
  5792. %@NL@%
  5793. %@CR:MQPA1302@%%@4@%Random access is like placing a phone call. You can immediately connect to%@EH@%
  5794. any place in the system by giving the right number. Sequential access is
  5795. like reading a novel. You advance from one page to the next in the order
  5796. given.%@NL@%
  5797. %@NL@%
  5798. %@CR:MQPA1303@%%@4@%The two principal random-access procedures are %@AB@%Seek%@AE@% and %@AB@%FilePos%@AE@%. The %@AB@%Seek%@AE@%%@EH@%
  5799. procedure sets the file buffer to the component denoted by the number you
  5800. specify. The first component is denoted by 0, the second by 1, and so on.
  5801. The syntax is%@NL@%
  5802. %@NL@%
  5803.      %@AB@%Seek (%@AE@%%@AI@%FileVar%@AE@%%@AB@%, %@AE@%%@AI@%Position%@AE@%%@AB@%)%@AE@%%@NL@%
  5804. %@NL@%
  5805. %@CR:MQPA1304@%%@4@%in which %@AI@%FileVar%@AE@% is a file variable, and %@AI@%Position%@AE@% is a constant or variable%@EH@%
  5806. of type %@AB@%LongInt%@AE@%. For example:%@NL@%
  5807. %@NL@%
  5808. %@AS@%     TYPE%@NL@%
  5809. %@AS@%        phone_rec = RECORD%@NL@%
  5810. %@AS@%            name,%@NL@%
  5811. %@AS@%            notes : STRING;%@NL@%
  5812. %@AS@%            number : LongInt;%@NL@%
  5813. %@AS@%            END;%@NL@%
  5814. %@AS@%     VAR%@NL@%
  5815. %@AS@%         phone_list : FILE OF phone_rec;%@NL@%
  5816. %@AS@%         rec10, rec11, rec15, rec25 : phone_rec;%@NL@%
  5817. %@AS@%     BEGIN%@NL@%
  5818. %@AS@%         Assign( phone_list, 'FONEHOME.DAT' );%@NL@%
  5819. %@AS@%         Reset( phone_list );%@NL@%
  5820. %@AS@%         Seek( phone_list, 9 );    { Get 10th & 11th record }%@NL@%
  5821. %@AS@%         Read( phone_list, rec10, rec11 );%@NL@%
  5822. %@AS@%         Seek( phone_list, 14 );    { Get 15th record }%@NL@%
  5823. %@AS@%         Read( phone_list, rec15 );%@NL@%
  5824. %@AS@%         Seek( phone_list, 24 );    { Get 25th record }%@NL@%
  5825. %@AS@%         Read( phone_list, rec25 );%@NL@%
  5826. %@NL@%
  5827. %@CR:MQPA1305@%%@4@%The example above copies records at predefined locations in the file. More%@EH@%
  5828. often, a practical application determines the record number interactively.
  5829. For example, the following code prompts the user for the record number and
  5830. data, then enters this data into the file:%@NL@%
  5831. %@NL@%
  5832. %@AS@%     VAR%@NL@%
  5833. %@AS@%         phone_list : FILE OF phone_rec;%@NL@%
  5834. %@AS@%         temp_rec : phone_rec;%@NL@%
  5835. %@AS@%         n : LongInt;%@NL@%
  5836. %@AS@%     BEGIN%@NL@%
  5837. %@AS@%         Assign( phone_list, 'FONEHOME.DAT' );%@NL@%
  5838. %@AS@%         Reset( phone_list );%@NL@%
  5839. %@AS@%         Write( 'Enter record number: ' );%@NL@%
  5840. %@AS@%         Readln( n );%@NL@%
  5841. %@AS@%         Write( 'Enter name: ' );  { Prompt for data }%@NL@%
  5842. %@AS@%         Readln( temp_rec.name );%@NL@%
  5843. %@AS@%         Write( 'Enter number: ' );%@NL@%
  5844. %@AS@%         Readln( temp_rec.number );%@NL@%
  5845. %@AS@%         Seek( phone_list, n );  { Access record requested }%@NL@%
  5846. %@AS@%         Write( phone_list, temp_rec ); { Write data to file }%@NL@%
  5847. %@NL@%
  5848. %@CR:MQPA1306@%%@4@%The %@AB@%FilePos%@AE@% function takes a file variable as a parameter and returns the%@EH@%
  5849. number (again, a %@AB@%LongInt%@AE@%) of the current component.%@NL@%
  5850. %@NL@%
  5851. %@CR:MQPA1307@%%@4@%The %@AB@%Eof%@AE@% function is useful for both sequential-access and random-access%@EH@%
  5852. operations. This function takes a file variable as its parameter and returns
  5853. %@AB@%True%@AE@% if the current component is past the end of the file. Thus, it tells
  5854. you when you have read to the end of the file or have a record number
  5855. corresponding to a nonexistent file component.%@NL@%
  5856. %@NL@%
  5857. %@CR:MQPA1308@%%@4@%So far, you have seen how to read and overwrite existing files. You can%@EH@%
  5858. append the end of files with%@NL@%
  5859. %@NL@%
  5860.      %@AB@%Seek(%@AE@%%@AI@%f%@AE@%%@AB@%, FilePos(%@AE@%%@AI@%f%@AE@%%@AB@%))%@AE@%%@NL@%
  5861. %@NL@%
  5862. %@CR:MQPA1309@%%@4@%and rewrite files completely with the %@AB@%Rewrite%@AE@% procedure. But there is no%@EH@%
  5863. easy way to insert new components into the middle of a file. The only way to
  5864. insert a component is to read an entire file into memory, manipulate the
  5865. contents, and write the file to disk again.%@NL@%
  5866. %@NL@%
  5867. %@NL@%
  5868. %@CR:MQPA2000@%%@2@%%@AB@%10.2  Untyped Files%@AE@%%@EH@%%@NL@%
  5869. %@NL@%
  5870. %@CR:MQPA2001@%%@4@%Untyped file variables support direct, low-level I/O operations with any%@EH@%
  5871. file. The %@AB@%BlockRead%@AE@% and %@AB@%BlockWrite%@AE@% functions used with untyped files allow
  5872. for fast data transfer for copy and backup of files. You can also use
  5873. untyped file I/O to create sequential binary files with variable-length
  5874. records.%@NL@%
  5875. %@NL@%
  5876. %@CR:MQPA2002@%%@4@%Untyped files differ from typed files in that%@EH@%%@NL@%
  5877. %@NL@%
  5878. %@CR:MQPA2003@%  ■  Untyped files can contain any type of data, even text.%@NL@%
  5879. %@NL@%
  5880.   ■  Untyped files can be read or written with any record length using%@NL@%
  5881.      %@AB@%BlockRead%@AE@% and %@AB@%BlockWrite%@AE@%.%@NL@%
  5882. %@NL@%
  5883. %@CR:MQPA2004@%%@4@%To declare a type or variable as an untyped file, just use the %@AB@%FILE%@AE@% keyword.%@EH@%
  5884. For example,%@NL@%
  5885. %@NL@%
  5886. %@AS@%     TYPE%@NL@%
  5887. %@AS@%         low_level = FILE;%@NL@%
  5888. %@AS@%     VAR%@NL@%
  5889. %@AS@%         my_file : low_level;%@NL@%
  5890. %@NL@%
  5891. %@CR:MQPA2005@%%@4@%The %@AB@%Read%@AE@% and %@AB@%Write%@AE@% procedures, supported for use with text files and typed%@EH@%
  5892. files, are not supported with untyped files. (Otherwise, any procedure
  5893. supported for typed files is also supported for untyped files.) Instead, use
  5894. the %@AB@%BlockRead%@AE@% and %@AB@%BlockWrite%@AE@% procedures to access data. %@AB@%BlockRead%@AE@% and
  5895. %@AB@%BlockWrite%@AE@% read and write records to a file. In this context, "record"
  5896. denotes a data block of a specific size. The default block size is 128 bytes
  5897. if you use the standard file-open sequence:%@NL@%
  5898. %@NL@%
  5899. %@AS@%     Assign( file_var, 'FILE' );%@NL@%
  5900. %@AS@%     Reset( file_var );%@NL@%
  5901. %@NL@%
  5902. %@CR:MQPA2006@%%@4@%With the default block size, the %@AB@%BlockRead%@AE@% procedure reads in units of 128%@EH@%
  5903. bytes at a time. If the last %@AB@%BlockRead%@AE@% finds fewer than 128 bytes, an error
  5904. occurs. Rarely are the contents of a file exactly equal to 128 * %@AI@%n%@AE@%. To avoid
  5905. errors, you have two alternatives:%@NL@%
  5906. %@NL@%
  5907. %@CR:MQPA2007@%  1. Create a file by writing records of a fixed size with %@AB@%BlockWrite%@AE@%. Then%@NL@%
  5908.      the file size will be exactly divisible by the size of the record.%@NL@%
  5909. %@NL@%
  5910.   2. Create a record size of one byte (since every file size is a multiple%@NL@%
  5911.      of one) by using the statements below:%@NL@%
  5912. %@NL@%
  5913.         %@AS@%Assign( file_var, 'FILE' );%@AE@%%@NL@%
  5914.         %@AS@%Reset( file_var, 1 );%@AE@%%@NL@%
  5915. %@NL@%
  5916. %@CR:MQPA2008@%%@4@%%@AB@%Reset%@AE@% and %@AB@%Rewrite%@AE@% have an optional parameter to define the number of bytes%@EH@%
  5917. in a record. Once the record size is set to one byte, the procedures
  5918. %@AB@%BlockRead%@AE@% and%@AB@%BlockWrite%@AE@% transfer multiples of one byte whenever they
  5919. execute. No error occurs at the end of the file.%@NL@%
  5920. %@NL@%
  5921. %@CR:MQPA2009@%%@4@%The syntax for %@AB@%BlockRead%@AE@% is%@EH@%%@NL@%
  5922. %@NL@%
  5923.      %@AB@%BlockRead(%@AE@%%@AI@%FileVar%@AE@%%@AB@%, %@AE@%%@AI@%Buffer%@AE@%%@AB@%,%@AE@% %@AI@%Count%@AE@% «%@AB@%,%@AE@%%@AI@%NumRead%@AE@%»%@AB@%)%@AE@%%@NL@%
  5924. %@NL@%
  5925. %@CR:MQPA200A@%%@4@%where %@AB@%BlockRead%@AE@% reads %@AI@%Count%@AE@% records (or the number of records remaining,%@EH@%
  5926. whichever is less) from the file into %@AI@%Buffer%@AE@%. The %@AI@%Buffer%@AE@% parameter can be
  5927. any variable large enough to hold the number of bytes read. The actual
  5928. number of complete records read is returned in the optional parameter
  5929. %@AI@%NumRead%@AE@%. Use %@AI@%NumRead%@AE@% to determine whether %@AB@%BlockRead%@AE@% was successful. If the
  5930. parameter %@AI@%NumRead%@AE@% is omitted and %@AB@%BlockRead%@AE@% reads fewer than %@AI@%Count%@AE@% records,
  5931. an I/O error occurs. The parameter list of %@AB@%BlockWrite%@AE@% is the same as that
  5932. for %@AB@%BlockRead%@AE@%.%@NL@%
  5933. %@NL@%
  5934. %@CR:MQPA200B@%%@4@%The following simple program, DUPLICAT.PAS, shows a typical use of block I/O%@EH@%
  5935. to copy a file:%@NL@%
  5936. %@NL@%
  5937. %@AS@%     PROGRAM duplicat;%@NL@%
  5938. %@AS@%     CONST%@NL@%
  5939. %@AS@%         max_buf=16384;%@NL@%
  5940. %@AS@%     VAR%@NL@%
  5941. %@AS@%         file_name, copyfile_name : STRING;%@NL@%
  5942. %@AS@%         source, target : FILE;%@NL@%
  5943. %@AS@%         buffer : ARRAY [1..max_buf] OF Char; { 16K buffer }%@NL@%
  5944. %@AS@%         bytes_read, bytes_written : Word;%@NL@%
  5945. %@NL@%
  5946. %@AS@%     BEGIN%@NL@%
  5947. %@AS@%         Write( 'Enter source file_name -> ' );%@NL@%
  5948. %@AS@%         Readln( file_name );%@NL@%
  5949. %@AS@%         Write( 'Enter name of target file -> ' );%@NL@%
  5950. %@AS@%         Readln( copyfile_name );%@NL@%
  5951. %@AS@%         Assign( source, file_name );%@NL@%
  5952. %@AS@%         Reset( source, 1 );          { 1 byte-block size }%@NL@%
  5953. %@AS@%         Assign( target, copyfile_name );%@NL@%
  5954. %@AS@%         Rewrite( target, 1 );        { 1 byte-block size }%@NL@%
  5955. %@AS@%         REPEAT%@NL@%
  5956. %@AS@%          BlockRead( source, buffer, SizeOf( buffer ), bytes_read );%@NL@%
  5957. %@AS@%          BlockWrite( target, buffer, bytes_read, bytes_written )%@NL@%
  5958. %@AS@%         UNTIL ( bytes_read = 0 ) OR ( bytes_read <> bytes_written );%@NL@%
  5959. %@AS@%         Close( source );%@NL@%
  5960. %@AS@%         Close( target );%@NL@%
  5961. %@AS@%     END.%@NL@%
  5962. %@NL@%
  5963. %@CR:MQPA200C@%%@4@%The program detects the end of the file by looking for either of the%@EH@%
  5964. following two conditions:%@NL@%
  5965. %@NL@%
  5966. %@CR:MQPA200D@%  1. No records were read by the last %@AB@%BlockRead%@AE@% call.%@NL@%
  5967. %@NL@%
  5968.   2. The requested number of records does not match the actual number of%@NL@%
  5969.      records read.%@NL@%
  5970. %@NL@%
  5971. %@CR:MQPA200E@%%@4@%The block I/O techniques presented in the program above are used to%@EH@%
  5972. implement an extended version of the DOS COPY command in the sample program
  5973. EXCOPY.PAS, available on-line in QuickPascal. The other sample program
  5974. components are the command-line arguments; the %@AB@%FindFirst%@AE@% and %@AB@%FindNext%@AE@%
  5975. routines; a binary tree to detect duplicate file names; I/O error checking
  5976. used with %@AB@%BlockRead%@AE@% and %@AB@%BlockWrite%@AE@%; and screen output informing the user of
  5977. the file copy progress.%@NL@%
  5978. %@NL@%
  5979. %@CR:MQPA200F@%%@4@%The EXCOPY.PAS procedure %@AS@%copyfile%@AE@% has the task of actually copying the%@EH@%
  5980. files, one at a time. Notice the following aspects of the procedure:%@NL@%
  5981. %@NL@%
  5982. %@CR:MQPA200G@%  ■  The %@AB@%Reset%@AE@% and %@AB@%Rewrite%@AE@% statements are accompanied by the %@AB@%{$I-}%@AE@% directive%@NL@%
  5983.      to prevent run-time errors from stopping the program. After calling%@NL@%
  5984.      %@AB@%Reset%@AE@% and %@AB@%Rewrite%@AE@%, the value of the function %@AB@%IOResult%@AE@% is compared with%@NL@%
  5985.      0. If it is not 0, the procedure terminates. This behavior protects%@NL@%
  5986.      against errors resulting from bad file names or attempts to copy files%@NL@%
  5987.      that cannot be accessed.%@NL@%
  5988. %@NL@%
  5989.   ■  After the %@AB@%BlockWrite%@AE@% procedure is executed, the parameters %@AS@%bytes_read%@AE@%%@NL@%
  5990.      and %@AS@%byte_written%@AE@% are compared. If they are not equal, the destination%@NL@%
  5991.      disk becomes full while copying the current file.%@NL@%
  5992. %@NL@%
  5993.   ■  If the file cannot be copied, then a message is displayed to that%@NL@%
  5994.      effect and the target file is erased. Consequently, any partially used%@NL@%
  5995.      disk space is freed for other smaller files to be copied. In addition,%@NL@%
  5996.      the above procedure also wipes off zero-byte files that would otherwise%@NL@%
  5997.      appear in the target directory.%@NL@%
  5998. %@NL@%
  5999. %@CR:MQPA200H@%%@4@%To run EXCOPY.EXE, first compile the program EXCOPY.PAS. The current%@EH@%
  6000. directory should contain the source files you wish to copy. Enter the
  6001. command line arguments as%@NL@%
  6002. %@NL@%
  6003.      %@AB@%EXCOPY %@AE@%%@AI@%TargetDirectory%@AE@% «%@AI@%FileList%@AE@%»%@NL@%
  6004. %@NL@%
  6005. %@CR:MQPA200I@%%@4@%The %@AI@%FileList%@AE@% argument can contain one or more file names separated by%@EH@%
  6006. spaces. Each file name can contain the wildcard characters %@AB@%*%@AE@% and %@AB@%?%@AE@%. If you
  6007. omit %@AI@%FileList%@AE@%, EXCOPY uses the default file specification %@AB@%*.*%@AE@% as the file
  6008. list.%@NL@%
  6009. %@NL@%
  6010. %@NL@%
  6011. %@CR:MQPB0000@%%@1@%%@AB@%Chapter 11  Pointers and Dynamic Memory%@AE@%%@EH@%%@NL@%
  6012. ───────────────────────────────────────────────────────────────────────────%@NL@%
  6013. %@NL@%
  6014. %@CR:MQPB0001@%%@4@%A pointer is a variable that contains the numeric address of another data%@EH@%
  6015. object. A pointer provides indirect access to data. For example, if you have
  6016. a pointer to a record and you pass this pointer to a procedure, then the
  6017. procedure can manipulate any field by using the pointer. The procedure does
  6018. not need its own copy of the data.%@NL@%
  6019. %@NL@%
  6020. %@CR:MQPB0002@%%@4@%In Pascal, you use pointers primarily as handles to dynamic-memory objects.%@EH@%
  6021. "Dynamic memory" consists of memory that the program explicitly requests at
  6022. run time. Dynamic memory gives you many advantages. It lets your memory
  6023. usage grow and contract as your needs require──you do not need to specify a
  6024. maximum size or limit.%@NL@%
  6025. %@NL@%
  6026. %@CR:MQPB0003@%%@4@%Because dynamic memory is allocated at run time, your program cannot know in%@EH@%
  6027. advance where the block is located. Pascal, therefore, returns a pointer
  6028. when it allocates dynamic memory. The pointer provides the access to the
  6029. data.%@NL@%
  6030. %@NL@%
  6031. %@CR:MQPB0004@%%@4@%Dynamic memory enables you to create powerful data structures such as linked%@EH@%
  6032. lists and binary trees. These structures, described at the end of this
  6033. chapter, are networks of data in which pointers provide the connecting
  6034. links.%@NL@%
  6035. %@NL@%
  6036. %@CR:MQPB0005@%%@4@%In QuickPascal, you can also use pointers to point to ordinary (non-dynamic)%@EH@%
  6037. variables. This chapter begins by explaining the basics of pointers using
  6038. nondynamic variables.%@NL@%
  6039. %@NL@%
  6040. %@NL@%
  6041. %@CR:MQPB1000@%%@2@%%@AB@%11.1  Declaring and Accessing Pointers%@AE@%%@EH@%%@NL@%
  6042. %@NL@%
  6043. %@CR:MQPB1001@%%@4@%Using pointers consists of three major steps, which you must always do in%@EH@%
  6044. this order:%@NL@%
  6045. %@NL@%
  6046. %@CR:MQPB1002@%  1. Declare the pointer as a specific type.%@NL@%
  6047. %@NL@%
  6048.   2. Initialize the pointer.%@NL@%
  6049. %@NL@%
  6050.   3. Use the pointer by assigning its value, testing its value, or accessing%@NL@%
  6051.      the value that it points to.%@NL@%
  6052. %@NL@%
  6053. %@NL@%
  6054. %@CR:MQPB1100@%%@3@%%@AB@%11.1.1  Declaring Pointers%@AE@%%@EH@%%@NL@%
  6055. %@NL@%
  6056. %@CR:MQPB1101@%%@4@%Like other variables, pointers have definite types and can only point to a%@EH@%
  6057. variable of the appropriate type. You can declare a pointer with the
  6058. following syntax:%@NL@%
  6059. %@NL@%
  6060.      %@AI@%PointerName%@AE@% %@AB@%: ^%@AE@%%@AI@%DataType%@AE@%%@NL@%
  6061. %@NL@%
  6062. %@CR:MQPB1102@%%@4@%Example pointer declarations are shown below:%@EH@%%@NL@%
  6063. %@NL@%
  6064. %@AS@%     TYPE%@NL@%
  6065. %@AS@%         totals = ARRAY[1..10] OF Integer;%@NL@%
  6066. %@AS@%     VAR%@NL@%
  6067. %@AS@%         int_ptr   : ^Integer;%@NL@%
  6068. %@AS@%         char_ptr  : ^Char;%@NL@%
  6069. %@AS@%         str_ptr   : ^STRING;%@NL@%
  6070. %@AS@%         real_ptr  : ^Real;%@NL@%
  6071. %@AS@%         total_ptr : ^totals;%@NL@%
  6072. %@NL@%
  6073. %@CR:MQPB1103@%%@4@%After you declare a pointer, it does not point to any meaningful value; you%@EH@%
  6074. can produce errors if you try to use it. The first thing you must do after
  6075. declaring a pointer is initialize it.%@NL@%
  6076. %@NL@%
  6077. %@NL@%
  6078. %@CR:MQPB1200@%%@3@%%@AB@%11.1.2  Initializing Pointers%@AE@%%@EH@%%@NL@%
  6079. %@NL@%
  6080. %@CR:MQPB1201@%%@4@%After declaring a pointer, you must initialize it to an address. You can%@EH@%
  6081. always initialize a pointer to the special %@AB@%NIL%@AE@% value. This value indicates
  6082. that the pointer is temporarily turned off──it has no object to point to.
  6083. Your program can test for this condition and take appropriate actions. The
  6084. %@AB@%NIL%@AE@% value is useful in indicating the end of a tree or linked list. Here is
  6085. an example of an assignment to %@AB@%NIL%@AE@%:%@NL@%
  6086. %@NL@%
  6087. %@AS@%     my_ptr := NIL;%@NL@%
  6088. %@NL@%
  6089. %@CR:MQPB1202@%%@4@%To assign the address of a variable to a pointer, you can use either the%@EH@%
  6090. address-of (%@AB@%@%@AE@%) operator, or the %@AB@%Addr%@AE@% function. The syntax is%@NL@%
  6091. %@NL@%
  6092.      %@AI@%Pointer%@AE@% %@AB@%:= Addr(%@AE@%%@AI@%Variable%@AE@%%@AB@%)%@AE@%%@NL@%
  6093.      %@AI@%Pointer%@AE@% %@AB@%:= @%@AE@%%@AI@%Variable%@AE@%%@NL@%
  6094. %@NL@%
  6095. %@CR:MQPB1203@%%@4@%The %@AI@%Variable%@AE@% can be any variable of the type that appears in the declaration%@EH@%
  6096. of %@AI@%Pointer%@AE@%. An example is shown below:%@NL@%
  6097. %@NL@%
  6098. %@AS@%     VAR%@NL@%
  6099. %@AS@%         an_int   : Byte;%@NL@%
  6100. %@AS@%         byte_ptr : ^Byte;%@NL@%
  6101. %@NL@%
  6102. %@AS@%     BEGIN%@NL@%
  6103. %@AS@%         an_int := 5;%@NL@%
  6104. %@NL@%
  6105. %@AS@%         { These assignment statements put the same%@NL@%
  6106. %@AS@%           address in pointer byte_ptr.%@NL@%
  6107. %@AS@%           Both Writeln statements print the number 5.%@NL@%
  6108. %@AS@%         }%@NL@%
  6109. %@AS@%         byte_ptr := Addr( an_int );%@NL@%
  6110. %@AS@%         Writeln( byte_ptr^ );%@NL@%
  6111. %@NL@%
  6112. %@AS@%         byte_ptr := @an_int;%@NL@%
  6113. %@AS@%         Writeln( byte_ptr^ );%@NL@%
  6114. %@AS@%     END.%@NL@%
  6115. %@NL@%
  6116. %@CR:MQPB1204@%%@4@%In Section 11.2%@BO:   4af71@%, you learn how to assign a value to a pointer by making a%@EH@%
  6117. dynamic-memory procedure call.%@NL@%
  6118. %@NL@%
  6119. %@NL@%
  6120. %@CR:MQPB1300@%%@3@%%@AB@%11.1.3  Manipulating Pointers%@AE@%%@EH@%%@NL@%
  6121. %@NL@%
  6122. %@CR:MQPB1301@%%@4@%Pointer manipulation in Pascal is extremely limited. In addition to the%@EH@%
  6123. methods described above, the only way to manipulate a pointer is to assign
  6124. it the value of another pointer of the same type. For example, the statement%@NL@%
  6125. %@NL@%
  6126. %@AS@%     ptr1 := ptr2;%@NL@%
  6127. %@NL@%
  6128. %@CR:MQPB1302@%%@4@%causes %@AS@%ptr1%@AE@% to point to the same location that %@AS@%ptr2%@AE@% does. This kind of%@EH@%
  6129. assignment is frequently useful in dealing with data structures such as
  6130. linked lists (shown in Section 11.3%@BO:   4cd58@%).%@NL@%
  6131. %@NL@%
  6132. %@CR:MQPB1303@%%@4@%Once you declare and initialize a pointer, you can use it in one of the%@EH@%
  6133. following ways:%@NL@%
  6134. %@NL@%
  6135. %@CR:MQPB1304@%  ■  Assign the value of the pointer itself to another pointer.%@NL@%
  6136. %@NL@%
  6137.   ■  Test the value of the pointer itself.%@NL@%
  6138. %@NL@%
  6139.   ■  Access the value of the variable pointed to.%@NL@%
  6140. %@NL@%
  6141. %@CR:MQPB1305@%%@4@%The number of operations you can do with the value of the pointer is%@EH@%
  6142. limited. As described above, you can assign the value of a pointer to
  6143. another pointer of the same type. You can also test a pointer for equality
  6144. to %@AB@%NIL%@AE@% or to another pointer. For example, the statement%@NL@%
  6145. %@NL@%
  6146. %@AS@%     IF (ptr1 = ptr2) THEN ...%@NL@%
  6147. %@NL@%
  6148. %@CR:MQPB1306@%%@4@%executes the statement following %@AB@%THEN%@AE@% if %@AS@%ptr1%@AE@% and %@AS@%ptr2%@AE@% point to the same%@EH@%
  6149. variable. Note that if %@AS@%ptr1%@AE@% and %@AS@%ptr2%@AE@% point to different locations, then the
  6150. expression %@AS@%ptr1 = ptr2%@AE@% evaluates as %@AB@%False%@AE@%, even if the objects that %@AS@%ptr1%@AE@% and
  6151. %@AS@%ptr2%@AE@% point to are equal.%@NL@%
  6152. %@NL@%
  6153. %@CR:MQPB1307@%%@4@%You can also access the value of the variable indicated by the pointer. This%@EH@%
  6154. value can be manipulated in any way you can manipulate the variable itself.
  6155. Use the following syntax to access the variable indicated by the pointer:%@NL@%
  6156. %@NL@%
  6157.      %@AI@%PointerName%@AE@%%@AB@%^%@AE@%%@NL@%
  6158. %@NL@%
  6159. %@CR:MQPB1308@%%@4@%This operation is called "dereferencing" the pointer. For example, the%@EH@%
  6160. following code sets the value of %@AS@%x%@AE@% to %@AS@%5%@AE@%, and then assigns this value to %@AS@%y%@AE@%:%@NL@%
  6161. %@NL@%
  6162. %@AS@%     VAR%@NL@%
  6163. %@AS@%         x, y     : Byte;%@NL@%
  6164. %@AS@%         byte_ptr : ^Byte;%@NL@%
  6165. %@NL@%
  6166. %@AS@%     BEGIN%@NL@%
  6167. %@AS@%         byte_ptr := Addr( x );{ byte_ptr now points to x }%@NL@%
  6168. %@AS@%         byte_ptr^ := 5;        { assign 5 to x }%@NL@%
  6169. %@AS@%         y := byte_ptr^;         { assign value of x to y }%@NL@%
  6170. %@AS@%     END.%@NL@%
  6171. %@NL@%
  6172. %@CR:MQPB1309@%%@4@%In testing pointer values, bear in mind the difference between a pointer and%@EH@%
  6173. the variable pointed to. For example, the statement%@NL@%
  6174. %@NL@%
  6175. %@AS@%     IF (ptr1^ = ptr2^) THEN ...%@NL@%
  6176. %@NL@%
  6177. %@CR:MQPB130A@%%@4@%executes the statement following %@AB@%THEN%@AE@% if the objects pointed to by %@AS@%ptr1%@AE@% and%@EH@%
  6178. %@AS@%ptr2%@AE@% are equal. Contrast this example with the previous %@AB@%IF%@AE@%-statement
  6179. example, which evaluated to %@AB@%True%@AE@% only if %@AS@%ptr1%@AE@% and %@AS@%ptr2%@AE@% pointed to the same
  6180. object.%@NL@%
  6181. %@NL@%
  6182. %@NL@%
  6183. %@CR:MQPB2000@%%@2@%%@AB@%11.2  Dynamic-Memory Allocation%@AE@%%@EH@%%@NL@%
  6184. %@NL@%
  6185. %@CR:MQPB2001@%%@4@%In most programs, you need to evaluate the maximum amount of memory the%@EH@%
  6186. program will require. If the amount of data becomes larger than you foresaw,
  6187. you must rewrite the program and then recompile. However, dynamic memory
  6188. lets your memory usage grow along with the needs of the program. The amount
  6189. of physical memory available is the only ultimate limit to dynamic memory.%@NL@%
  6190. %@NL@%
  6191. %@CR:MQPB2002@%%@4@%The use of pointers is essential to all dynamic-memory operations. When%@EH@%
  6192. QuickPascal allocates memory, it returns a pointer. The pointer gives you
  6193. access to the memory block.%@NL@%
  6194. %@NL@%
  6195. %@CR:MQPB2003@%%@4@%There are two basic ways of dynamically allocating memory:%@EH@%%@NL@%
  6196. %@NL@%
  6197. %@CR:MQPB2004@%  1. Allocating one object at a time (%@AB@%New%@AE@% and %@AB@%Dispose%@AE@%)%@NL@%
  6198. %@NL@%
  6199.   2. Allocating a block of memory (%@AB@%GetMem%@AE@% and %@AB@%FreeMem%@AE@%)%@NL@%
  6200. %@NL@%
  6201. %@NL@%
  6202. %@CR:MQPB2100@%%@3@%%@AB@%11.2.1  Allocating a Single Object%@AE@%%@EH@%%@NL@%
  6203. %@NL@%
  6204. %@CR:MQPB2101@%%@4@%By using the %@AB@%New%@AE@% procedure, you allocate space equal to the size of the data%@EH@%
  6205. type associated with the pointer. The syntax is%@NL@%
  6206. %@NL@%
  6207.      %@AB@%New(%@AE@%%@AI@%Pointer%@AE@%%@AB@%)%@AE@%%@NL@%
  6208. %@NL@%
  6209. %@CR:MQPB2102@%%@4@%Once the %@AB@%New%@AE@% function executes, QuickPascal assigns the address of the%@EH@%
  6210. dynamic-memory block to %@AI@%Pointer%@AE@%. The %@AI@%Pointer%@AE@% must be a variable previously
  6211. declared. The following example shows how to declare a pointer of type %@AS@%Byte%@AE@%;
  6212. allocate memory through the pointer; and then use the dynamic variable to
  6213. hold, manipulate, and display a value.%@NL@%
  6214. %@NL@%
  6215. %@AS@%     VAR%@NL@%
  6216. %@AS@%         int_ptr : ^Byte;%@NL@%
  6217. %@NL@%
  6218. %@AS@%     BEGIN%@NL@%
  6219. %@AS@%         int_ptr := NIL;%@NL@%
  6220. %@AS@%         { create a Byte-type dynamic variable }%@NL@%
  6221. %@AS@%         New( int_ptr );%@NL@%
  6222. %@AS@%         int_ptr^ := 100;      { assign a value to the dynamic%@NL@%
  6223. %@AS@%                                       variable }%@NL@%
  6224. %@AS@%         Inc( int_ptr^, 10 );  { increment it }%@NL@%
  6225. %@AS@%         Writeln( int_ptr^ );  { display its value }%@NL@%
  6226. %@AS@%         Dispose( int_ptr );%@NL@%
  6227. %@AS@%     END.%@NL@%
  6228. %@NL@%
  6229. %@CR:MQPB2103@%%@4@%As described in the previous section, %@AS@%int_ptr^%@AE@% is an example of a%@EH@%
  6230. dereferenced pointer. %@AS@%int_ptr%@AE@% itself is a pointer, which can only be
  6231. manipulated in a few restricted ways. However, %@AS@%int_ptr^%@AE@% is equivalent to an
  6232. ordinary variable of type %@AS@%Byte%@AE@%. Use %@AS@%int_ptr^%@AE@% anywhere you would use a %@AS@%Byte%@AE@%
  6233. variable.%@NL@%
  6234. %@NL@%
  6235. %@CR:MQPB2104@%%@4@%To remove a dynamic-memory object created with the %@AB@%New%@AE@% function, use the%@EH@%
  6236. %@AB@%Dispose%@AE@% function. See Section 11.3%@BO:   4cd58@%, "Linked Lists," for more examples of
  6237. %@AB@%New%@AE@% and %@AB@%Dispose%@AE@%.%@NL@%
  6238. %@NL@%
  6239. %@NL@%
  6240. %@CR:MQPB2200@%%@3@%%@AB@%11.2.2  Allocating a Memory Block%@AE@%%@EH@%%@NL@%
  6241. %@NL@%
  6242. %@CR:MQPB2201@%%@4@%The %@AB@%GetMem%@AE@% and %@AB@%FreeMem%@AE@% functions are similar to %@AB@%New%@AE@% and %@AB@%Dispose%@AE@%. However,%@EH@%
  6243. %@AB@%GetMem%@AE@% and %@AB@%FreeMem%@AE@% deal with entire blocks of memory rather than one object
  6244. at a time. Once a block is allocated, you access it as if it were an array
  6245. of indefinite size.%@NL@%
  6246. %@NL@%
  6247. %@CR:MQPB2202@%%@4@%Use the %@AB@%GetMem%@AE@% procedure to select the size of a dynamic-memory block. The%@EH@%
  6248. size should be a multiple of the size of the element type of the array.
  6249. Therefore, if %@AS@%size%@AE@% is the number of elements you want to allocate, and
  6250. %@AS@%base_type%@AE@% is the element type of the array, then pass the following
  6251. parameters to %@AB@%GetMem%@AE@%:%@NL@%
  6252. %@NL@%
  6253. %@AS@%     Size * SizeOf(base_type)%@NL@%
  6254. %@NL@%
  6255. %@CR:MQPB2203@%%@4@%A common way to use %@AB@%GetMem%@AE@% is to declare an array type of %@AS@%max_elements%@AE@%%@EH@%
  6256. elements first, where %@AS@%max_elements%@AE@% is the largest possible number of
  6257. elements of the base type. Because the type is an array, you can access
  6258. memory throughout the block with an array index. For example, the following
  6259. code makes the necessary declarations and then calls %@AB@%GetMem%@AE@% to return a
  6260. memory block:%@NL@%
  6261. %@NL@%
  6262. %@AS@%     CONST%@NL@%
  6263. %@AS@%         max_elements = 65520 DIV SizeOf( base_type );%@NL@%
  6264. %@AS@%     TYPE%@NL@%
  6265. %@AS@%         big_array = ARRAY[1..max_elements] OF base_type;%@NL@%
  6266. %@AS@%     VAR%@NL@%
  6267. %@AS@%         array_ptr : ^big_array;%@NL@%
  6268. %@AS@%     BEGIN%@NL@%
  6269. %@AS@%         .%@NL@%
  6270. %@AS@%         .%@NL@%
  6271. %@AS@%         .%@NL@%
  6272. %@AS@%         GetMem( array_ptr, size * SizeOf(base_type) );%@NL@%
  6273. %@NL@%
  6274. %@CR:MQPB2204@%%@4@%The %@AS@%array_ptr%@AE@% now points to an array of type %@AS@%base_type%@AE@%. You can treat%@EH@%
  6275. %@AS@%array_ptr%@AE@% just like any array. The largest index in this array is %@AS@%size%@AE@%. To
  6276. access any element in this array, use the following syntax:%@NL@%
  6277. %@NL@%
  6278.      %@AI@%ArrayPointer%@AE@%%@AB@%^[%@AE@%%@AI@%Index%@AE@%%@AB@%]%@AE@%%@NL@%
  6279. %@NL@%
  6280. %@CR:MQPB2205@%%@4@%The example shown below requests a memory block %@AS@%100%@AE@% elements long. In this%@EH@%
  6281. case, %@AS@%array_size%@AE@% is set to %@AS@%100%@AE@%, but at run time, the program could set
  6282. %@AS@%array_size%@AE@% to whatever length it needed.%@NL@%
  6283. %@NL@%
  6284. %@AS@%     CONST%@NL@%
  6285. %@AS@%         max_elements = 65520 DIV SizeOf( Real );%@NL@%
  6286. %@AS@%     TYPE%@NL@%
  6287. %@AS@%         some_reals : ARRAY[1..max_elements] OF Real;%@NL@%
  6288. %@AS@%     VAR%@NL@%
  6289. %@AS@%         rptr       : ^some_reals;%@NL@%
  6290. %@AS@%         i          : Byte;%@NL@%
  6291. %@AS@%         array_size : Word;%@NL@%
  6292. %@AS@%     BEGIN%@NL@%
  6293. %@AS@%         array_size := 100;%@NL@%
  6294. %@AS@%         GetMem( rptr, array_size * SizeOf(Real) );%@NL@%
  6295. %@AS@%         FOR i := 1 TO array_size DO%@NL@%
  6296. %@AS@%             BEGIN%@NL@%
  6297. %@AS@%             rptr^[i] := i;%@NL@%
  6298. %@AS@%             Writeln( rptr^[i] );%@NL@%
  6299. %@AS@%             END;%@NL@%
  6300. %@AS@%         FreeMem( rptr, array_size * SizeOf( Real ));%@NL@%
  6301. %@AS@%     END.%@NL@%
  6302. %@NL@%
  6303. %@CR:MQPB2206@%%@4@%The %@AB@%FreeMem%@AE@% procedure frees up memory blocks allocated by %@AB@%GetMem%@AE@%. If you no%@EH@%
  6304. longer need to use a particular memory block, it is a good idea to free the
  6305. memory. Otherwise, the program can use up all of the available memory over
  6306. time. The %@AB@%FreeMem%@AE@% procedure takes the same parameters that %@AB@%GetMem%@AE@% does. Make
  6307. sure that the size you specify in %@AB@%FreeMem%@AE@% matches the size allocated with
  6308. %@AB@%GetMem%@AE@%.%@NL@%
  6309. %@NL@%
  6310. %@CR:MQPB2207@%%@4@%Table 11.1%@BO:   4c9f4@% summarizes the procedures provided by QuickPascal for use with%@EH@%
  6311. pointers.%@NL@%
  6312. %@NL@%
  6313. %@CR:MQPBT100@%%@4@%%@AB@%Table 11.1  Pointer Procedures%@AE@%%@EH@%%@NL@%
  6314. %@NL@%
  6315. %@AB@%Routine           Purpose                             Example%@AE@%%@NL@%
  6316. %@NL@%
  6317. %@AB@%Addr%@AE@%              Returns the address of a data       %@AS@%aptr :=  Addr( I );%@AE@%%@NL@%
  6318.                   object (same as the %@AB@%@%@AE@% operator)%@NL@%
  6319. %@NL@%
  6320. %@AB@%Dispose%@AE@%           Disposes of a dynamic variable      %@AS@%Dispose( nextptr );%@AE@%%@NL@%
  6321. %@NL@%
  6322. %@AB@%FreeMem%@AE@%           Disposes of a dynamic variable      %@AS@%FreeMem( aptr, 512 );%@AE@%%@NL@%
  6323.                   of given size in bytes
  6324. %@NL@%
  6325. %@AB@%GetMem%@AE@%            Creates a dynamic variable of a     %@AS@%GetMem( aptr, 512 );%@AE@%%@NL@%
  6326.                   given size in bytes%@NL@%
  6327.  
  6328. %@AB@%New%@AE@%               Creates a dynamic variable          %@AS@%New( aptr );%@AE@%%@NL@%
  6329.  
  6330. %@NL@%
  6331. %@CR:MQPB3000@%%@2@%%@AB@%11.3  Linked Lists%@AE@%%@EH@%%@NL@%
  6332. %@NL@%
  6333. %@CR:MQPB3001@%%@4@%Stacks, queues, and trees are data structures that are linked lists. A%@EH@%
  6334. "linked list" is a collection of dynamically allocated records, each having
  6335. a field that is a pointer to the next record. Essentially, the pointers
  6336. serve as the connectors between any two items. By altering the value of the
  6337. pointers, you can sort or reorganize the list in any way──without physically
  6338. moving any of the stored records.%@NL@%
  6339. %@NL@%
  6340. %@CR:MQPB3002@%%@4@%If your program implements a straightforward algorithm, you do not need to%@EH@%
  6341. use these data structures. However, these structures give you a great deal
  6342. of power to solve complex computing tasks. They can grow to any size, and
  6343. they let the program traverse, analyze, and restructure a network of data
  6344. paths. The only limit to the complexity is your own imagination.%@NL@%
  6345. %@NL@%
  6346. %@CR:MQPB3003@%%@4@%The LIST.PAS program adds records to a list, deletes them, and prints the%@EH@%
  6347. contents of the list. The data is stored in a record declared as:%@NL@%
  6348. %@NL@%
  6349. %@AS@%     TYPE%@NL@%
  6350. %@AS@%         rec_ptr = ^stack_rec;%@NL@%
  6351. %@AS@%         stack_rec = RECORD%@NL@%
  6352. %@AS@%             data     : Integer;%@NL@%
  6353. %@AS@%             next_rec : rec_ptr;%@NL@%
  6354. %@AS@%             END;%@NL@%
  6355. %@NL@%
  6356. %@CR:MQPB3004@%%@4@%Note that the second field of type %@AS@%stack_rec%@AE@% points to another record──also%@EH@%
  6357. of type %@AS@%stack_rec%@AE@%. Though this self reference may seem paradoxical, it is
  6358. perfectly legal. It simply means that the second field is the connector to
  6359. another record of the same type. The %@AS@%data%@AE@% field contains the data to be
  6360. stored. For more complex programs, the record could have any number of
  6361. appropriate data fields.%@NL@%
  6362. %@NL@%
  6363. %@CR:MQPB3005@%%@4@%To create a list, first declare a pointer to the start of the list and%@EH@%
  6364. initialize this pointer to %@AB@%NIL%@AE@%:%@NL@%
  6365. %@NL@%
  6366. %@AS@%     VAR%@NL@%
  6367. %@AS@%         stack_ptr : rec_ptr;%@NL@%
  6368. %@AS@%     BEGIN%@NL@%
  6369. %@AS@%         stack_ptr := NIL;%@NL@%
  6370. %@NL@%
  6371. %@CR:MQPB3006@%%@4@%The program has two major procedures, %@AS@%push%@AE@% and %@AS@%pop%@AE@%. These procedures model%@EH@%
  6372. the behavior of the %@AB@%PUSH%@AE@% and %@AB@%POP%@AE@% instructions of the processor. The linked
  6373. list in this program is a last-in, first-out mechanism, just like the stack
  6374. of the 8086 microprocessor. The %@AS@%push%@AE@% procedure adds items to the front of
  6375. the list, and %@AS@%pop%@AE@% removes these items from the front as well. Therefore, the
  6376. last item stored is also the first item retrieved.%@NL@%
  6377. %@NL@%
  6378. %@CR:MQPB3007@%%@4@%The code in the %@AS@%push%@AE@% procedure inserts a new record at the front of the list%@EH@%
  6379. and then assigns the new value (%@AS@%x%@AE@%) to the %@AS@%data%@AE@% field. These actions simulate
  6380. the action of pushing %@AS@%x%@AE@% onto the top of a stack.%@NL@%
  6381. %@NL@%
  6382. %@AS@%     VAR%@NL@%
  6383. %@AS@%         temp :  rec_ptr;%@NL@%
  6384. %@AS@%     BEGIN%@NL@%
  6385. %@AS@%         New( temp );%@NL@%
  6386. %@AS@%         temp^.next_rec := stack_ptr;%@NL@%
  6387. %@AS@%         stack_ptr := temp;%@NL@%
  6388. %@AS@%         stack_ptr^.data := x;%@NL@%
  6389. %@AS@%     END;%@NL@%
  6390. %@NL@%
  6391. %@CR:MQPB3008@%%@4@%The above lines of code show the four steps required for the %@AS@%push%@AE@% procedure%@EH@%
  6392. to add a new record to the linked list. These four steps are listed below:%@NL@%
  6393. %@NL@%
  6394. %@CR:MQPB3009@%  1. The first statement, %@AS@%New(temp)%@AE@%, allocates a memory location large%@NL@%
  6395.      enough to hold a record with the fields %@AS@%data%@AE@% and %@AS@%next_rec%@AE@%. The pointer%@NL@%
  6396.      %@AS@%temp%@AE@% now points to this new record.%@NL@%
  6397. %@NL@%
  6398.   2. To insert this record at the front of the list, the code reassigns two%@NL@%
  6399.      pointer values. First, the procedure sets the %@AS@%next_rec%@AE@% field to point%@NL@%
  6400.      to the current item at the front of the list. The pointer variable%@NL@%
  6401.      %@AS@%stack_ptr%@AE@% points to the front of the list, so the following line of%@NL@%
  6402.      code assigns the value %@AS@%stack_ptr%@AE@% to the %@AS@%next_rec%@AE@% field of the new%@NL@%
  6403.      record (the new record is referred to as %@AS@%temp^%@AE@%).%@NL@%
  6404. %@NL@%
  6405.         %@AS@%temp^.next_rec := stack_ptr;%@AE@%%@NL@%
  6406. %@NL@%
  6407.   3. Next, the pointer %@AS@%stack_ptr%@AE@% must be reassigned to %@AS@%temp%@AE@%. The result is%@NL@%
  6408.      that the item previously at the front of the list is now the second%@NL@%
  6409.      item (because of step 2), and the new record is at the very front.%@NL@%
  6410. %@NL@%
  6411.   4. Now that the new record has been created and inserted, you can simply%@NL@%
  6412.      load the new data into the record. The following statement assigns the%@NL@%
  6413.      value of %@AS@%x%@AE@% to the %@AS@%data%@AE@% field of the new record. Note that because of%@NL@%
  6414.      step 3, the new record can be referred to as %@AS@%stack_ptr^%@AE@%.%@NL@%
  6415. %@NL@%
  6416.         %@AS@%stack_ptr^.data := x;%@AE@%%@NL@%
  6417. %@NL@%
  6418.      Note that %@AS@%temp%@AE@% still points to the new record, but now %@AS@%temp%@AE@% can be%@NL@%
  6419.      ignored because %@AS@%stack_ptr%@AE@% also points to this record.%@NL@%
  6420. %@NL@%
  6421. %@CR:MQPB300A@%%@4@%Figure 11.1%@BO:   4e1ca@% illustrates the %@AS@%push%@AE@% procedure.%@EH@%%@NL@%
  6422. %@NL@%
  6423. %@NL@%
  6424. %@CR:MQPBf100@%%@4@%%@AB@%Figure 11.1  The Push Procedure%@AE@%%@EH@%%@NL@%
  6425. %@NL@%
  6426. %@AB@%Initial Condition%@AE@%%@NL@%
  6427.                               ┌───────────┐  ┌───────────┐%@NL@%
  6428.                               │   data    │  │   data    │%@NL@%
  6429.                ┌───────────┐┌├───────────┤┌├───────────┤         ┌──────────┐%@NL@%
  6430.                │ stack_ptr ├┘ │ next_rec  ├┘ │ next_rec  ├─ ∙∙∙ ─│   NIL    │%@NL@%
  6431.                └───────────┘  └───────────┘  └───────────┘         └──────────┘%@NL@%
  6432.  %@NL@%
  6433. %@AB@%Step 1%@AE@%   %@AS@%New (temp) ;%@AE@%%@NL@%
  6434.                ┌───────────┐%@NL@%
  6435.                │   data    │%@NL@%
  6436. ┌───────────┐┌├───────────┤%@NL@%
  6437. │ stack_ptr ├┘ │ next_rec  │%@NL@%
  6438. └───────────┘  └───────────┘%@NL@%
  6439.  %@NL@%
  6440. %@AB@%Step 2%@AE@%   %@AS@%temp^.next_rec := stack_ptr;%@AE@%%@NL@%
  6441.                               ┌───────────┐  ┌───────────┐%@NL@%
  6442.                ┌───────────┐  │   data    │  │   data    │%@NL@%
  6443.                │ stack_ptr ├┬├───────────┤┌├───────────┤         ┌──────────┐%@NL@%
  6444.                └───────────┘│ │ next_rec  ├┘ │ next_rec  ├─ ∙∙∙ ─│   NIL    │%@NL@%
  6445.                ┌───────────┐│ └───────────┘  └───────────┘         └──────────┘%@NL@%
  6446.                │   data    ││%@NL@%
  6447. ┌───────────┐┌├───────────┤│%@NL@%
  6448. │ stack_ptr ├┘ │ next_rec  ├┘%@NL@%
  6449. └───────────┘  └───────────┘%@NL@%
  6450. %@NL@%
  6451. %@AB@%Step 3%@AE@%   %@AS@%stack_ptr := temp;%@AE@%%@NL@%
  6452.                               ┌───────────┐  ┌───────────┐%@NL@%
  6453.                ┌───────────┐  │   data    │  │   data    │%@NL@%
  6454.              ┌─┤ stack_ptr │┌├───────────┤┌├───────────┤         ┌──────────┐%@NL@%
  6455.              │ └───────────┘│ │ next_rec  ├┘ │ next_rec  ├─ ∙∙∙ ─│   NIL    │%@NL@%
  6456.              │ ┌───────────┐│ └───────────┘  └───────────┘         └──────────┘%@NL@%
  6457.              │ │   data    ││%@NL@%
  6458. ┌───────────┐├├───────────┤│%@NL@%
  6459. │ stack_ptr ├┘ │ next_rec  ├┘%@NL@%
  6460. └───────────┘  └───────────┘%@NL@%
  6461.  %@NL@%
  6462. %@AB@%Step 4%@AE@%   %@AS@%stack_ptr^.data := x;%@AE@%%@NL@%
  6463.                               ┌───────────┐  ┌───────────┐%@NL@%
  6464.                ┌───────────┐  │   data    │  │   data    │%@NL@%
  6465.              ┌─┤ stack_ptr │┌├───────────┤┌├───────────┤         ┌──────────┐%@NL@%
  6466.              │ └───────────┘│ │ next_rec  ├┘ │ next_rec  ├─ ∙∙∙ ─│   NIL    │%@NL@%
  6467.              │ ┌───────────┐│ └───────────┘  └───────────┘         └──────────┘%@NL@%
  6468.              │ │           │┐┌───────────┐%@NL@%
  6469.              └├───────────┤│└┤     x     │%@NL@%
  6470.                │ next_rec  ├┘ └───────────┘%@NL@%
  6471.                └───────────┘%@NL@%
  6472. %@NL@%
  6473. %@NL@%
  6474. %@CR:MQPB300B@%%@4@%The %@AS@%pop%@AE@% procedure works by executing the series of steps in reverse, as%@EH@%
  6475. shown in the code below:%@NL@%
  6476. %@NL@%
  6477. %@AS@%     z := stack_ptr^.data;%@NL@%
  6478. %@AS@%     temp := stack_ptr;%@NL@%
  6479. %@AS@%     stack_ptr := stack_ptr^.next_rec;%@NL@%
  6480. %@AS@%     Dispose(temp);%@NL@%
  6481. %@NL@%
  6482. %@CR:MQPB300C@%  1. The procedure pops the value off the top of the stack by saving the%@NL@%
  6483.      value in the %@AS@%data%@AE@% field of the first record. The following statement%@NL@%
  6484.      saves this value by loading it into %@AS@%z%@AE@%, the output value of the%@NL@%
  6485.      procedure.%@NL@%
  6486. %@NL@%
  6487.         %@AS@%z := stack_ptr^.data;%@AE@%%@NL@%
  6488. %@NL@%
  6489.   2. Note that the current record at the front of the list must be deleted.%@NL@%
  6490.      The pointer %@AS@%temp%@AE@% points to this record, so that the procedure can use%@NL@%
  6491.      %@AS@%temp%@AE@% to delete the record later on.%@NL@%
  6492. %@NL@%
  6493.         %@AS@%temp := stack_ptr;%@AE@%%@NL@%
  6494. %@NL@%
  6495.   3. Then the pointer to the top of the stack, %@AS@%stack_ptr%@AE@%, is moved so it%@NL@%
  6496.      points to %@AS@%stack_ptr^.next_rec%@AE@%. Note that %@AS@%stack_ptr%@AE@% points to the top%@NL@%
  6497.      record in the list, which is a record with two fields: the %@AS@%data%@AE@% field%@NL@%
  6498.      and the %@AS@%next_rec%@AE@% field. The %@AS@%next_rec%@AE@% field in that top record currently%@NL@%
  6499.      points to the next record in the list. The statement%@NL@%
  6500. %@NL@%
  6501.         %@AS@%stack_ptr := stack_ptr^.next_rec;%@AE@%%@NL@%
  6502. %@NL@%
  6503.      moves %@AS@%stack_ptr%@AE@% to point to the same record that %@AS@%stack_ptr^.next%@AE@%%@AS@%_rec%@AE@%%@NL@%
  6504.      is pointing to. By assigning %@AS@%stack_ptr%@AE@% to point to the same record to%@NL@%
  6505.      which the top record was pointing, there is now no pointer in the list%@NL@%
  6506.      pointing to the record that was on top. The record has been removed%@NL@%
  6507.      from the list.%@NL@%
  6508. %@NL@%
  6509.   4. The old record at the front of the list, pointed to by %@AS@%temp%@AE@%, is now%@NL@%
  6510.      deleted from memory.%@NL@%
  6511. %@NL@%
  6512.         %@AS@%Dispose( temp );%@AE@%%@NL@%
  6513. %@NL@%
  6514. %@CR:MQPB300D@%%@4@%Figure 11.2%@BO:   4f47e@% illustrates the %@AS@%pop%@AE@% procedure.%@EH@%%@NL@%
  6515. %@NL@%
  6516. %@CR:MQPBf200@%%@4@%%@AB@%Figure 11.2  The Pop Procedure%@AE@%%@EH@%%@NL@%
  6517. %@NL@%
  6518. %@AB@%Step 1%@AE@%   %@AS@%z := stack_ptr^.data;%@AE@%%@NL@%
  6519.                                 ┌───────────┐%@NL@%
  6520.                               ┌│     Z     │%@NL@%
  6521.                               │ └───────────┘%@NL@%
  6522.                  ┌───────────┐│ ┌───────────┐%@NL@%
  6523.                  │   data    ├┘ │   data    │%@NL@%
  6524. ┌───────────┐ ┌─├───────────┤┌├───────────┤         ┌──────────┐%@NL@%
  6525. │ stack_ptr ├─┘  │ next_rec  ├┘ │ next_rec  ├─ ∙∙∙ ─│   NIL    │%@NL@%
  6526. └───────────┘    └───────────┘  └───────────┘         └──────────┘%@NL@%
  6527.  %@NL@%
  6528. %@AB@%Step 2%@AE@%   %@AS@%temp := stack_ptr;%@AE@%%@NL@%
  6529.                  ┌───────────┐  ┌───────────┐%@NL@%
  6530.                  │   data    │  │   data    │%@NL@%
  6531. ┌───────────┐ ┌─├───────────┤┌├───────────┤         ┌──────────┐%@NL@%
  6532. │ stack_ptr ├─┤  │ next_rec  ├┘ │ next_rec  ├─ ∙∙∙ ─│   NIL    │%@NL@%
  6533. └───────────┘ │  └───────────┘  └───────────┘         └──────────┘%@NL@%
  6534. ┌───────────┐ │%@NL@%
  6535. │   temp    ├─┘%@NL@%
  6536. └───────────┘%@NL@%
  6537.  %@NL@%
  6538. %@AB@%Step 3%@AE@%   %@AS@%stack_ptr := stack_ptr^.next_rec;%@AE@%%@NL@%
  6539.              ┌────────────────┐%@NL@%
  6540.              │   ┌───────────┐│ ┌───────────┐%@NL@%
  6541.              │   │   data    ││ │   data    │%@NL@%
  6542. ┌───────────┐│┌─├───────────┤├├───────────┤         ┌──────────┐%@NL@%
  6543. │ stack_ptr ├┘│  │ next_rec  ├┘ │ next_rec  ├─ ∙∙∙ ─│   NIL    │%@NL@%
  6544. └───────────┘ │  └───────────┘  └───────────┘         └──────────┘%@NL@%
  6545. ┌───────────┐ │%@NL@%
  6546. │   temp    ├─┘%@NL@%
  6547. └───────────┘%@NL@%
  6548.  %@NL@%
  6549. %@AB@%Step 4%@AE@%   %@AS@%Dispose (temp) ;%@AE@%%@NL@%
  6550.              ┌────────────────┐%@NL@%
  6551.              │  ┌ ─ ─ ─ ─ ─ ┐ │ ┌───────────┐%@NL@%
  6552.              │                │ │   data    │%@NL@%
  6553. ┌───────────┐│  │           │ └├───────────┤         ┌──────────┐%@NL@%
  6554. │ stack_ptr ├┘                  │ next_rec  ├─ ∙∙∙ ─│   NIL    │%@NL@%
  6555. └───────────┘   └ ─ ─ ─ ─ ─ ┘   └───────────┘         └──────────┘%@NL@%
  6556. %@NL@%
  6557. %@NL@%
  6558. %@CR:MQPB4000@%%@2@%%@AB@%11.4  Binary Trees%@AE@%%@EH@%%@NL@%
  6559. %@NL@%
  6560. %@CR:MQPB4001@%%@4@%Binary trees are one of the many types of tree structures that can be%@EH@%
  6561. created with pointer variables. Binary trees are more complex than the
  6562. linked lists described in the previous section. Each record (called a
  6563. "node") has not one, but two pointers. Each of these pointers connects the
  6564. node to two other nodes (called "children")──one on its left and one on its
  6565. right.%@NL@%
  6566. %@NL@%
  6567. %@CR:MQPB4002@%%@4@%Figure 11.3%@BO:   50034@% shows a sample binary tree. As you can see, a left child always%@EH@%
  6568. contains a smaller value than the "parent node," and the right child
  6569. contains a value larger than the parent node. Moreover, the %@AI@%entire subtree%@AE@%
  6570. of a given node contains smaller values than the parent, if on the left
  6571. side, or larger values than the parent, if on the right side. This
  6572. organization permits efficient searching for any value in the tree.%@NL@%
  6573. %@NL@%
  6574. %@NL@%
  6575. %@CR:MQPBf300@%%@4@%%@AB@%Figure 11.3  A Binary Tree%@AE@%%@EH@%%@NL@%
  6576. %@NL@%
  6577.                                %@AB@%Root Node%@AE@%%@NL@%
  6578.                                 ┌─────────┐%@NL@%
  6579.                         ┌───────┤   702   ├─────────┐%@NL@%
  6580.                         │       └─────────┘         │%@NL@%
  6581.                    ┌────┴────┐                 ┌────┴────┐%@NL@%
  6582.           ┌────────┤   659   │                 │   833   ├────────┐%@NL@%
  6583.           │        └─────────┘                 └─────────┘        │%@NL@%
  6584.      ┌────┴────┐                                             ┌────┴────┐%@NL@%
  6585.      │   100   ├────────┐                                    │   853   │%@NL@%
  6586.      └─────────┘        │                                    └─────────┘%@NL@%
  6587.                    ┌────┴────┐%@NL@%
  6588.           ┌────────┤   362   ├────────┐%@NL@%
  6589.           │        └─────────┘        │%@NL@%
  6590.      ┌────┴────┐                 ┌────┴────┐%@NL@%
  6591.      │   239   │        ┌────────┤   640   │%@NL@%
  6592.      └─────────┘        │        └─────────┘%@NL@%
  6593.                    ┌────┴────┐%@NL@%
  6594.           ┌────────┤   622   │%@NL@%
  6595.           │        └─────────┘%@NL@%
  6596.      ┌────┴────┐%@NL@%
  6597.      │   619   │%@NL@%
  6598.      └─────────┘%@NL@%
  6599. %@NL@%
  6600. %@NL@%
  6601. %@CR:MQPB4003@%%@4@%This sample binary tree contains only simple arithmetic nodes. However, you%@EH@%
  6602. can create binary trees containing any kind of information (as long as each
  6603. node is the same type). You can also organize or sort items in the tree
  6604. using a variety of methods.%@NL@%
  6605. %@NL@%
  6606. %@CR:MQPB4004@%%@4@%To build a binary tree, first declare the following types:%@EH@%%@NL@%
  6607. %@NL@%
  6608.  %@AS@%    TYPE%@NL@%
  6609. %@AS@%         node_ptr = ^node;%@NL@%
  6610. %@AS@%         node = RECORD%@NL@%
  6611. %@AS@%             left,%@NL@%
  6612. %@AS@%             right : node_ptr;%@NL@%
  6613. %@AS@%             data  : Word;%@NL@%
  6614. %@AS@%             END;%@NL@%
  6615. %@NL@%
  6616. %@CR:MQPB4005@%%@4@%Similar to the record type of a linked list, the %@AS@%Node%@AE@% type contains pointers%@EH@%
  6617. that point to other records of the same type. If the node currently lacks a
  6618. left or right child, the corresponding pointer field should be initialized
  6619. to %@AB@%NIL%@AE@%.%@NL@%
  6620. %@NL@%
  6621. %@CR:MQPB4006@%%@4@%To create a tree, first declare a pointer to the start of the tree and%@EH@%
  6622. initialize this pointer to %@AB@%NIL%@AE@%,  as shown below. Although no node currently
  6623. exists in the tree, one will be inserted eventually. The first node will
  6624. become the original ancestor of all other nodes in the tree.%@NL@%
  6625. %@NL@%
  6626. %@AS@%     VAR%@NL@%
  6627. %@AS@%         root_ptr : node_ptr;%@NL@%
  6628. %@AS@%     BEGIN%@NL@%
  6629. %@AS@%         root_ptr := NIL;%@NL@%
  6630. %@NL@%
  6631. %@CR:MQPB4007@%%@4@%You can start building the tree by inserting values, which can be generated%@EH@%
  6632. in a number of ways──standard input, a data file, or with the %@AB@%Random%@AE@%
  6633. function. Each time you get a value, add it to the tree by using the
  6634. following five steps:%@NL@%
  6635. %@NL@%
  6636. %@CR:MQPB4008@%  1. Examine %@AS@%root_ptr%@AE@%, the pointer to the first node of the tree. The%@NL@%
  6637.      expression %@AS@%root_ptr^%@AE@% is equivalent to the first node, if one exists. If%@NL@%
  6638.      no node exists, %@AS@%root_ptr%@AE@% is equal to %@AB@%NIL%@AE@%.%@NL@%
  6639. %@NL@%
  6640.   2. If the pointer is %@AB@%NIL%@AE@%, add a new record and assign the pointer to point%@NL@%
  6641.      to this record. Load the %@AS@%data%@AE@% field of the new record with the value to%@NL@%
  6642.      be added.%@NL@%
  6643. %@NL@%
  6644.   3. If the pointer is not %@AB@%NIL%@AE@%, then a node exists and must be compared to%@NL@%
  6645.      the new value. Compare the value to the %@AS@%data%@AE@% field of the node.%@NL@%
  6646. %@NL@%
  6647.   4. If the new value is less than the one at the node, use the %@AS@%left%@AE@% field%@NL@%
  6648.      as the new pointer value, and go to step 2.%@NL@%
  6649. %@NL@%
  6650.   5. If the new value is greater than the one at the node, use the %@AS@%right%@AE@%%@NL@%
  6651.      field as the new pointer value, and go to step 2.%@NL@%
  6652. %@NL@%
  6653. %@CR:MQPB4009@%%@4@%You can use a recursive procedure to implement these steps. Linked lists and%@EH@%
  6654. trees are often good subjects for recursive solutions. As explained in
  6655. Chapter 3%@BO:   13ad7@%, "Procedures and Functions," a "recursive" procedure presents a
  6656. simplified algorithm by calling itself repeatedly. In the case of binary
  6657. trees, a recursive procedure traces left and right branches repeatedly until
  6658. it finds a matching value at the end of the tree.%@NL@%
  6659. %@NL@%
  6660. %@CR:MQPB400A@%%@4@%In the case of the steps discussed above, you initially call the procedure%@EH@%
  6661. by passing the value you want to insert and %@AS@%root_ptr%@AE@% as arguments. The
  6662. procedure calls itself to trace the left or right subtree, each time passing
  6663. the %@AS@%left%@AE@% or %@AS@%right%@AE@% field as the pointer argument, as follows:%@NL@%
  6664. %@NL@%
  6665. %@AS@%     PROCEDURE insert( x : Integer; VAR ptr : node_ptr );%@NL@%
  6666. %@AS@%         BEGIN%@NL@%
  6667. %@AS@%             IF (ptr = NIL) THEN%@NL@%
  6668. %@AS@%                 create_node( x, ptr )%@NL@%
  6669. %@AS@%             ELSE IF (x <ptr^.data) THEN%@NL@%
  6670. %@AS@%                 insert( x, ptr^.left )%@NL@%
  6671. %@AS@%             ELSE%@NL@%
  6672. %@AS@%                 insert( x, ptr^.right );%@NL@%
  6673. %@AS@%         END;%@NL@%
  6674. %@NL@%
  6675. %@CR:MQPB400B@%%@4@%Notice how short the above procedure is. The actual work of inserting the%@EH@%
  6676. node is the last step of the process, and it is carried out by a separate
  6677. procedure written just for that purpose:%@NL@%
  6678. %@NL@%
  6679. %@AS@%     PROCEDURE create_node( x : Integer; VAR ptr : node_ptr );%@NL@%
  6680. %@AS@%         BEGIN%@NL@%
  6681. %@AS@%             New( ptr );%@NL@%
  6682. %@AS@%             ptr^.data  := x;%@NL@%
  6683. %@AS@%             ptr^.left  := NIL;%@NL@%
  6684. %@AS@%             ptr^.right := NIL;%@NL@%
  6685. %@AS@%         END;%@NL@%
  6686. %@NL@%
  6687. %@CR:MQPB400C@%%@4@%The initialization of the %@AS@%left%@AE@% and %@AS@%right%@AE@% fields to %@AB@%NIL%@AE@% is critical.%@EH@%
  6688. Otherwise, the %@AS@%insert%@AE@% procedure produces unpredictable results when it
  6689. reaches the end of the tree and attempts a comparison. The procedures above
  6690. effectively use %@AB@%NIL%@AE@% as the end-of-the-tree indicator.%@NL@%
  6691. %@NL@%
  6692. %@NL@%
  6693. %@CR:MQPC0000@%%@1@%%@AB@%Chapter 12  Advanced Topics%@AE@%%@EH@%%@NL@%
  6694. ───────────────────────────────────────────────────────────────────────────%@NL@%
  6695. %@NL@%
  6696. %@CR:MQPC0001@%%@4@%This chapter gives you a look inside QuickPascal. You can accomplish most%@EH@%
  6697. any standard programming task by using the techniques presented in prior
  6698. chapters. This chapter helps you deal with special situations, such as
  6699. running out of dynamic memory, analyzing internal data formats, and linking
  6700. to assembly language.%@NL@%
  6701. %@NL@%
  6702. %@CR:MQPC0002@%%@4@%The bitwise operators are of special interest to assembly-language%@EH@%
  6703. programmers, but are useful even if you don't use assembly language. You can
  6704. use the bitwise operators to mask out bits within an integer, manipulate
  6705. individual bits, or test a variable to see which bits are on.%@NL@%
  6706. %@NL@%
  6707. %@CR:MQPC0003@%%@4@%After presenting the bitwise operators, the chapter shows a general picture%@EH@%
  6708. of how QuickPascal organizes memory. Then the chapter illustrates internal
  6709. data formats and explains how to link to assembly language.%@NL@%
  6710. %@NL@%
  6711. %@NL@%
  6712. %@CR:MQPC1000@%%@2@%%@AB@%12.1  The Bitwise Operators%@AE@%%@EH@%%@NL@%
  6713. %@NL@%
  6714. %@CR:MQPC1001@%%@4@%You can access and manipulate bits by using the standard Boolean operators%@EH@%
  6715. and the shift operators.%@NL@%
  6716. %@NL@%
  6717. %@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@%
  6718. you use them with integer types. Bitwise operations take two data items of
  6719. the same size and compare each bit in one operand to the corresponding bit
  6720. in the other. For example, consider the following statement:%@NL@%
  6721. %@NL@%
  6722. %@CR:MQPC1003@%%@4@%%@AS@%Result := $FF00 AND $9055;%@AE@% QuickPascal implements this statement by%@EH@%
  6723. comparing each bit in the constant %@AS@%$FF00%@AE@% to each corresponding bit in the
  6724. constant %@AS@%$9055%@AE@%. The %@AB@%AND%@AE@% operator sets a bit in the result to 1, if and only
  6725. if the corresponding bits in both operands have a value of 1:%@NL@%
  6726. %@NL@%
  6727. %@AS@%               $FF00 = 1111 1111  0000 0000%@NL@%
  6728. %@AS@%          AND  $90FF = 1001 0000  1111 1111%@NL@%
  6729.      %@NL@%
  6730. %@AS@%     Result    $9000 = 1001 0000  0000 0000%@NL@%
  6731. %@NL@%
  6732. %@CR:MQPC1004@%%@4@%The result of the operation is %@AS@%$9000%@AE@%. In the example above, using the %@AB@%AND%@AE@%%@EH@%
  6733. operator with the constant %@AS@%$FF00%@AE@% in effect masks out the low 8 bits of a
  6734. 16-bit integer. You can create other constants to selectively mask out any
  6735. combination of bits. For example, you can use the %@AB@%AND%@AE@% operator to test
  6736. whether a value is a multiple of four by masking out all but the lowest two
  6737. bits and determining whether the result is zero:%@NL@%
  6738. %@NL@%
  6739. %@AS@%     IF (x AND $0003 = 0) THEN%@NL@%
  6740. %@AS@%         Writeln( 'x is multiple of 4.' );%@NL@%
  6741. %@NL@%
  6742. %@CR:MQPC1005@%%@4@%Conversely, you can use the %@AB@%OR%@AE@% operator to set specific bits to 1. All of%@EH@%
  6743. the bitwise operators work in a similar way. The following list shows how
  6744. each operator works:%@NL@%
  6745. %@NL@%
  6746. %@CR:MQPC1006@%%@AB@%Operator                    Sets a bit to 1 if:     %@AE@%%@NL@%
  6747. %@NL@%
  6748.    %@AB@%NOT%@AE@%                      The corresponding bit in operand is 0. (This%@NL@%
  6749.                             operator takes just one operand.)%@NL@%
  6750. %@NL@%
  6751.    %@AB@%AND%@AE@%                      Both corresponding bits in the operands have the%@NL@%
  6752.                             value 1.%@NL@%
  6753. %@NL@%
  6754.    %@AB@%OR%@AE@%                       Either one of the corresponding bits in the%@NL@%
  6755.                             operand has the value 1.%@NL@%
  6756. %@NL@%
  6757.    %@AB@%XOR%@AE@%                      Either one, but not both, of the corresponding%@NL@%
  6758.                             bits has the value 1.%@NL@%
  6759. %@NL@%
  6760. %@CR:MQPC1007@%%@4@%The %@AB@%AND%@AE@%, %@AB@%OR%@AE@%, and %@AB@%XOR%@AE@% operators all take two operands each. With each of%@EH@%
  6761. these operators, the two integers you specify must be of the same type. For
  6762. all the bitwise operators, the integer operands may be 8, 16, or 32 bits
  6763. long. (Thus, operations with %@AB@%LongInt%@AE@% types are valid.)%@NL@%
  6764. %@NL@%
  6765. %@CR:MQPC1008@%%@4@%The %@AB@%SHL%@AE@% and %@AB@%SHR%@AE@% operators take an integer operand and move the bits by the%@EH@%
  6766. number of positions specified by the second operand. For example, the binary
  6767. number for 12 is%@NL@%
  6768. %@NL@%
  6769. %@AS@%     $0C = 00001100%@NL@%
  6770. %@NL@%
  6771. %@CR:MQPC1009@%%@4@%When you execute the statement %@AS@%12 SHR 2%@AE@%, each of the bits is moved two%@EH@%
  6772. positions to the right, and the result looks like this:%@NL@%
  6773. %@NL@%
  6774. %@AS@%     $03 = 00000011%@NL@%
  6775. %@NL@%
  6776. %@CR:MQPC100A@%%@4@%The result of the shift is the number 3. Note that shifting right by two is%@EH@%
  6777. equivalent to dividing by 4. Left and right shifts are equivalent to
  6778. multiplying and dividing by a power of two.%@NL@%
  6779. %@NL@%
  6780. %@CR:MQPC100B@%%@4@%The general syntaxes for %@AB@%SHL%@AE@% and %@AB@%SHR%@AE@% are%@EH@%%@NL@%
  6781. %@NL@%
  6782.      %@AI@%IntVar%@AE@% %@AB@%SHL%@AE@% %@AI@%NumPositions%@AE@%%@NL@%
  6783.      %@AI@%IntVar%@AE@% %@AB@%SHR%@AE@% %@AI@%NumPositions%@AE@%%@NL@%
  6784. %@NL@%
  6785. %@CR:MQPC100C@%%@4@%The result is always of the same type as %@AI@%IntVar%@AE@%. The %@AI@%NumPositions%@AE@% argument%@EH@%
  6786. determines the number of bit positions to shift. If this number is equal to
  6787. or larger than the number of bits in %@AI@%IntVar%@AE@%, the result is always zero.%@NL@%
  6788. %@NL@%
  6789. %@NL@%
  6790. %@CR:MQPC2000@%%@2@%%@AB@%12.2  QuickPascal Memory Map%@AE@%%@EH@%%@NL@%
  6791. %@NL@%
  6792. %@CR:MQPC2001@%%@4@%The memory map described in this section shows how a QuickPascal program%@EH@%
  6793. uses memory. This information can help you develop strategies for very large
  6794. programs that may run out of memory quickly.%@NL@%
  6795. %@NL@%
  6796. %@CR:MQPC2002@%%@4@%When you execute a QuickPascal program, it uses all available memory%@EH@%
  6797. (subject to the limits imposed by the %@AB@%{$M}%@AE@% compiler directive as described
  6798. below). Figure 12.1%@BO:   52fbf@% shows the general layout of memory in a QuickPascal
  6799. program, and the rest of the section explains the meaning of items in this
  6800. layout.%@NL@%
  6801. %@NL@%
  6802. %@CR:MQPCf100@%%@4@%%@AB@%Figure 12.1  Quick Pascal Memory Map%@AE@%%@EH@%%@NL@%
  6803. %@NL@%
  6804.                               %@AB@%Top of DOS Memory%@AE@%%@NL@%
  6805.                        ┌─────────────────────────────┐%@NL@%
  6806.                        │ Free List (grows downwards) │%@NL@%
  6807.                        ├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤──── %@AI@%Free_Ptr%@AE@%%@NL@%
  6808.                        │                             │%@NL@%
  6809.                        │         Free Memory         │%@NL@%
  6810.                        │                             │%@NL@%
  6811.                        ├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤──── %@AI@%Heap_Ptr%@AE@%%@NL@%
  6812.                        │                             │%@NL@%
  6813.                        │    Heap (grows upwards)     │%@NL@%
  6814.                        │                             │%@NL@%
  6815.                        ├─────────────────────────────┤──── %@AI@%HeapOrg%@AE@%%@NL@%
  6816.                        │   Stack (grows downwards)   │%@NL@%
  6817.                        ├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤──── %@AI@%SSeg:SPtr%@AE@%%@NL@%
  6818.                        │          Free Stack         │%@NL@%
  6819.                        ├─────────────────────────────┤──── %@AI@%SSeg:0000%@AE@%%@NL@%
  6820.                        │      Global Variables       │%@NL@%
  6821.                      ┌─├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤%@NL@%
  6822.                      │ │      Typed Constants        │%@NL@%
  6823.                      │ ├─────────────────────────────┤──── %@AI@%DSeg:0000%@AE@%%@NL@%
  6824.                      │ │  System Unit Code Segment   │%@NL@%
  6825.                      │ ├─────────────────────────────┤%@NL@%
  6826.                      │ │   First Unit Code Segment   │%@NL@%
  6827.                      │ ├─────────────────────────────┤%@NL@%
  6828.       %@AI@%Contents of%@AE@%    │%@NL@%
  6829.       %@AI@%an executable%@AE@% ─┤ │  Other Unit Code Segments   │%@NL@%
  6830.       %@AI@%file image%@AE@%     │%@NL@%
  6831.                      │ ├─────────────────────────────┤%@NL@%
  6832.                      │ │   Last Unit Code Segment    │%@NL@%
  6833.                      │ ├─────────────────────────────┤%@NL@%
  6834.                      │ │                             │%@NL@%
  6835.                      │ │  Main Program Code Segment  │%@NL@%
  6836.                      │ │                             │%@NL@%
  6837.                      └─├─────────────────────────────┤%@NL@%
  6838.                        │ Program Segment Prefix (PSP)│%@NL@%
  6839.                        └─────────────────────────────┘──── %@AI@%PrefixSeg%@AE@%%@NL@%
  6840. %@NL@%
  6841. %@NL@%
  6842. %@CR:MQPC2003@%%@4@%The solid lines in Figure 12.1%@BO:   52fbf@% show demarcations between segments. A%@EH@%
  6843. "segment" is an area of memory that can be up to 64K in length. Thus, as you
  6844. can see from Figure 12.1%@BO:   52fbf@%, the code segment of the main program can never be
  6845. more than 64K. However, for very large programs, you can surpass the 64K
  6846. limit by simply adding additional units. The amount of code for each unit
  6847. can be as large as 64K.%@NL@%
  6848. %@NL@%
  6849. %@CR:MQPC2004@%%@4@%All global variables and typed constants are placed in a single segment.%@EH@%
  6850. Thus, the total size of these data items cannot exceed 64K across all units.%@NL@%
  6851. %@NL@%
  6852. %@CR:MQPC2005@%%@4@%The stack is placed in its own segment. You can set the stack size with the%@EH@%
  6853. %@AB@%{$M}%@AE@% compiler directive. Increasing the stack lets the program accommodate
  6854. more procedure calls, but may take away from memory available for the heap.
  6855. (See Appendix B%@BO:   857d9@%, "Compiler Directives.")%@NL@%
  6856. %@NL@%
  6857. %@CR:MQPC2006@%%@4@%The heap consists of the rest of available RAM, unless you use the %@AB@%{$M}%@AE@%%@EH@%
  6858. compiler directive to set maximum heap size. The heap contains all dynamic
  6859. variables allocated through calls to %@AB@%New%@AE@% or %@AB@%GetMem%@AE@%. If you know in advance
  6860. that your program %@AI@%must%@AE@% have a certain amount of heap space to run properly,
  6861. you can use the %@AB@%{$M}%@AE@% compiler directive to specify a minimum heap size. DOS
  6862. will not load the program unless it can allocate enough memory for the
  6863. requested minimum heap size.%@NL@%
  6864. %@NL@%
  6865. %@CR:MQPC2007@%%@4@%Certain variables appear in the QuickPascal memory map. These are public%@EH@%
  6866. variables declared in the %@AB@%System%@AE@% unit, and your program can access them at
  6867. any time (no special declaration is needed to use the %@AB@%System%@AE@% unit).%@NL@%
  6868. %@NL@%
  6869. %@CR:MQPC2008@%%@4@%The following list describes the public variables appearing in the memory%@EH@%
  6870. map:%@NL@%
  6871. %@NL@%
  6872. %@CR:MQPC2009@%%@AB@%Variable  Description     %@AE@%%@NL@%
  6873. %@NL@%
  6874. %@AB@%FreePtr%@AE@%                     Pointer to beginning of "free list," (as%@NL@%
  6875.                             described in Section 12.3%@BO:   548d8@%). The free list is a%@NL@%
  6876.                             series of records that describes the size and%@NL@%
  6877.                             location of free mem-ory blocks inside the heap.%@NL@%
  6878.                             As the free list grows, %@AB@%FreePtr%@AE@% decreases%@NL@%
  6879.                             because the free list grows downward.%@NL@%
  6880. %@NL@%
  6881. %@AB@%HeapPtr%@AE@%                     Pointer to top of heap. As the amount of space%@NL@%
  6882.                             needed by dynamic variables increases, %@AB@%HeapPtr%@AE@%%@NL@%
  6883.                             increases. It decreases only when memory is%@NL@%
  6884.                             freed from the top of the heap.%@NL@%
  6885. %@NL@%
  6886. %@AB@%HeapOrg%@AE@%                     Pointer to beginning of heap. This variable has%@NL@%
  6887.                             the generic type %@AB@%POINTER%@AE@%, as do the other%@NL@%
  6888.                             pointers declared in the %@AB@%System%@AE@% unit. You cannot%@NL@%
  6889.                             dereference pointers of this type, but you can%@NL@%
  6890.                             assign the value of such a pointer to any other%@NL@%
  6891.                             pointer, regardless of type.%@NL@%
  6892. %@NL@%
  6893. %@AB@%PrefixSeg%@AE@%                   Word variable containing segment address of%@NL@%
  6894.                             Program Segment Prefix (PSP). When DOS loads%@NL@%
  6895.                             your program, it constructs the PSP to store%@NL@%
  6896.                             command-line arguments, interrupt vectors, and%@NL@%
  6897.                             other information. See the %@AI@%MS-DOS Programmer's%@AE@%%@NL@%
  6898.                             %@AI@%Reference%@AE@% or %@AI@%MS-DOS Encyclopedia%@AE@% for more%@NL@%
  6899.                             information.%@NL@%
  6900. %@NL@%
  6901. %@NL@%
  6902. %@CR:MQPC3000@%%@2@%%@AB@%12.3  Managing the Heap%@AE@%%@EH@%%@NL@%
  6903. %@NL@%
  6904. %@CR:MQPC3001@%%@4@%The simplest way to create dynamic variables is to make calls to %@AB@%New%@AE@% and%@EH@%
  6905. %@AB@%GetMem%@AE@%. In small programs, you can generally call these procedures without
  6906. worrying about how the heap is managed. However, if your programs make heavy
  6907. use of dynamic memory, you can sometimes avoid running out of memory by
  6908. knowing how the heap works.%@NL@%
  6909. %@NL@%
  6910. %@CR:MQPC3002@%%@4@%The basic model of the heap is simple. Initially, the %@AB@%New%@AE@% and %@AB@%GetMem%@AE@%%@EH@%
  6911. procedures simply increment %@AB@%HeapPtr%@AE@% by the size of the memory block you
  6912. request and return a pointer to the beginning of the block.%@NL@%
  6913. %@NL@%
  6914. %@CR:MQPC3003@%%@4@%The structure of the heap becomes more complicated when you start freeing%@EH@%
  6915. blocks of memory. If you free memory at the current top of the heap, %@AB@%HeapPtr%@AE@%
  6916. is decreased by the amount of memory freed. More often, however, the block
  6917. to be freed is somewhere in the middle of the heap. In this case, the
  6918. free-memory procedure (%@AB@%Dispose%@AE@% or %@AB@%FreeMem%@AE@%) adds a record to the free list to
  6919. record the existence of the freed block.%@NL@%
  6920. %@NL@%
  6921. %@CR:MQPC3004@%%@4@%The free block is then like a hole in the middle of the heap. The next time%@EH@%
  6922. you request memory, the allocation procedure attempts to allocate memory
  6923. from a free block if it can. Furthermore, if a block is freed adjacent to an
  6924. existing free block, the two blocks form one larger free block, and the free
  6925. list is updated to reflect this fact.%@NL@%
  6926. %@NL@%
  6927. %@CR:MQPC3005@%%@4@%The maximum number of free blocks that Pascal programs can maintain is%@EH@%
  6928. 8,192. Programs rarely reach this limit. However, you can use a variety of
  6929. techniques to manage the heap, each of which is explained in a section
  6930. below:%@NL@%
  6931. %@NL@%
  6932. %@CR:MQPC3006@%  ■  Use the %@AB@%Mark%@AE@% and %@AB@%Release%@AE@% functions to free memory efficiently%@NL@%
  6933. %@NL@%
  6934.   ■  Determine the amount of heap space left and the number of records in%@NL@%
  6935.      the free list%@NL@%
  6936. %@NL@%
  6937.   ■  Set the %@AB@%FreeMin%@AE@% variable to prevent a deadlock between the heap and the%@NL@%
  6938.      free list%@NL@%
  6939. %@NL@%
  6940.   ■  Write a customized %@AB@%HeapError%@AE@% function to control how the program%@NL@%
  6941.      responds when you run out of heap space (the default action is to abort%@NL@%
  6942.      execution)%@NL@%
  6943. %@NL@%
  6944. %@NL@%
  6945. %@CR:MQPC3100@%%@3@%%@AB@%12.3.1  Using Mark and Release to Free Memory%@AE@%%@EH@%%@NL@%
  6946. %@NL@%
  6947. %@CR:MQPC3101@%%@4@%The %@AB@%Mark%@AE@% and %@AB@%Release%@AE@% procedures provide a simpler and more efficient way to%@EH@%
  6948. free memory than %@AB@%Dispose%@AE@% or %@AB@%FreeMem%@AE@%. However, the use of %@AB@%Mark%@AE@% and %@AB@%Release%@AE@%
  6949. requires that you release memory in the reverse order to that in which you
  6950. allocated it. Not all programs can adhere to this requirement.%@NL@%
  6951. %@NL@%
  6952. %@CR:MQPC3102@%%@4@%The %@AB@%Mark%@AE@% procedure sets a pointer to point to the current top of the heap.%@EH@%
  6953. The pointer can have any base type. Then if you allocate more dynamic
  6954. memory, the new memory is higher in memory than the marked location (because
  6955. the heap grows upward).%@NL@%
  6956. %@NL@%
  6957. %@CR:MQPC3103@%%@4@%The %@AB@%Release%@AE@% procedure takes a single pointer as an argument, just as %@AB@%Mark%@AE@%%@EH@%
  6958. does, and releases all dynamic memory above the pointer. In other words, it
  6959. releases all memory allocated after the %@AB@%Mark%@AE@% procedure was called. The
  6960. %@AB@%Release%@AE@% procedure basically works by setting %@AB@%HeapPtr%@AE@% to the value of the
  6961. pointer argument.%@NL@%
  6962. %@NL@%
  6963. %@CR:MQPC3104@%%@4@%For example, the following code allocates five dynamic variables:%@EH@%%@NL@%
  6964. %@NL@%
  6965. %@AS@%     New( PtrA );%@NL@%
  6966. %@AS@%     New( PtrB );%@NL@%
  6967. %@AS@%     Mark( Ptrs );%@NL@%
  6968. %@AS@%     New( PtrC );%@NL@%
  6969. %@AS@%     New( PtrD );%@NL@%
  6970. %@NL@%
  6971. %@CR:MQPC3105@%%@4@%The next line of code releases the pointers declared after the %@AS@%Mark( Ptrs )%@AE@%%@EH@%
  6972. statement. Specifically, it frees the memory pointed to by %@AS@%PtrC%@AE@% and %@AS@%PtrD%@AE@%:%@NL@%
  6973. %@NL@%
  6974. %@AS@%     Release( Ptrs );%@NL@%
  6975. %@NL@%
  6976. %@CR:MQPC3106@%%@4@%%@AB@%Mark%@AE@% and %@AB@%Release%@AE@% impose significant limitations on program logic because%@EH@%
  6977. they do not let you randomly free any block of memory; you can only free
  6978. contiguous blocks at the top of the heap. However, if you use these
  6979. procedures, you have none of the problems that sometimes occur with a free
  6980. list.%@NL@%
  6981. %@NL@%
  6982. %@CR:MQPC3107@%%@4@%Note that the %@AB@%Mark%@AE@% and %@AB@%Release%@AE@% procedures are not compatible with %@AB@%Dispose%@AE@%%@EH@%
  6983. and %@AB@%FreeMem%@AE@%. Once you use one of the latter two procedures, you should not
  6984. call %@AB@%Release%@AE@%.%@NL@%
  6985. %@NL@%
  6986. %@NL@%
  6987. %@CR:MQPC3200@%%@3@%%@AB@%12.3.2  Determining Free Memory and Size of the Free List%@AE@%%@EH@%%@NL@%
  6988. %@NL@%
  6989. %@CR:MQPC3201@%%@4@%Two functions let you determine the amount of free memory available:%@EH@%%@NL@%
  6990. %@NL@%
  6991. %@CR:MQPC3202@%  ■  The %@AB@%MemAvail%@AE@% function returns the total number of free bytes in the%@NL@%
  6992.      heap.%@NL@%
  6993. %@NL@%
  6994.   ■  The %@AB@%MaxAvail%@AE@% function returns the size of the largest single free block%@NL@%
  6995.      in the heap──in other words, the largest amount of memory that you can%@NL@%
  6996.      successfully request.%@NL@%
  6997. %@NL@%
  6998. %@CR:MQPC3203@%%@4@%Generally, the %@AB@%MaxAvail%@AE@% function is the more useful of the two functions,%@EH@%
  6999. since it lets you know whether any given call to %@AB@%New%@AE@% or %@AB@%GetMem%@AE@% will be
  7000. successful. Both the %@AB@%MemAvail%@AE@% and %@AB@%MaxAvail%@AE@% functions return a %@AB@%LongInt%@AE@%
  7001. result, and neither takes any parameters.%@NL@%
  7002. %@NL@%
  7003. %@CR:MQPC3204@%%@4@%Determining the size of the free list also helps you discover if you are%@EH@%
  7004. going to run out of memory. The free list is declared as follows:%@NL@%
  7005. %@NL@%
  7006. %@AS@%     TYPE%@NL@%
  7007. %@AS@%         FreeRec = RECORD%@NL@%
  7008. %@AS@%             OrgPtr, EndPtr : Pointer;%@NL@%
  7009. %@AS@%             END;%@NL@%
  7010. %@NL@%
  7011. %@AS@%         FreeList = ARRAY [0..8190] OF FreeRec;%@NL@%
  7012. %@AS@%         FreeListP = ^FreeList;%@NL@%
  7013. %@NL@%
  7014. %@CR:MQPC3205@%%@4@%Each record in the free list defines a single free memory block; the  %@AS@%OrgPtr%@AE@%%@EH@%
  7015. and %@AS@%EndPtr%@AE@% fields define the beginning and ending address, respectively, of
  7016. the block. %@AS@%EndPtr%@AE@% points to the first byte after the end of the block. You
  7017. can calculate the number of free blocks recorded in the free list by using
  7018. the following statement:%@NL@%
  7019. %@NL@%
  7020. %@AS@%     free_blocks := (8192 - Ofs( FreePtr^ ) DIV 8) MOD 8192;%@NL@%
  7021. %@NL@%
  7022. %@CR:MQPC3206@%%@4@%When the offset portion of the address in %@AB@%FreePtr%@AE@% is 0, the free list is%@EH@%
  7023. empty. As a free block is added to the list, %@AB@%FreePtr%@AE@% decreases by eight
  7024. bytes, and the free list also grows downward by eight.%@NL@%
  7025. %@NL@%
  7026. %@NL@%
  7027. %@CR:MQPC3300@%%@3@%%@AB@%12.3.3  Preventing Deadlock with the Free List%@AE@%%@EH@%%@NL@%
  7028. %@NL@%
  7029. %@CR:MQPC3301@%%@4@%If the top of the heap is very close to the bottom of the free list, then%@EH@%
  7030. deadlock can occur when you try to free blocks of memory. If the blocks to
  7031. be freed are at the top of the heap, there is no problem. Otherwise, the
  7032. free list is blocked from expanding.%@NL@%
  7033. %@NL@%
  7034. %@CR:MQPC3302@%%@4@%This problem always causes a run-time error. You can neither allocate new%@EH@%
  7035. dynamic memory nor free any existing memory. The only way to prevent this
  7036. situation is to set a minimum amount of space between the locations pointed
  7037. to by %@AB@%HeapPtr%@AE@% and %@AB@%FreePtr%@AE@%.%@NL@%
  7038. %@NL@%
  7039. %@CR:MQPC3303@%%@4@%The %@AB@%FreeMin%@AE@% system variable sets the minimum free memory space (between the%@EH@%
  7040. top of the heap and bottom of the free list). This variable has type %@AB@%Word%@AE@%
  7041. and represents a distance in bytes. The %@AB@%New%@AE@% and %@AB@%FreeMem%@AE@% procedures will not
  7042. allocate a block of memory if doing so would make the space between the heap
  7043. and the free list fall below %@AB@%FreeMin%@AE@%. The %@AB@%MemAvail%@AE@% and %@AB@%MaxAvail%@AE@% functions
  7044. also take %@AB@%FreeMin%@AE@% into account by subtracting it from the free memory area.%@NL@%
  7045. %@NL@%
  7046. %@NL@%
  7047. %@CR:MQPC3400@%%@3@%%@AB@%12.3.4  Writing a Heap-Error Function%@AE@%%@EH@%%@NL@%
  7048. %@NL@%
  7049. %@CR:MQPC3401@%%@4@%By default, the %@AB@%New%@AE@% and %@AB@%GetMem%@AE@% procedures simply abort program execution%@EH@%
  7050. when they cannot return a memory block of the requested size. However, you
  7051. can create a customized function to respond to heap errors.%@NL@%
  7052. %@NL@%
  7053. %@CR:MQPC3402@%%@4@%Your heap-error function is called by %@AB@%New%@AE@% and %@AB@%GetMem%@AE@% as needed, and it can%@EH@%
  7054. return one of three values:%@NL@%
  7055. %@NL@%
  7056. %@CR:MQPC3403@%%@AB@%Value                  Meaning%@AE@%%@NL@%
  7057. %@NL@%
  7058. 0                      Failure; abort program%@NL@%
  7059. %@NL@%
  7060. 1                      Failure; return the %@AB@%NIL%@AE@% pointer value to the%@NL@%
  7061.                        caller of %@AB@%New%@AE@% or %@AB@%GetMem%@AE@%, but do not abort program%@NL@%
  7062. %@NL@%
  7063. 2                      Memory successfully freed; authorize %@AB@%New%@AE@% or %@AB@%%@AE@%%@NL@%
  7064.                        %@AB@%GetMem%@AE@% to retry%@NL@%
  7065. %@NL@%
  7066. %@CR:MQPC3404@%%@4@%Your function should return the value 2 only if it was able to find a%@EH@%
  7067. disposable dynamic variable in your program and free the necessary memory.
  7068. If the function returns 2 without freeing memory first, then it will be
  7069. called again.%@NL@%
  7070. %@NL@%
  7071. %@CR:MQPC3405@%%@4@%To create a heap-error function, first declare a function similar to the one%@EH@%
  7072. below:%@NL@%
  7073. %@NL@%
  7074. %@AS@%     {$F+}%@NL@%
  7075. %@AS@%     FUNCTION heap_err( size : Word ) : Integer;%@NL@%
  7076. %@AS@%     {$F-}%@NL@%
  7077. %@AS@%     BEGIN%@NL@%
  7078. %@AS@%         { Cause FreeMem to return NIL but continue execution }%@NL@%
  7079. %@AS@%         heap_err := 1;%@NL@%
  7080. %@AS@%     END;%@NL@%
  7081. %@NL@%
  7082. %@CR:MQPC3406@%%@4@%You can give the function any name you want and supply any statements in the%@EH@%
  7083. body of the function. However, the rest of the declaration should be the
  7084. same. In particular, the %@AB@%{$F+}%@AE@% compiler directive is necessary to make sure
  7085. the function is compiled for far calls. The single parameter of type %@AB@%Word%@AE@%
  7086. gives the size of the memory block that %@AB@%New%@AE@% or %@AB@%GetMem%@AE@% failed to allocate.%@NL@%
  7087. %@NL@%
  7088. %@CR:MQPC3407@%%@4@%After declaring your heap-error function, set the %@AB@%HeapError%@AE@% system variable%@EH@%
  7089. to point to your function:%@NL@%
  7090. %@NL@%
  7091. %@AS@%     HeapError := @heap_err;%@NL@%
  7092. %@NL@%
  7093. %@NL@%
  7094. %@CR:MQPC4000@%%@2@%%@AB@%12.4  Internal Data Formats%@AE@%%@EH@%%@NL@%
  7095. %@NL@%
  7096. %@CR:MQPC4001@%%@4@%Knowledge of internal data formats is useful if you want to write%@EH@%
  7097. assembly-language procedures that access data from QuickPascal programs.
  7098. Furthermore, you can use this knowledge to help determine what data types
  7099. most efficiently store information for a given program.%@NL@%
  7100. %@NL@%
  7101. %@CR:MQPC4002@%%@4@%Section 12.4.1%@BO:   574ac@% describes the data formats for all types except%@EH@%
  7102. floating-point numbers. The floating-point data types are described
  7103. separately in Section 12.4.2%@BO:   58bd3@%, because of their complexity.%@NL@%
  7104. %@NL@%
  7105. %@NL@%
  7106. %@CR:MQPC4100@%%@3@%%@AB@%12.4.1  Non-Floating-Point Data Types%@AE@%%@EH@%%@NL@%
  7107. %@NL@%
  7108. %@CR:MQPC4101@%%@4@%The list that follows describes the internal formats of most data types,%@EH@%
  7109. including structured variables such as arrays and records. Note that any
  7110. given type is stored the same way, whether it is a simple variable or part
  7111. of a record.%@NL@%
  7112. %@NL@%
  7113. %@CR:MQPC4102@%%@4@%Where an integer value is designated as signed, QuickPascal uses the two's%@EH@%
  7114. complement format for storing negative numbers. This format represents the
  7115. negative of a number by logically negating each bit (as is done by the %@AB@%NOT%@AE@%
  7116. operator) and then adding 1. For example, since 00000011 represents 3, then
  7117. 11111100 is the logical negation, and 11111101 is the two's complement of 3.%@NL@%
  7118. %@NL@%
  7119. %@CR:MQPC4103@%%@4@%Therefore, if you declare a %@AB@%Byte%@AE@% constant as -3, QuickPascal stores this%@EH@%
  7120. value as 11111101. Generally speaking, you never have to carry out
  7121. two's-complement conversion yourself. It is simply an internal format
  7122. understood by both Quick-Pascal and the 8086 family of processors.%@NL@%
  7123. %@NL@%
  7124. %@CR:MQPC4104@%%@4@%As a consequence, all nonnegative numbers have 0 in the most significant%@EH@%
  7125. bit; all negative numbers have 1 in the most significant bit. The unsigned
  7126. formats do not consider any number to be negative.%@NL@%
  7127. %@CR:MQPC4105@%%@NL@%
  7128. %@TH:   74   4518  2 28 48 @%
  7129. %@AB@%Data Type                   Internal Format%@AE@%
  7130.  
  7131. %@AB@%Char%@AE@%                        An unsigned byte. (Values range from 0 to 255.)
  7132.  
  7133. %@AB@%Byte%@AE@%                        A signed byte. (Values range from -128 to 127.)
  7134.  
  7135. %@AB@%Integer%@AE@%                     A signed word. (Values range from -32768 to
  7136.                             32767.)
  7137.  
  7138. %@AB@%Word%@AE@%                        An unsigned word. (Values range from 0 to
  7139.                             65535.)
  7140.  
  7141. %@AB@%LongInt%@AE@%                     A signed double word. (Values range from
  7142.                             -2147483648 to 2147483647.)
  7143.  
  7144. %@AB@%Comp%@AE@%                        A signed eight-byte integer. If the
  7145.                             most-significant bit is 1 and the other bits are
  7146.                             all 0, this type has the special value NAN (Not
  7147.                             a Number). Note that with the %@AB@%{N+}%@AE@% directive,
  7148.                             QuickPascal uses the 8087 coprocessor, if
  7149.                             installed, to do calculations with %@AB@%Comp%@AE@% types.
  7150.  
  7151. %@AB@%Boolean%@AE@%                     A byte assuming the value 0 (%@AB@%False%@AE@%) or 1 (%@AB@%True%@AE@%).
  7152.  
  7153. Enumerated types            Stored as an unsigned byte if the type can
  7154.                             assume 256 values or fewer. Otherwise, the
  7155.                             enumerated type is stored as an unsigned word.
  7156.                             The first item in an enumerated-type definition
  7157.                             corresponds to the value 0, and the rest are
  7158.                             numbered sequentially in the order given.
  7159.  
  7160. %@AB@%STRING%@AE@% types                A sequence of bytes in which the first byte
  7161.                             stores the current length of the string (which
  7162.                             may be less than its maximum length), and the
  7163.                             rest of the bytes store the string data.
  7164.                             QuickPascal allocates enough space for a
  7165.                             string's maximum length plus one additional byte
  7166.                             (for the length indicator). The generic %@AB@%STRING%@AE@%
  7167.                             type is equivalent to %@AS@%STRING[255]%@AE@%, which has the
  7168.                             maximum limit.
  7169.  
  7170. %@AB@%CSTRING%@AE@%                     Similar to %@AB@%STRING%@AE@% types, except that the first
  7171.                             byte is not a length indicator, and the string
  7172.                             data includes a terminating null byte. Maximum
  7173.                             limit is 255 + null bytes. The generic %@AB@%CSTRING%@AE@%
  7174.                             type defaults to this length.
  7175.  
  7176. %@AB@%SET%@AE@% types                   Stored as a bit array, in which each bit
  7177.                             corresponds to a specific element. If a bit is
  7178.                             on, then the corresponding element is present.
  7179.                             QuickPascal allocates one byte for each element,
  7180.                             up to a maximum of 32 bytes (256 elements).
  7181.                             Elements within a set are stored in order of
  7182.                             their ordinal value, in which the first element
  7183.                             is stored in the least-significant bit.
  7184.  
  7185. %@AB@%ARRAY%@AE@% types                 Elements of the array are stored contiguously in
  7186.                             memory, starting from the lowest-indexed
  7187.                             component and going in sequence to the highest.
  7188.                             In multidimensional arrays, the rightmost index
  7189.                             changes fastest. Thus, in the array declared as
  7190.                             %@AS@%Grid[Rows,Cols]%@AE@%, all elements for an entire row
  7191.                             are stored next to each other in memory.
  7192.  
  7193. %@AB@%RECORD%@AE@% types                A sequence of variables stored contiguously in
  7194.                             memory (the fields appear in memory in the same
  7195.                             order they do in source code). With variant
  7196.                             records, each variant case starts at the same
  7197.                             address.
  7198.  
  7199. Pointer types               A double word that contains the offset address
  7200.                             in the low word and the segment address in the
  7201.                             high word. The special value %@AB@%NIL%@AE@% is a generic
  7202.                             pointer containing the value zero.
  7203. %@TE:   74   4518  2 28 48 @%
  7204. %@NL@%
  7205. %@CR:MQPC4200@%%@3@%%@AB@%12.4.2  Floating-Point Data Types%@AE@%%@EH@%%@NL@%
  7206. %@NL@%
  7207. %@CR:MQPC4201@%%@4@%Figure 12.2 displays the formats used to represent floating-point numbers of%@EH@%
  7208. different levels of precision. QuickPascal uses these data formats whether
  7209. or not a math coprocessor is installed. If a coprocessor is not installed,
  7210. then Quick-Pascal provides procedures to execute floating-point
  7211. calculations. In cases of rounding, these procedures are not guaranteed to
  7212. produce precisely the same results as a coprocessor.%@NL@%
  7213. %@NL@%
  7214. %@CR:MQPCf200@%%@4@%%@AB@%Figure 12.2  QuickPascal Data Formats%@AE@%%@EH@%%@NL@%
  7215. %@NL@%
  7216. %@AB@%Real Type%@AE@%%@NL@%
  7217.    Width   1                    39                         8%@NL@%
  7218.          ┌───┬──────────────────────────────────────┬─────────────┐%@NL@%
  7219.          │ s │                  f                   │      e      │%@NL@%
  7220.          └───┴──────────────────────────────────────┴─────────────┘%@NL@%
  7221.    Bits   47                                                     0%@NL@%
  7222. %@NL@%
  7223. %@AB@%Single Type%@AE@%%@NL@%
  7224.    Width   1        8                           23%@NL@%
  7225.          ┌───┬─────────────┬──────────────────────────────────────┐%@NL@%
  7226.          │ s │      e      │                    f                 │%@NL@%
  7227.          └───┴─────────────┴──────────────────────────────────────┘%@NL@%
  7228.    Bits   31                                                     0%@NL@%
  7229. %@NL@%
  7230. %@AB@%Double Type%@AE@%%@NL@%
  7231.    Width   1        11                          52%@NL@%
  7232.          ┌───┬─────────────┬──────────────────────────────────────┐%@NL@%
  7233.          │ s │      e      │                    f                 │%@NL@%
  7234.          └───┴─────────────┴──────────────────────────────────────┘%@NL@%
  7235.    Bits   63                                                     0%@NL@%
  7236. %@NL@%
  7237. %@AB@%Extended Type%@AE@%%@NL@%
  7238.    Width   1        15     1                    63%@NL@%
  7239.          ┌───┬───────────┬───┬────────────────────────────────────┐%@NL@%
  7240.          │ s │      e    │ i │                  f                 │%@NL@%
  7241.          └───┴───────────┴───┴────────────────────────────────────┘%@NL@%
  7242.    Bits   79                                                     0%@NL@%
  7243. %@NL@%
  7244. %@AB@%Comp Type%@AE@%%@NL@%
  7245.    Width   1                             63%@NL@%
  7246.          ┌───┬────────────────────────────────────────────────────┐%@NL@%
  7247.          │ s │                           d                        │%@NL@%
  7248.          └───┴────────────────────────────────────────────────────┘%@NL@%
  7249.    Bits   63                                                     0%@NL@%
  7250. %@NL@%
  7251. %@NL@%
  7252. %@CR:MQPC4202@%%@4@%With each of the formats illustrated in Figure 12.2%@BO:   58df2@%, the sign bit (s)%@EH@%
  7253. indicates a negative number if on, and a nonnegative number if off. The
  7254. fractional part (f) indicates the fractional part of the mantissa. To save
  7255. space, the data formats all assume that the units' digit in the mantissa is
  7256. equal to 1. Finally, the exponent is adjusted downward by a different number
  7257. for each format. This means that for the four-byte %@AB@%Single%@AE@% type, the value
  7258. represented is equal to%@NL@%
  7259. %@NL@%
  7260.      -1^(s) * 1.f * 2^(e-127)%@NL@%
  7261. %@NL@%
  7262. %@CR:MQPC4204@%%@4@%For example, assume a variable of this type contains the following values:%@EH@%%@NL@%
  7263. %@NL@%
  7264. %@AS@%     s = 0%@NL@%
  7265. %@AS@%     e = 127  decimal%@NL@%
  7266. %@AS@%     f = 11110100000000000000000  binary%@NL@%
  7267. %@NL@%
  7268. %@CR:MQPC4205@%%@4@%The value of the variable is 1.111101 binary. Note that (in contrast to%@EH@%
  7269. Figure 12.2%@BO:   58df2@% and the example above) data storage on 8086 processors actually
  7270. runs from least-significant bit (stored lowest in memory) to
  7271. most-significant bit. This fact may make bytes appear to be backward if you
  7272. use a debugging tool to dump a word at a time.%@NL@%
  7273. %@NL@%
  7274. %@CR:MQPC4206@%%@4@%The exponents are automatically reduced by 129 for the six-byte %@AB@%Real%@AE@% format,%@EH@%
  7275. by 1,023 for the %@AB@%Double%@AE@% format, and by 16,383 for the %@AB@%Extended%@AE@% format. This
  7276. automatic reduction lets the exponent field represent a negative number
  7277. (producing a floating-point value between 1 and -1).%@NL@%
  7278. %@NL@%
  7279. %@CR:MQPC4207@%%@4@%In each format, if all bits are set to zero, then the resulting%@EH@%
  7280. floating-point number is equal to zero.%@NL@%
  7281. %@NL@%
  7282. %@NL@%
  7283. %@CR:MQPC5000@%%@2@%%@AB@%12.5  Linking to Assembly Language%@AE@%%@EH@%%@NL@%
  7284. %@NL@%
  7285. %@CR:MQPC5001@%%@4@%You can link QuickPascal programs to modules written with the Microsoft%@EH@%
  7286. Macro Assembler and other assemblers. However, be forewarned that
  7287. Quick-Pascal has a number of conventions and restrictions that differ from
  7288. other Microsoft languages. When you write an assembly-language procedure to
  7289. link to QuickPascal, your assembly-language module can include%@NL@%
  7290. %@NL@%
  7291. %@CR:MQPC5002@%  ■  Procedures and functions that the main program can call%@NL@%
  7292. %@NL@%
  7293.   ■  References to global variables or data from a unit declared in an%@NL@%
  7294.      %@AB@%INTERFACE%@AE@% statement%@NL@%
  7295. %@NL@%
  7296.   ■  Static data that is private to your assembly-language module%@NL@%
  7297. %@NL@%
  7298. %@CR:MQPC5003@%%@4@%However, the assembly-language module cannot declare public data for the%@EH@%
  7299. QuickPascal code to reference. Furthermore, an assembly-language module must
  7300. place all instructions in a single segment named CODE, and cannot use the
  7301. %@AB@%GROUP%@AE@% directive. (Segment conventions are described in Section 12.5.2.%@BO:   5a798@%)
  7302. Sections 12.5.1%@BO:   5a2af@%-12.5.6 list steps for writing an assembly-language module,
  7303. in roughly the order that you would observe them in writing the code. You
  7304. should read all of these sections carefully before attempting to write an
  7305. assembly-language procedure (although the section on return values is
  7306. optional and applies only when you write a function). Section 12.5.7%@BO:   5cf03@% has a
  7307. simple, but complete, example.%@NL@%
  7308. %@NL@%
  7309. %@NL@%
  7310. %@CR:MQPC5100@%%@3@%%@AB@%12.5.1  Setting Up a Link to Assembly Language%@AE@%%@EH@%%@NL@%
  7311. %@NL@%
  7312. %@CR:MQPC5101@%%@4@%To link to assembly language, you must write an %@AB@%EXTERNAL%@AE@% declaration for%@EH@%
  7313. each assembly-language procedure you're going to call and use the %@AB@%{$L}%@AE@%
  7314. compiler directive to link in the object file.%@NL@%
  7315. %@NL@%
  7316. %@CR:MQPC5102@%%@4@%To write an %@AB@%EXTERNAL%@AE@% declaration, simply write a procedure or function%@EH@%
  7317. heading as you would normally and follow the heading with the keyword
  7318. %@AB@%EXTERNAL%@AE@% as shown below:%@NL@%
  7319. %@NL@%
  7320. %@AS@%     FUNCTION compute( a, b, c: Integer ) : Integer; EXTERNAL;%@NL@%
  7321. %@AS@%     PROCEDURE switcheroo( VAR a, b, c : Byte ); EXTERNAL;%@NL@%
  7322. %@NL@%
  7323. %@CR:MQPC5103@%%@4@%Place the %@AB@%{$L}%@AE@% compiler directive at the beginning of your QuickPascal main%@EH@%
  7324. program. The %@AB@%{$L}%@AE@% directive takes a single argument: the base file name of
  7325. an object file. Note that you do not use LINK or any other utility to
  7326. produce a program. Instead, QuickPascal sets up the link by copying the
  7327. object file into the program and changing the file into its own internal
  7328. object-code format. (The disk-based copy of the object file is not affected,
  7329. however.)%@NL@%
  7330. %@NL@%
  7331. %@NL@%
  7332. %@CR:MQPC5200@%%@3@%%@AB@%12.5.2  Segment and Data Conventions%@AE@%%@EH@%%@NL@%
  7333. %@NL@%
  7334. %@CR:MQPC5201@%%@4@%Observe the following conventions when declaring segments and data:%@EH@%%@NL@%
  7335. %@NL@%
  7336. %@CR:MQPC5202@%  ■  Place all executable statements in a segment named CODE or CSEG. Place%@NL@%
  7337.      all data declarations in a segment named DATA or DSEG. All other%@NL@%
  7338.      segments are ignored, as are group statements.%@NL@%
  7339. %@NL@%
  7340.   ■  The segments can have the %@AB@%BYTE%@AE@% or %@AB@%WORD%@AE@% align type, but QuickPascal will%@NL@%
  7341.      always give segments word alignment.%@NL@%
  7342. %@NL@%
  7343.   ■  Do not specify class names.%@NL@%
  7344. %@NL@%
  7345.   ■  Declare %@AB@%PUBLIC%@AE@% each procedure that you want to call from QuickPascal.%@NL@%
  7346.      However, QuickPascal ignores any %@AB@%PUBLIC%@AE@% data declarations.%@NL@%
  7347. %@NL@%
  7348.   ■  Do not initialize variables in the %@AB@%DATA%@AE@% segment. (Variables must be%@NL@%
  7349.      initialized with instructions.)%@NL@%
  7350. %@NL@%
  7351.   ■  You can access data declared by the main program (or declared in an%@NL@%
  7352.      %@AB@%INTERFACE%@AE@% statement) by declaring it with the %@AB@%EXTRN%@AE@% directive. However,%@NL@%
  7353.      you cannot use the %@AB@%HIGH%@AE@% or %@AB@%LOW%@AE@% operators with external data. See%@NL@%
  7354.      Section 12.4%@BO:   5721f@%, "Internal Data Formats," for information on how to%@NL@%
  7355.      evaluate each data type.%@NL@%
  7356. %@NL@%
  7357. %@NL@%
  7358. %@CR:MQPC5300@%%@3@%%@AB@%12.5.3  Entering the Procedure%@AE@%%@EH@%%@NL@%
  7359. %@NL@%
  7360. %@CR:MQPC5301@%%@4@%The entry sequence for QuickPascal procedures is the same as that for other%@EH@%
  7361. Microsoft languages. The first two instructions set up the BP register as
  7362. the "framepointer," which points to the stack area of the current procedure.
  7363. All parameters and local variables are available through BP:%@NL@%
  7364. %@NL@%
  7365. %@AS@%     push     bp%@NL@%
  7366. %@AS@%     mov      bp, sp%@NL@%
  7367. %@AS@%     sub      sp, local_size%@NL@%
  7368. %@NL@%
  7369. %@CR:MQPC5302@%%@4@%In the code above, %@AS@%local_size%@AE@% is a placeholder for the total size of local%@EH@%
  7370. parameters you wish to use. This last step is entirely optional. Your
  7371. procedure may be able to use registers to hold all temporary values. If not,
  7372. you can use locations on the stack to hold data. (Specifically, these
  7373. locations are below the address pointed to by BP, but no more than
  7374. %@AS@%local_size%@AE@% bytes below this address.)%@NL@%
  7375. %@NL@%
  7376. %@CR:MQPC5303@%%@4@%Procedures called by QuickPascal must preserve the values of the BP, SP, SS,%@EH@%
  7377. and DS registers. BP and SP are preserved by the standard entry and exit
  7378. code. If you need to alter DS or SS, you must push their values onto the
  7379. stack and pop them just before returning as shown below:%@NL@%
  7380. %@NL@%
  7381. %@AS@%     push     bp%@NL@%
  7382. %@AS@%     mov      bp, sp%@NL@%
  7383. %@AS@%     sub      sp, local_size%@NL@%
  7384. %@AS@%     push     ds%@NL@%
  7385. %@NL@%
  7386. %@NL@%
  7387. %@CR:MQPC5400@%%@3@%%@AB@%12.5.4  Accessing Parameters%@AE@%%@EH@%%@NL@%
  7388. %@NL@%
  7389. %@CR:MQPC5401@%%@4@%All parameters and local variables are accessed as indirect memory operands%@EH@%
  7390. using the BP register. To determine the location of each parameter, you need
  7391. to understand the QuickPascal calling conventions. This section summarizes
  7392. those conventions and gives some examples with specific procedures.%@NL@%
  7393. %@NL@%
  7394. %@CR:MQPC5402@%%@4@%QuickPascal pushes each parameter onto the stack──in the order that the%@EH@%
  7395. parameters appear in the source code──before making the actual call.
  7396. Consequently, the first parameter is highest in memory. (Recall that the
  7397. stack grows downward.) You can pass parameters by value or by reference. In
  7398. Pascal, %@AB@%VAR%@AE@% parameters are passed by reference; other parameters are passed
  7399. by value.%@NL@%
  7400. %@NL@%
  7401. %@CR:MQPC5403@%%@4@%When a parameter is passed by reference, QuickPascal pushes a four-byte%@EH@%
  7402. pointer to the data. The offset portion of the pointer is always pushed
  7403. first and is therefore higher in memory.%@NL@%
  7404. %@NL@%
  7405. %@CR:MQPC5404@%%@4@%When a parameter is passed by value, Pascal takes different actions%@EH@%
  7406. depending on the data type:%@NL@%
  7407. %@NL@%
  7408. %@CR:MQPC5405@%  ■  If the value parameter is %@AB@%Char%@AE@%, %@AB@%Boolean%@AE@%, any Pointer, any integer, or%@NL@%
  7409.      any floating-point type, QuickPascal pushes the parameter onto the%@NL@%
  7410.      stack.%@NL@%
  7411. %@NL@%
  7412.   ■  If the parameter is a string or set type, QuickPascal passes a pointer%@NL@%
  7413.      to the data. This action is really the same as passing by reference. If%@NL@%
  7414.      you want to avoid any possibility of altering the data, make a%@NL@%
  7415.      temporary copy of the data, then work with the temporary copy.%@NL@%
  7416.      (QuickPascal procedures use this technique.)%@NL@%
  7417. %@NL@%
  7418.   ■  If the parameter is an array or record type, QuickPascal pushes the%@NL@%
  7419.      variable directly onto the stack if it is no more than four bytes long.%@NL@%
  7420.      Otherwise, it pushes a pointer to the data.%@NL@%
  7421. %@NL@%
  7422. %@CR:MQPC5406@%%@4@%This calling convention for value parameters is not shared by other%@EH@%
  7423. Microsoft high-level languages, which always push a value parameter directly
  7424. onto the stack.%@NL@%
  7425. %@NL@%
  7426. %@CR:MQPC5407@%%@4@%Note that the %@AB@%PUSH%@AE@% instruction can push only one word of data at a time.%@EH@%
  7427. QuickPascal always pushes the most-significant portion first, consistent
  7428. with the 8086-processor convention that the most-significant portion is
  7429. stored highest in memory.%@NL@%
  7430. %@NL@%
  7431. %@CR:MQPC5408@%%@4@%As noted in the next section, the QuickPascal code sometimes places an extra%@EH@%
  7432. parameter on the stack for functions. (This extra parameter is a pointer to
  7433. the location of the return value.)%@NL@%
  7434. %@NL@%
  7435. %@CR:MQPC5409@%%@4@%Finally, the QuickPascal code calls the procedure with a %@AB@%CALL%@AE@% instruction.%@EH@%
  7436. Calls to external procedures are always far, so you should declare your
  7437. assembly procedure with the %@AB@%FAR%@AE@% keyword.%@NL@%
  7438. %@NL@%
  7439. %@CR:MQPC540A@%%@4@%As an example, consider the following procedure call:%@EH@%%@NL@%
  7440. %@NL@%
  7441. %@AS@%     PROCEDURE quad( VAR x : Real; a, b, c : Integer ); EXTERNAL;%@NL@%
  7442. %@AS@%     .%@NL@%
  7443. %@AS@%     .%@NL@%
  7444. %@AS@%     .%@NL@%
  7445. %@AS@%     quad( result, 2, 3, 4 );%@NL@%
  7446. %@NL@%
  7447. %@CR:MQPC540B@%%@4@%QuickPascal implements the call by placing the following items on the stack,%@EH@%
  7448. and in this order:%@NL@%
  7449. %@NL@%
  7450. %@CR:MQPC540C@%  1. The segment address of result%@NL@%
  7451. %@NL@%
  7452.   2. The offset address of result%@NL@%
  7453. %@NL@%
  7454.   3. The value 2 (as a word)%@NL@%
  7455. %@NL@%
  7456.   4. The value 3%@NL@%
  7457. %@NL@%
  7458.   5. The value 4%@NL@%
  7459. %@NL@%
  7460.   6. The segment of the return address (the address to return to when done)%@NL@%
  7461. %@NL@%
  7462.   7. The offset of the return address%@NL@%
  7463. %@NL@%
  7464. %@CR:MQPC540D@%%@4@%A far %@AB@%CALL%@AE@% instruction places the last item, the return address, on the%@EH@%
  7465. stack. After you perform the entry sequence, the BP register points to the
  7466. location just below the return address. Each parameter can then be accessed
  7467. with the following equates:%@NL@%
  7468. %@NL@%
  7469. %@AS@%     result  EQU     <[BP + 12]>%@NL@%
  7470. %@AS@%     a       EQU     <[BP + 10]>%@NL@%
  7471. %@AS@%     b       EQU     <[BP +  8]>%@NL@%
  7472. %@AS@%     c       EQU     <[BP +  6]>%@NL@%
  7473. %@NL@%
  7474. %@CR:MQPC540E@%%@4@%As another example, consider the procedure call%@EH@%%@NL@%
  7475. %@NL@%
  7476. %@AS@%     PROCEDURE repeat_it( num : LongInt;%@NL@%
  7477. %@AS@%                          stuff : STRING ); EXTERNAL;%@NL@%
  7478. %@AS@%     .%@NL@%
  7479. %@AS@%     .%@NL@%
  7480. %@AS@%     .%@NL@%
  7481. %@AS@%     repeat_it( n, 'This is a message.' );%@NL@%
  7482. %@NL@%
  7483. %@CR:MQPC540F@%%@4@%With this procedure, QuickPascal implements the call by placing the%@EH@%
  7484. following items on the stack:%@NL@%
  7485. %@NL@%
  7486. %@CR:MQPC540G@%  1. The most-significant word of the long integer %@AS@%n%@AE@%%@NL@%
  7487. %@NL@%
  7488.   2. The least-significant word of %@AS@%n%@AE@%%@NL@%
  7489. %@NL@%
  7490.   3. The segment address of the string data%@NL@%
  7491. %@NL@%
  7492.   4. The offset address of the string data%@NL@%
  7493. %@NL@%
  7494.   5. The segment of the return address%@NL@%
  7495. %@NL@%
  7496.   6. The offset of the return address%@NL@%
  7497. %@NL@%
  7498. %@CR:MQPC540H@%%@4@%A far %@AB@%CALL%@AE@% instruction places the last two items on the stack. After%@EH@%
  7499. writing the entry sequence, you can access the parameters with the following
  7500. equates:%@NL@%
  7501. %@NL@%
  7502. %@AS@%     num     EQU     <[BP + 10]>%@NL@%
  7503. %@AS@%     stuff   EQU     <[BP +  6]>%@NL@%
  7504. %@NL@%
  7505. %@NL@%
  7506. %@CR:MQPC5500@%%@3@%%@AB@%12.5.5  Returning a Value%@AE@%%@EH@%%@NL@%
  7507. %@NL@%
  7508. %@CR:MQPC5501@%%@4@%This section affects functions only. From the standpoint of assembly code,%@EH@%
  7509. functions are just procedures that have a return value. To return a value to
  7510. Quick-Pascal code, follow these conventions:%@NL@%
  7511. %@NL@%
  7512. %@CR:MQPC5502@%  ■  For a six-byte %@AB@%Real%@AE@% type, place the result in DX:BX:AX, in which DX%@NL@%
  7513.      holds the most-significant word and AX the least.%@NL@%
  7514. %@NL@%
  7515.   ■  For a string, %@AB@%CSTRING%@AE@%, %@AB@%Comp%@AE@%, or floating-point type other than %@AB@%Real%@AE@%,%@NL@%
  7516.      QuickPascal passes an additional parameter. This parameter is pushed%@NL@%
  7517.      first and is a pointer to a temporary storage location. Place the%@NL@%
  7518.      result of the function in this location.%@NL@%
  7519. %@NL@%
  7520.   ■  For ordinal types (including %@AB@%Char%@AE@%, %@AB@%Boolean%@AE@%, and any integer), place the%@NL@%
  7521.      result in AL if one byte, AX if two bytes, and DX:AX if a double word%@NL@%
  7522.      (in which DX holds the most-significant byte).%@NL@%
  7523. %@NL@%
  7524.   ■  QuickPascal does not support functions that return array or record%@NL@%
  7525.      types. (However, you can set the value of an array or record if%@NL@%
  7526.      QuickPascal passes it as a %@AB@%VAR%@AE@% parameter.)%@NL@%
  7527. %@NL@%
  7528. %@NL@%
  7529. %@CR:MQPC5600@%%@3@%%@AB@%12.5.6  Exiting the Procedure%@AE@%%@EH@%%@NL@%
  7530. %@NL@%
  7531. %@CR:MQPC5601@%%@4@%To exit the procedure, first pop any registers you preserved on the stack.%@EH@%
  7532. Then write the following instructions:%@NL@%
  7533. %@NL@%
  7534. %@AS@%     mov  sp,bp%@NL@%
  7535. %@AS@%     pop  bp%@NL@%
  7536. %@AS@%     ret  param_size%@NL@%
  7537. %@NL@%
  7538. %@CR:MQPC5602@%%@4@%In the code given above, %@AS@%param_size%@AE@% is a placeholder for the total size of%@EH@%
  7539. parameters in your procedure. This last instruction is necessary to
  7540. completely restore the stack.%@NL@%
  7541. %@NL@%
  7542. %@NL@%
  7543. %@CR:MQPC5700@%%@3@%%@AB@%12.5.7  A Complete Example%@AE@%%@EH@%%@NL@%
  7544. %@NL@%
  7545. %@CR:MQPC5701@%%@4@%The following example of linking QuickPascal programs to modules written in%@EH@%
  7546. assembly language is simple, but complete. The Pascal source code contains
  7547. the following statements:%@NL@%
  7548. %@NL@%
  7549. %@AS@%     {$L SWITCH }%@NL@%
  7550. %@AS@%     PROCEDURE switch( VAR a, b : Word ); EXTERNAL;%@NL@%
  7551. %@AS@%     .%@NL@%
  7552. %@AS@%     .%@NL@%
  7553. %@AS@%     .%@NL@%
  7554. %@AS@%     switch( x, y );%@NL@%
  7555. %@NL@%
  7556. %@CR:MQPC5702@%%@4@%Since the parameters are %@AB@%VAR%@AE@% parameters, QuickPascal passes pointers to the%@EH@%
  7557. parameters. Then, the assembly code must use indirect register operands to
  7558. access the data. The following procedure exchanges the values of the two
  7559. variables.%@NL@%
  7560. %@NL@%
  7561.      %@AI@%; SWITCH.ASM%@AE@%%@NL@%
  7562.      %@AI@%;%@AE@%%@NL@%
  7563. %@AS@%     CODE    SEGMENT WORD PUBLIC%@NL@%
  7564. %@NL@%
  7565. %@AS@%             ASSUME  CS:CODE%@NL@%
  7566. %@NL@%
  7567. %@AS@%             PUBLIC  switch%@AE@%       %@AI@%; Make procedure public%@AE@%%@NL@%
  7568. %@NL@%
  7569. %@AS@%     a       EQU    <[BP + 10]>%@AE@%    %@AI@%; Parameters for switch%@AE@%%@NL@%
  7570. %@AS@%     b       EQU    <[BP + 6]>  %@AE@%   %@AI@%;  procedure%@AE@%%@NL@%
  7571. %@NL@%
  7572. %@AS@%     switch  PROC    FAR%@NL@%
  7573. %@AS@%             push    bp         %@AE@%  %@AI@%; Entry sequence%@AE@%%@NL@%
  7574. %@AS@%             mov     bp,sp%@NL@%
  7575. %@AS@%             push    ds%@NL@%
  7576. %@NL@%
  7577. %@AS@%             lds     si, a      %@AE@%  %@AI@%; Load ptr into ds:si%@AE@%%@NL@%
  7578. %@AS@%             les     di, b      %@AE@%  %@AI@%; Load ptr into es:di%@AE@%%@NL@%
  7579. %@AS@%             mov     bx, es:[di]%@AE@%  %@AI@%; temp = b%@AE@%%@NL@%
  7580. %@AS@%             xchg    bx, [si]   %@AE@%  %@AI@%; Switch temp and a%@AE@%%@NL@%
  7581. %@AS@%             xchg    bx, es:[di]%@AE@%  %@AI@%; Switch temp and b%@AE@%%@NL@%
  7582. %@NL@%
  7583. %@AS@%             pop     ds%@NL@%
  7584. %@AS@%             mov     sp,bp      %@AE@%  %@AI@%; Exit sequence%@AE@%%@NL@%
  7585. %@AS@%             pop     bp%@NL@%
  7586. %@AS@%             ret     8          %@AE@%  %@AI@%; Total of 8 bytes in%@AE@%%@NL@%
  7587.                                   %@AI@%;  parameters%@AE@%%@NL@%
  7588. %@AS@%     switch  ENDP%@NL@%
  7589. %@NL@%
  7590. %@NL@%
  7591. ───────────────────────────────────────────────────────────────────────────%@NL@%
  7592. %@CR:MQPP3000@%%@1@%%@AB@%Part 3  Graphics and Objects%@AE@%%@EH@%%@NL@%
  7593. %@NL@%
  7594. %@CR:MQPP3003@%%@4@%Part 3 of %@AI@%Pascal by Example%@AE@% covers QuickPascal support of graphics, fonts,%@EH@%
  7595. and object-oriented programming. Each of these topics requires a moderate
  7596. degree of experience with Pascal. You need to be comfortable with all of the
  7597. topics in Part 1 and may find familiarity with Part 2 helpful.%@NL@%
  7598. %@NL@%
  7599. %@CR:MQPP3004@%%@4@%The graphics and fonts chapters show you how to use the QuickPascal graphics%@EH@%
  7600. unit to create colorful and informative screen displays. The chapter on
  7601. object-oriented programming introduces the fundamental concepts of
  7602. programming with objects and how to implement those concepts in QuickPascal.%@NL@%
  7603. %@NL@%
  7604. %@NL@%
  7605. %@CR:MQPD0000@%%@1@%%@AB@%Chapter 13  Using Graphics%@AE@%%@EH@%%@NL@%
  7606. ───────────────────────────────────────────────────────────────────────────%@NL@%
  7607. %@NL@%
  7608. %@CR:MQPD0001@%%@4@%This chapter explains how to call graphics routines that set points, draw%@EH@%
  7609. lines, change colors, and draw shapes such as rectangles and circles. The
  7610. first section describes the general structure of any graphics program,
  7611. defines important graphics terms, and works through an example program step
  7612. by step, showing how to use the basic routines. Subsequent sections explain
  7613. video modes, coordinate systems, and animation.%@NL@%
  7614. %@NL@%
  7615. %@CR:MQPD0002@%%@4@%To run any graphics programs, your computer must have graphics capability.%@EH@%
  7616. The QuickPascal graphics facility supports the Color Graphics Adapter (CGA),
  7617. the Enhanced Graphics Adapter (EGA), and the Video Graphics Adapter (VGA)
  7618. video modes available on IBM(R) and IBM-compatible computers. The graphics
  7619. facility also supports the Olivetti(R) (and AT&T(R)) enhanced video modes
  7620. and the Hercules(R) monochrome graphics mode.%@NL@%
  7621. %@NL@%
  7622. %@CR:MQPD0003@%%@4@%This chapter discusses the techniques for writing graphics programs but does%@EH@%
  7623. not cover every graphics procedure and function (there are more than 75).
  7624. You can explore additional topics by using the QP Advisor and the example
  7625. programs. Be sure to check the README.DOC file for any last-minute changes
  7626. or additions.%@NL@%
  7627. %@NL@%
  7628. %@NL@%
  7629. %@CR:MQPD1000@%%@2@%%@AB@%13.1  Getting Started with Graphics%@AE@%%@EH@%%@NL@%
  7630. %@NL@%
  7631. %@CR:MQPD1001@%%@4@%The subject of graphics and color display on computers is fairly complex.%@EH@%
  7632. This chapter and the next one, "Using Fonts," provide an introduction to
  7633. graphics and fonts. The next sections cover common graphics terms and list
  7634. sources for more information on graphics.%@NL@%
  7635. %@NL@%
  7636. %@NL@%
  7637. %@CR:MQPD1100@%%@3@%%@AB@%13.1.1  Graphics Terms%@AE@%%@EH@%%@NL@%
  7638. %@NL@%
  7639. %@CR:MQPD1101@%%@4@%There are several concepts you need to know before you can create graphics%@EH@%
  7640. programs. The following list explains the most useful terms:%@NL@%
  7641. %@NL@%
  7642. %@CR:MQPD1102@%  ■  The "%@AI@%x%@AE@% axis" determines the horizontal position on the screen. The%@NL@%
  7643.      "origin" (point 0, 0) is in the upper left corner. The maximum number%@NL@%
  7644.      of horizontal "pixels" (picture elements) varies from 320 to 640 to%@NL@%
  7645.      720, depending on the graphics card installed and the graphics mode in%@NL@%
  7646.      effect.%@NL@%
  7647. %@NL@%
  7648.   ■  The "%@AI@%y%@AE@% axis" is the vertical position on the screen. The origin is the%@NL@%
  7649.      upper left corner. The number of vertical pixels ranges from 200 to%@NL@%
  7650.      480.%@NL@%
  7651. %@NL@%
  7652.   ■  Each graphics mode offers a "palette" from which you may choose the%@NL@%
  7653.      colors to be displayed. You may have access to 2, 4, 8, 16, or 256%@NL@%
  7654.      "color indexes," depending on the graphics card in the computer and the%@NL@%
  7655.      graphics mode in effect. The color is the index to the palette of%@NL@%
  7656.      colors displayable by a particular graphics adapter.%@NL@%
  7657. %@NL@%
  7658.   ■  The CGA modes offer four fixed palettes containing predefined colors%@NL@%
  7659.      that may not be changed. In EGA, MCGA, and VGA graphics modes, you may%@NL@%
  7660.      change any of the color indexes by providing a color value that%@NL@%
  7661.      describes the mix of colors you wish to use.%@NL@%
  7662. %@NL@%
  7663.   ■  A color index is always a short integer. A color value is always a long%@NL@%
  7664.      integer. When you're calling graphics functions that require%@NL@%
  7665.      color-related parameters, you should be aware of the difference between%@NL@%
  7666.      color indexes and color values.%@NL@%
  7667. %@NL@%
  7668. %@NL@%
  7669. %@CR:MQPD1200@%%@3@%%@AB@%13.1.2  For More Information%@AE@%%@EH@%%@NL@%
  7670. %@NL@%
  7671. %@CR:MQPD1201@%%@4@%The following books cover a variety of graphics topics that you may find%@EH@%
  7672. useful. They are listed only for your convenience. With the exception of its
  7673. own publications, Microsoft does not endorse these books or recommend them
  7674. over others on the same subject.%@NL@%
  7675. %@NL@%
  7676. %@CR:MQPD1202@%  ■  Artwick, Bruce. %@AI@%Microcomputer Displays, Graphics and Animation%@AE@%.%@NL@%
  7677.      Englewood Cliffs, NJ: Prentice-Hall, Inc., 1985.%@NL@%
  7678. %@NL@%
  7679.           Discussion of microcomputer graphics and animation from the%@NL@%
  7680.           creator of %@AI@%Microsoft Flight Simulator%@AE@%.%@NL@%
  7681. %@NL@%
  7682.   ■  Kliewer, Bradley D. %@AI@%EGA/VGA: A Programmer's Reference%@AE@% %@AI@%Guide%@AE@%. New York,%@NL@%
  7683.      NY: Intertext Publications, Inc., 1988.%@NL@%
  7684. %@NL@%
  7685.           A detailed discussion of the EGA and VGA video modes.%@NL@%
  7686. %@NL@%
  7687.   ■  Norton, Peter, and Richard Wilton. %@AI@%The New Peter Norton%@AE@% %@AI@%Programmer's%@AE@%%@NL@%
  7688.      %@AI@%Guide to the IBM PC and PS/2%@AE@%. Redmond, WA: Microsoft Press, 1985.%@NL@%
  7689. %@NL@%
  7690.           The standard guide to the inside of the IBM PC and PS/2 families%@NL@%
  7691.           of computers. Several chapters are devoted to video modes.%@NL@%
  7692. %@NL@%
  7693.   ■  Wilton, Richard. %@AI@%Programmer's Guide to PC and PS/2%@AE@% %@AI@%Video Systems%@AE@%.%@NL@%
  7694.      Redmond, WA: Microsoft Press, 1987.%@NL@%
  7695. %@NL@%
  7696.           An advanced guide to all the PC and PS/2 video modes.%@NL@%
  7697. %@NL@%
  7698. %@NL@%
  7699. %@CR:MQPD2000@%%@2@%%@AB@%13.2  Writing Your First Graphics Program%@AE@%%@EH@%%@NL@%
  7700. %@NL@%
  7701. %@CR:MQPD2001@%%@4@%In QuickPascal, all graphics programs must follow these six basic steps:%@EH@%%@NL@%
  7702. %@NL@%
  7703. %@CR:MQPD2002@%  1. Use the %@AB@%MSGraph%@AE@% unit.%@NL@%
  7704. %@NL@%
  7705.   2. Set a video mode.%@NL@%
  7706. %@NL@%
  7707.   3. Determine the video parameters.%@NL@%
  7708. %@NL@%
  7709.   4. Set up a coordinate system.%@NL@%
  7710. %@NL@%
  7711.   5. Create and display graphics.%@NL@%
  7712. %@NL@%
  7713.   6. Restore initial video configuration and exit the program.%@NL@%
  7714. %@NL@%
  7715. %@CR:MQPD2003@%%@4@%A simple graphics program, 1STGRAPH.PAS, is shown below. In the next few%@EH@%
  7716. pages, this program will be dissected into the six required elements of a
  7717. graphics program.%@NL@%
  7718. %@NL@%
  7719. %@AS@%     PROGRAM FirstGraphics;%@NL@%
  7720. %@AS@%     { 1STGRAPH.PAS: Demonstrates basic graphics program structure }%@NL@%
  7721. %@NL@%
  7722. %@AS@%     USES%@NL@%
  7723. %@AS@%         MSGraph;%@NL@%
  7724. %@NL@%
  7725. %@AS@%     VAR%@NL@%
  7726. %@AS@%         a, i : integer;%@NL@%
  7727. %@AS@%         vc   : _VideoConfig;%@NL@%
  7728. %@NL@%
  7729. %@AS@%     BEGIN  { Begin main program. }%@NL@%
  7730. %@NL@%
  7731. %@AS@%         _ClearScreen( _GClearScreen);%@NL@%
  7732. %@NL@%
  7733. %@AS@%     { Set the highest resolution video mode and check for success }%@NL@%
  7734. %@AS@%         a := _SetVideoMode( _MaxResMode );%@NL@%
  7735. %@NL@%
  7736. %@AS@%     IF ( a = 0 ) THEN%@NL@%
  7737. %@AS@%             BEGIN%@NL@%
  7738. %@AS@%               Writeln( 'No valid graphics mode; hit RETURN to continue' );%@NL@%
  7739. %@AS@%               Readln;%@NL@%
  7740. %@AS@%               a := _SetVideoMode( _DefaultMode );%@NL@%
  7741. %@AS@%               Halt ( 0 );%@NL@%
  7742. %@AS@%             END;%@NL@%
  7743. %@NL@%
  7744. %@AS@%         { Find out some screen characteristics. }%@NL@%
  7745. %@AS@%         _GetVideoConfig( vc );%@NL@%
  7746. %@AS@%         Writeln( 'mode: ',vc.Mode );%@NL@%
  7747. %@AS@%         Writeln( 'Horizontal resolution: ', vc.NumXPixels );%@NL@%
  7748. %@AS@%         Writeln( 'Vertical resolution: ', vc.NumYPixels );%@NL@%
  7749. %@AS@%         Writeln( 'Number of colors: ', vc.NumColors );%@NL@%
  7750. %@NL@%
  7751. %@AS@%         { Draw a colored rectangle and ellipse in lower left quadrant. }%@NL@%
  7752. %@AS@%         _SetColor( 4 );%@NL@%
  7753. %@AS@%         _Rectangle( _GBorder, 0, vc.NumYPixels - 1,%@NL@%
  7754. %@AS@%                     vc.NumXPixels DIV 4,%@NL@%
  7755. %@AS@%                     vc.NumYPixels * 3 DIV 4 );%@NL@%
  7756. %@AS@%         _Ellipse( _GBorder, 0, vc.NumYPixels - 1,%@NL@%
  7757. %@AS@%                   vc.NumXPixels DIV 4,%@NL@%
  7758. %@AS@%                   vc.NumYPixels * 3 DIV 4 );%@NL@%
  7759. %@NL@%
  7760. %@AS@%   { Draw a line from the corner of the rectangle to the screen center. }%@NL@%
  7761. %@AS@%         _SetColor( 3 );%@NL@%
  7762. %@AS@%         _MoveTo( vc.NumXPixels DIV 4, vc.NumYPixels * DIV 4 );%@NL@%
  7763. %@AS@%         _LineTo( vc.NumXPixels DIV 2, vc.NumYPixels DIV 2 );%@NL@%
  7764. %@NL@%
  7765. %@AS@%         { Wait for RETURN key and then restore video mode. }%@NL@%
  7766. %@AS@%         Readln;%@NL@%
  7767. %@AS@%         _SetVideoMode(_DefaultMode);%@NL@%
  7768. %@AS@%     END.%@NL@%
  7769. %@NL@%
  7770. %@CR:MQPD2010@%%@4@%%@AB@%Using the MSGraph Unit%@AE@%%@EH@%%@NL@%
  7771. %@NL@%
  7772. %@CR:MQPD2011@%%@4@%The first step in creating 1STGRAPH.PAS is to use the %@AB@%MSGraph%@AE@% unit within%@EH@%
  7773. your QuickPascal program. The %@AB@%MSGraph%@AE@% unit contains the constants, data
  7774. types, procedures, and functions used in graphics programs. QuickPascal
  7775. units are explained in Chapter 7%@BO:   31ac9@%, "Units." The %@AB@%MSGraph%@AE@% unit is the library
  7776. of graphics features you need to access from your program.%@NL@%
  7777. %@NL@%
  7778. %@CR:MQPD2012@%%@4@%The %@AB@%USES%@AE@% section of your program calls %@AB@%MSGraph%@AE@%. This section appears%@EH@%
  7779. immediately after the %@AB@%PROGRAM%@AE@% declaration line and looks like this:%@NL@%
  7780. %@NL@%
  7781. %@AS@%     USES%@NL@%
  7782. %@AS@%         MSGraph;%@NL@%
  7783. %@NL@%
  7784. %@CR:MQPD2013@%%@4@%Note that some components of the %@AB@%MSGraph%@AE@% unit are incompatible with some%@EH@%
  7785. functions within the %@AB@%Crt%@AE@% unit. Some of the %@AB@%Crt%@AE@% unit routines that deal with
  7786. the display (such as %@AB@%HighVideo%@AE@% or %@AB@%DirectVideo%@AE@%) conflict with the graphics
  7787. functions.%@NL@%
  7788. %@NL@%
  7789. %@CR:MQPD2014@%%@4@%The following %@AB@%Crt%@AE@% routines are safe to use with the %@AB@%MSGraph%@AE@% unit:%@EH@%%@NL@%
  7790. %@NL@%
  7791.      %@AB@%AssignCRT       NoSound     WhereY%@AE@%%@NL@%
  7792.      %@AB@%Delay           ReadKey     Window%@AE@%%@NL@%
  7793.      %@AB@%GotoXY          Sound%@AE@%%@NL@%
  7794.      %@AB@%KeyPressed      WhereX%@AE@%%@NL@%
  7795. %@NL@%
  7796. %@CR:MQPD2020@%%@4@%%@AB@%Setting the Video Mode%@AE@%%@EH@%%@NL@%
  7797. %@NL@%
  7798. %@CR:MQPD2021@%%@4@%Before you can start drawing pictures on the screen, your program must tell%@EH@%
  7799. the graphics adapter to switch from text mode to graphics mode. Call
  7800. %@AB@%_SetVideoMode%@AE@%, passing it a predefined constant that tells it which mode to
  7801. display. The constants listed in Table 13.1%@BO:   60246@% are defined in the %@AB@%MSGraph%@AE@%
  7802. unit. The dimensions are listed in columns for video text modes and in
  7803. pixels for graphics mode.%@NL@%
  7804. %@NL@%
  7805. %@CR:MQPDT100@%%@4@%%@AB@%Table 13.1  Constants Set by _SetVideoMode%@AE@%%@EH@%%@NL@%
  7806. %@NL@%
  7807. %@AB@%Constant                Video Mode                        Mode Type/Hardware%@AE@%%@NL@%
  7808. %@NL@%
  7809. %@AB@%_DefaultMode%@AE@%            Restores to original mode         Both/All%@NL@%
  7810. %@AB@%_MaxResMode%@AE@%             Highest resolution                Graphics/All%@NL@%
  7811. %@AB@%_MaxColorMode%@AE@%           Maximum colors                    Graphics/All%@NL@%
  7812. %@AB@%_TextBW40%@AE@%               40 column text, 16 gray           Text/CGA%@NL@%
  7813. %@AB@%_TextC40%@AE@%                40 column text, 16/8 color        Text/CGA%@NL@%
  7814. %@AB@%_TextBW80%@AE@%               80 column text, 16 gray           Text/CGA%@NL@%
  7815. %@AB@%_TextC80%@AE@%                80 column text, 16/8 color        Text/CGA%@NL@%
  7816. %@AB@%_MRes4Color%@AE@%             320 X 200, 4 color                Graphics/CGA%@NL@%
  7817. %@AB@%_MResNoColor%@AE@%            320 X 200, 4 gray                 Graphics/CGA%@NL@%
  7818. %@AB@%_HResBW%@AE@%                 640 X 200, BW                     Graphics/CGA%@NL@%
  7819. %@AB@%_TextMono%@AE@%               80 column text, BW                Text/MDPA%@NL@%
  7820. %@AB@%_HercMono%@AE@%               720 X 348, BW for HGC             Graphics/HGC%@NL@%
  7821. %@AB@%_MRes16Color%@AE@%            320 X 200, 16 color               Graphics/EGA%@NL@%
  7822. %@AB@%_HRes16Color%@AE@%            640 X 200, 16 color               Graphics/EGA%@NL@%
  7823. %@AB@%_EResNoColor%@AE@%            640 X 350, BW                     Graphics/EGA%@NL@%
  7824. %@AB@%_EResColor%@AE@%              640 X 350, 4 or 16 color          Graphics/EGA%@NL@%
  7825. %@AB@%_VRes2Color%@AE@%             640 X 480, BW                     Graphics/VGA/MCGA%@NL@%
  7826. %@AB@%_VRes16Color%@AE@%            640 X 480, 16 color               Graphics/VGA%@NL@%
  7827. %@AB@%_MRes256Color%@AE@%           320 X 200, 256 color              Graphics/VGA/MCGA%@NL@%
  7828. %@AB@%_OResColor%@AE@%              640 X 400, 1 of 16 colors         Graphics/Olivetti%@NL@%
  7829. %@NL@%
  7830. %@CR:MQPD2022@%%@4@%These video modes are described more fully in Section 13.3%@BO:   63072@%.%@EH@%%@NL@%
  7831. %@NL@%
  7832. %@CR:MQPD2023@%%@4@%The special modes %@AB@%_MaxResMode%@AE@% and %@AB@%_MaxColorMode%@AE@% are used when you simply%@EH@%
  7833. want QuickPascal to determine the highest resolution or maximum color mode
  7834. available.%@NL@%
  7835. %@NL@%
  7836. %@CR:MQPD2024@%%@4@%If the %@AB@%_SetVideoMode%@AE@% function returns a 0, it means the hardware does not%@EH@%
  7837. support the selected mode. You may continue to select alternate video modes
  7838. until a nonzero value is returned. If the hardware configuration doesn't
  7839. support any of the selected video modes, then exit the program.%@NL@%
  7840. %@NL@%
  7841. %@CR:MQPD2025@%%@4@%The segment of example program 1STGRAPH.PAS below sets the video mode for%@EH@%
  7842. maximum resolution and then checks for success. If the function
  7843. %@AB@%_SetVideoMode%@AE@% fails (and returns a 0), the program prints a message,
  7844. restores the video mode, and halts.%@NL@%
  7845. %@NL@%
  7846. %@AS@%     { Set the highest resolution mode and check for success }%@NL@%
  7847. %@AS@%     a := _SetVideoMode( _MaxResMode );%@NL@%
  7848. %@AS@%     IF ( a = 0 ) THEN%@NL@%
  7849. %@AS@%         BEGIN%@NL@%
  7850. %@AS@%         Writeln( 'No valid graphics mode; hit RETURN to continue' );%@NL@%
  7851. %@AS@%         Readln;%@NL@%
  7852. %@AS@%          a := _SetVideoMode( _DefaultMode );%@NL@%
  7853. %@AS@%         Halt (0);%@NL@%
  7854. %@AS@%         END;%@NL@%
  7855. %@NL@%
  7856. %@CR:MQPD2030@%%@4@%%@AB@%Determining the Video Parameters%@AE@%%@EH@%%@NL@%
  7857. %@NL@%
  7858. %@CR:MQPD2031@%%@4@%After entering graphics mode, you can check the current video configuration.%@EH@%
  7859. This is necessary when you have used the constant %@AB@%_MaxResMode%@AE@% or
  7860. %@AB@%_MaxColorMode%@AE@%, since you do not know the specifics of the video mode
  7861. selected.%@NL@%
  7862. %@NL@%
  7863. %@CR:MQPD2032@%%@4@%The video configuration requires a special structure called %@AB@%_VideoConfig%@AE@%,%@EH@%
  7864. which is defined in the %@AB@%MSGraph%@AE@% unit. The %@AB@%_GetVideoConfig%@AE@% procedure finds
  7865. the current video configuration information.%@NL@%
  7866. %@NL@%
  7867. %@CR:MQPD2033@%%@4@%The %@AB@%_VideoConfig%@AE@% structure contains the following elements:%@EH@%%@NL@%
  7868. %@NL@%
  7869. %@AS@%     { Structure for GetVideoConfig }%@NL@%
  7870. %@NL@%
  7871. %@AS@%       _VideoConfig = RECORD%@NL@%
  7872. %@AS@%         NumXPixels : Integer; { Horizontal resolution }%@NL@%
  7873. %@AS@%         NumYPixels : Integer; { Vertical resolution }%@NL@%
  7874. %@AS@%         NumTextCols : Integer; { Number of text columns available }%@NL@%
  7875. %@AS@%         NumTextRows : Integer; { Number of text rows available }%@NL@%
  7876. %@AS@%         NumColors : Integer; { Number of actual colors }%@NL@%
  7877. %@AS@%         BitsPerPixel : Integer; { Number of bits per pixel }%@NL@%
  7878. %@AS@%         NumVideoPages : Integer; { Number of available video pages }%@NL@%
  7879. %@AS@%         Mode : Integer; { Current video mode }%@NL@%
  7880. %@AS@%         Adapter : Integer; { Active display adapter }%@NL@%
  7881. %@AS@%         Monitor : Integer; { Active display monitor }%@NL@%
  7882. %@AS@%         Memory : Integer; { Adapter video memory in K bytes }%@NL@%
  7883. %@AS@%       END;%@NL@%
  7884. %@NL@%
  7885. %@CR:MQPD2034@%%@4@%The variables within the %@AB@%_VideoConfig%@AE@% structure are initialized when you%@EH@%
  7886. call %@AB@%_GetVideoConfig%@AE@%. In the following example program, the video mode is
  7887. set to %@AB@%_MaxResMode%@AE@%. The program then calls %@AB@%_GetVideoConfig%@AE@% to determine the
  7888. screen dimensions (in pixels) and the maximum number of colors allowed.%@NL@%
  7889. %@NL@%
  7890. %@AS@%     { Find out some screen characteristics. }%@NL@%
  7891. %@AS@%     _GetVideoConfig( ,vc );%@NL@%
  7892. %@AS@%     Writeln( 'mode: 'vc.Mode );%@NL@%
  7893. %@AS@%     Writeln( 'Horizontal resolution: ', vc.NumXPixels );%@NL@%
  7894. %@AS@%     Writeln( 'Vertical resolution: ', vc.NumYPixels );%@NL@%
  7895. %@AS@%     Writeln( 'Number of colors: ', vc.NumColors );%@NL@%
  7896. %@NL@%
  7897. %@CR:MQPD2040@%%@4@%%@AB@%Setting Up Coordinate Systems%@AE@%%@EH@%%@NL@%
  7898. %@NL@%
  7899. %@CR:MQPD2041@%%@4@%The third step in writing a QuickPascal graphics program is to establish the%@EH@%
  7900. "coordinate system."%@NL@%
  7901. %@NL@%
  7902. %@CR:MQPD2042@%%@4@%A coordinate system is used to identify a pixel location relative to a%@EH@%
  7903. horizontal and vertical axis. In a graphics mode, each pixel on the screen
  7904. can be located by means of a unique pair of coordinates. The QuickPascal
  7905. graphics unit supports the following coordinate systems:%@NL@%
  7906. %@NL@%
  7907. %@CR:MQPD2043@%  ■  Text coordinates%@NL@%
  7908. %@NL@%
  7909.   ■  Physical coordinates%@NL@%
  7910. %@NL@%
  7911.   ■  Viewport coordinates%@NL@%
  7912. %@NL@%
  7913.   ■  Window coordinates%@NL@%
  7914. %@NL@%
  7915. %@CR:MQPD2044@%%@4@%Since this example graphics program does not specify otherwise, the%@EH@%
  7916. coordinate system used is that provided by the physical screen dimensions.
  7917. This is known as the "physical-coordinate system."%@NL@%
  7918. %@NL@%
  7919. %@CR:MQPD2045@%%@4@%But how much screen is available to work with? There might be 720 X 348, 640%@EH@%
  7920. X 480, 640 X 400, 640 X 350, or 640 X 200 pixels. The %@AB@%_VideoConfig%@AE@% structure
  7921. elements %@AB@%NumXPixels%@AE@% and %@AB@%NumYPixels%@AE@% provide the screen dimensions. On a VGA
  7922. card, a request for maximum resolution would set the screen to the
  7923. %@AB@%_VRes16Color%@AE@% mode. The horizontal resolution is 640 pixels and vertical
  7924. resolution is 480. The horizontal resolution might be 640, but the pixels
  7925. are numbered 0-639.%@NL@%
  7926. %@NL@%
  7927. %@CR:MQPD2046@%%@4@%The physical-coordinate system places the origin (or the coordinate pair%@EH@%
  7928. (0,0)) at the upper left corner of the screen. Increasing positive values of
  7929. the %@AI@%x%@AE@% coordinate extend from left to right. Increasing positive values of
  7930. the %@AI@%y%@AE@% coordinate extend from top to bottom.%@NL@%
  7931. %@NL@%
  7932. %@CR:MQPD2047@%%@4@%The physical-coordinate system is dependent on the hardware and display%@EH@%
  7933. configuration and cannot be changed. The other coordinate systems and the
  7934. procedures used to translate between them are described in Section 13.4%@BO:   6ac8a@%.%@NL@%
  7935. %@NL@%
  7936. %@CR:MQPD2050@%%@4@%%@AB@%Drawing Graphics%@AE@%%@EH@%%@NL@%
  7937. %@NL@%
  7938. %@CR:MQPD2051@%%@4@%The next few lines in this example program draw a rectangle and an ellipse%@EH@%
  7939. and then a line to the center of the screen. Prior to drawing the rectangle
  7940. or the line, the graphics color is set to two different values. The program
  7941. segment that draws the rectangle and ellipse is shown below:%@NL@%
  7942. %@NL@%
  7943. %@AS@%     { Draw a colored rectangle and ellipse in lower left quadrant. }%@NL@%
  7944. %@AS@%     _SetColor( 4 );%@NL@%
  7945. %@AS@%     _Rectangle( _GBorder, 0, vc.NumYPixels - 1,%@NL@%
  7946. %@AS@%                 vc.NumXPixels DIV 4, vc.NumYPixels * 3 DIV 4 );%@NL@%
  7947. %@AS@%     _Ellipse( _GBorder, 0, vc.NumYPixels - 1,%@NL@%
  7948. %@AS@%               vc.NumXPixels DIV 4, vc.NumYPixels * 3 DIV 4 );%@NL@%
  7949. %@NL@%
  7950. %@CR:MQPD2052@%%@4@%The call to the%@AB@%_Rectangle%@AE@% procedure has five arguments. The first argument%@EH@%
  7951. is the "fill flag," which may be either %@AB@%_GBorder%@AE@% or%@AB@%_GFillInterior%@AE@%. The fill
  7952. flag determines whether the figure  will be drawn with just the border or as
  7953. a solid figure. Choose %@AB@%_GBorder%@AE@% if you want a rectangle of four lines (a
  7954. border only, in the current line style). Or you can choose %@AB@%_GFillInterior%@AE@% if
  7955. you want a solid rectangle (filled in with the current color and fill
  7956. pattern).%@NL@%
  7957. %@NL@%
  7958. %@CR:MQPD2053@%%@4@%The second and third arguments are the %@AI@%x%@AE@% and %@AI@%y%@AE@% coordinates of one corner of%@EH@%
  7959. the rectangle. The fourth and fifth arguments are the coordinates of the
  7960. opposite corner. The coordinates for the two corners are defined in terms of
  7961. the measurements obtained from %@AB@%_GetVideoConfig%@AE@%. As a result, this program
  7962. draws the rectangle correctly in any graphics mode.%@NL@%
  7963. %@NL@%
  7964. %@CR:MQPD2054@%%@4@%The %@AB@%_Ellipse%@AE@% procedure draws an ellipse on the screen. Its parameters%@EH@%
  7965. resemble the parameters for %@AB@%_Rectangle%@AE@%. Both procedures require a fill flag
  7966. and two corners of a "bounding rectangle." When the ellipse is drawn, four
  7967. points touch the edges of the bounding rectangle. A bounding rectangle
  7968. defines the space in which a rounded figure is drawn. For a rounded figure,
  7969. the center of the bounding rectangle defines the center of the rounded
  7970. figure. A bounding rectangle is defined by the coordinates of the upper left
  7971. corner and the lower right corner of the rectangle.%@NL@%
  7972. %@NL@%
  7973. %@CR:MQPD2055@%%@4@%When the program first enters a graphics mode or sets a viewport (as%@EH@%
  7974. discussed in Section 13.4%@BO:   6ac8a@%), the drawing position is set to the center of
  7975. the screen. Since the %@AB@%_Rectangle%@AE@% procedure takes the corners of the
  7976. rectangle as parameters, there is no need to set the drawing position. But
  7977. after the figures are drawn, the program moves the current drawing position
  7978. (with the %@AB@%_MoveTo%@AE@% procedure) and draws a line from the new position to the
  7979. center of the screen:%@NL@%
  7980. %@NL@%
  7981. %@AS@%     { Draw a line from the corner of the rectangle to the screen center. }%@NL@%
  7982. %@AS@%     _SetColor( 3 );%@NL@%
  7983. %@AS@%     _MoveTo( vc.NumXPixels DIV 4, vc.NumYPixels * 3 DIV 4 );%@NL@%
  7984. %@AS@%     _LineTo( vc.NumXPixels DIV 2, vc.NumYPixels DIV 2 );%@NL@%
  7985. %@NL@%
  7986. %@CR:MQPD2056@%%@4@%Again, the coordinates are given in terms of %@AB@%NumXPixels%@AE@% and %@AB@%NumYPixels%@AE@% to%@EH@%
  7987. ensure portability across video modes.%@NL@%
  7988. %@NL@%
  7989. %@CR:MQPD2060@%%@4@%%@AB@%Restoring Initial Video Configuration and Exiting%@AE@%%@EH@%%@NL@%
  7990. %@NL@%
  7991. %@CR:MQPD2061@%%@4@%The final step in any graphics program is to restore the default video mode.%@EH@%
  7992. In the sample program, the %@AB@%Readln%@AE@% procedure waits for the RETURN key. The
  7993. %@AB@%_SetVideoMode%@AE@% function restores the screen to the default mode, which sets
  7994. the screen back to normal.%@NL@%
  7995. %@NL@%
  7996. %@AS@%     { Wait for RETURN key and then restore the video mode. }%@NL@%
  7997. %@AS@%     Readln;%@NL@%
  7998. %@AS@%     a := _SetVideoMode(_DefaultMode);%@NL@%
  7999. %@NL@%
  8000. %@NL@%
  8001. %@CR:MQPD3000@%%@2@%%@AB@%13.3  Using Video Modes%@AE@%%@EH@%%@NL@%
  8002. %@NL@%
  8003. %@CR:MQPD3001@%%@4@%The QuickPascal %@AB@%MSGraph%@AE@% unit provides support for the following video%@EH@%
  8004. adapters and displays:%@NL@%
  8005. %@NL@%
  8006. %@CR:MQPD3002@%  ■  Monochrome Display Printer Adapter (MDPA)%@NL@%
  8007.   ■  Hercules-compatible graphics adapters%@NL@%
  8008.   ■  CGA%@NL@%
  8009.   ■  EGA%@NL@%
  8010.   ■  VGA%@NL@%
  8011.   ■  MCGA%@NL@%
  8012.   ■  Olivetti-compatible graphics adapters (including AT&T 6300 series)%@NL@%
  8013. %@NL@%
  8014. %@CR:MQPD3003@%%@4@%The sections that follow explain how to select a video mode, then discuss%@EH@%
  8015. the major CGA, EGA, and VGA graphics modes. A complete listing of the
  8016. QuickPascal video modes that can be set by the %@AB@%_SetVideoMode%@AE@% function is
  8017. shown in Table 13.1%@BO:   60246@%.%@NL@%
  8018. %@NL@%
  8019. ───────────────────────────────────────────────────────────────────────────%@NL@%
  8020. %@AI@%NOTE%@AE@%%@NL@%
  8021.    If you use a Hercules graphics card, you must run the MSHERC.COM program%@NL@%
  8022.    before attempting to display any graphics in %@AB@%_HercMono%@AE@% mode. If your%@NL@%
  8023.    computer also has a color graphics card, you must run MSHERC.COM with the%@NL@%
  8024.    /H (/HALF) option to set the Hercules graphics card in HALF mode.%@NL@%
  8025.    Otherwise, the results will be unpredictable.%@NL@%
  8026. ───────────────────────────────────────────────────────────────────────────%@NL@%
  8027. %@NL@%
  8028. %@CR:MQPD3004@%%@4@%The %@AB@%_VideoConfig%@AE@% structure, which is returned by %@AB@%_GetVideoConfig%@AE@%, includes%@EH@%
  8029. fields that denote the type of graphics adapter and monitor in use. Table
  8030. 13.2%@BO:   636da@% lists the constants for graphics adapters.%@NL@%
  8031. %@NL@%
  8032. %@CR:MQPDT200@%%@4@%%@AB@%Table  13.2  Constants for Graphics Adapters%@AE@%%@EH@%%@NL@%
  8033. %@NL@%
  8034. %@AB@%Constant      Value       Description%@AE@%%@NL@%
  8035. %@NL@%
  8036. %@AB@%_MDPA%@AE@%         0x0001      Monochrome Display Adapter%@NL@%
  8037. %@AB@%_CGA%@AE@%          0x0002      Color Graphics Adapter%@NL@%
  8038. %@AB@%_EGA%@AE@%          0x0004      Enhanced Graphics Adapter%@NL@%
  8039. %@AB@%_VGA%@AE@%          0x0008      Video Graphics Array%@NL@%
  8040. %@AB@%_MCGA%@AE@%         0x0010      MultiColor Graphics Array%@NL@%
  8041. %@AB@%_HGC%@AE@%          0x0020      Hercules Graphics Card%@NL@%
  8042. %@AB@%_OCGA%@AE@%         0x0042      Olivetti Color Graphics Adapter%@NL@%
  8043. %@AB@%_OEGA%@AE@%         0x0044      Olivetti Enhanced Graphics Adapter%@NL@%
  8044. %@AB@%_OVGA%@AE@%         0x0048      Olivetti Video Graphics Array%@NL@%
  8045. %@NL@%
  8046. %@CR:MQPD3005@%%@4@%Table 13.3%@BO:   63a63@%  lists the constants for monitors.%@EH@%%@NL@%
  8047. %@NL@%
  8048. %@CR:MQPDT300@%%@4@%%@AB@%Table 13.3  Constants for Monitors%@AE@%%@EH@%%@NL@%
  8049. %@NL@%
  8050. %@AB@%Constant        Value              Description%@AE@%%@NL@%
  8051. %@NL@%
  8052. %@AB@%_Mono%@AE@%           0x0001             Monochrome%@NL@%
  8053. %@AB@%_Color%@AE@%          0x0002             Color%@NL@%
  8054. %@AB@%_ENHColor%@AE@%       0x0004             Enhanced Color%@NL@%
  8055. %@AB@%_AnalogMono%@AE@%     0x0008             Analog Monochrome only%@NL@%
  8056. %@AB@%_AnalogColor%@AE@%    0x0010             Analog Color only%@NL@%
  8057. %@AB@%_Analog%@AE@%         0x0018             Analog Monochrome and Color modes%@NL@%
  8058. %@NL@%
  8059. %@NL@%
  8060. %@CR:MQPD3100@%%@3@%%@AB@%13.3.1  Selecting a Video Mode%@AE@%%@EH@%%@NL@%
  8061. %@NL@%
  8062. %@CR:MQPD3101@%%@4@%Before you can display graphics, you must put the graphics adapter into a%@EH@%
  8063. graphics mode. As shown in the example program, the %@AB@%_SetVideoMode%@AE@% function
  8064. performs this task. Before calling %@AB@%_SetVideoMode%@AE@%, you must decide which
  8065. graphics modes are acceptable for your purposes. There are several ways you
  8066. can select an appropriate graphics mode:%@NL@%
  8067. %@NL@%
  8068. %@CR:MQPD3102@%  ■  Set the mode to a specified value. If you want the program to work in a%@NL@%
  8069.      high-resolution EGA color mode, use %@AB@%_SetVideoMode%@AE@% to set the mode to%@NL@%
  8070.      %@AB@%_EResColor%@AE@%:%@NL@%
  8071. %@NL@%
  8072.         %@AS@%a := _SetVideoMode( _EResColor );%@AE@%%@NL@%
  8073. %@NL@%
  8074.   ■  Request either the highest resolution available using the %@AB@%_MaxResMode%@AE@%%@NL@%
  8075.      constant or the greatest color selection, %@AB@%_MaxColorMode%@AE@%, available with%@NL@%
  8076.      your monitor and adapter configuration:%@NL@%
  8077. %@NL@%
  8078. %@AS@%        { Selects highest resolution }%@NL@%
  8079.         %@AS@%a := _SetVideoMode( _MaxResMode );%@AE@%%@NL@%
  8080. %@AS@%        { or, selects most colors }%@NL@%
  8081.         %@AS@%a := _SetVideoMode( _MaxColorMode );%@AE@%%@NL@%
  8082. %@NL@%
  8083.   ■  Specify a specific resolution mode (such as 320 x 200 pixels) by first%@NL@%
  8084.      determining the video adapter type (from the %@AB@%_VideoConfig%@AE@% structure)%@NL@%
  8085.      and then setting the appropriate mode for the adapter. The program%@NL@%
  8086.      fragment below shows how this technique can be used to set a 320 x 200%@NL@%
  8087.      pixel resolution mode.%@NL@%
  8088. %@NL@%
  8089. %@NL@%
  8090. %@AS@%   _GetVideoConfig( vc );    { Find out adapter type }%@NL@%
  8091. %@AS@%      IF (vc.Monitor = _Mono) THEN%@NL@%
  8092. %@AS@%         BEGIN%@NL@%
  8093. %@AS@%         Writeln( 'This program requires a color monitor.' );%@NL@%
  8094. %@AS@%         Halt( 0 );%@NL@%
  8095. %@AS@%         END%@NL@%
  8096. %@AS@%      ELSE%@NL@%
  8097. %@AS@%         CASE vc.Adapter OF%@NL@%
  8098. %@AS@%            _MDPA, _HGC :%@NL@%
  8099. %@AS@%               BEGIN%@NL@%
  8100. %@AS@%               Writeln( 'This program requires a color graphics adapter.' );%@NL@%
  8101. %@AS@%               Halt( 0 );%@NL@%
  8102. %@AS@%               END;%@NL@%
  8103. %@AS@%            _CGA, _OCGA : a := _SetVideoMode( _MRes4Color );%@NL@%
  8104. %@AS@%            _EGA, _OEGA : a := _SetVideoMode( _MRes16Color );%@NL@%
  8105. %@AS@%            _MCGA, _VGA : a := _SetVideoMode( _MRes256Color );%@NL@%
  8106. %@AS@%            END;%@NL@%
  8107. %@AS@%      { To get video configuration after mode is set }%@NL@%
  8108. %@AS@%      _GetVideoConfig( vc );%@NL@%
  8109. %@NL@%
  8110. %@NL@%
  8111. %@CR:MQPD3103@%%@4@%This program fragment begins by calling %@AB@%_GetVideoConfig%@AE@%, which determines%@EH@%
  8112. the graphics configuration and tells the type of adapter currently in use.
  8113. If the monitor is monochrome, the program displays a message and halts.
  8114. Next, the %@AB@%CASE%@AE@% statement enters the appropriate graphics mode. Finally, the
  8115. program segment calls %@AB@%_GetVideoConfig%@AE@% to get the new configuration values
  8116. after the mode has been set.%@NL@%
  8117. %@NL@%
  8118. %@CR:MQPD3104@%%@4@%To view every possible graphics mode, you can run the example program%@EH@%
  8119. GRAPHIC.PAS, shown below. Sections 13.3.2%@BO:   6586d@%-13.3.6 explain the various
  8120. graphics modes.%@NL@%
  8121. %@NL@%
  8122. %@AS@%     PROGRAM graphic;  { Displays every graphic mode }%@NL@%
  8123. %@NL@%
  8124. %@AS@%     USES%@NL@%
  8125. %@AS@%         Crt, MSGraph;%@NL@%
  8126. %@AS@%     CONST%@NL@%
  8127. %@AS@%         modes : ARRAY [0..11] OF Integer =%@NL@%
  8128. %@AS@%                (_MRes4Color, _MResNoColor, _HResBW, _HercMono,%@NL@%
  8129. %@AS@%                 _MRes16Color, _HRes16Color, _EResNoColor, _EResColor,%@NL@%
  8130. %@AS@%                 _VRes2Color, _VRes16Color, _MRes256Color, _OResColor );%@NL@%
  8131. %@AS@%     VAR%@NL@%
  8132. %@AS@%         vc : _VideoConfig;%@NL@%
  8133. %@AS@%         ch, key   : Char;%@NL@%
  8134. %@AS@%         which : Char;%@NL@%
  8135. %@AS@%         a : Integer;%@NL@%
  8136. %@NL@%
  8137. %@AS@%     PROCEDURE print_menu;%@NL@%
  8138. %@AS@%     { Prints a menu on the screen }%@NL@%
  8139. %@AS@%     BEGIN%@NL@%
  8140. %@NL@%
  8141. %@AS@%         Writeln( 'Please choose a graphics mode' );%@NL@%
  8142. %@AS@%         Writeln( 'Type "x" to exit' );%@NL@%
  8143. %@AS@%         Writeln;%@NL@%
  8144. %@AS@%         Writeln( '0  _MRES4COLOR' );%@NL@%
  8145. %@AS@%         Writeln( '1  _MRESNOCOLOR' );%@NL@%
  8146. %@AS@%         Writeln( '2  _HRESBW' );%@NL@%
  8147. %@AS@%         Writeln( '3  _HERCMONO' );%@NL@%
  8148. %@AS@%         Writeln( '4  _MRES16COLOR' );%@NL@%
  8149. %@AS@%         Writeln( '5  _HRES16COLOR' );%@NL@%
  8150. %@AS@%         Writeln( '6  _ERESNOCOLOR' );%@NL@%
  8151. %@AS@%         Writeln( '7  _ERESCOLOR' );%@NL@%
  8152. %@AS@%         Writeln( '8  _VRES2COLOR' );%@NL@%
  8153. %@AS@%         Writeln( '9  _VRES16COLOR' );%@NL@%
  8154. %@AS@%         Writeln( 'a  _MRES256COLOR' );%@NL@%
  8155. %@AS@%         Writeln( 'b  _ORESCOLOR' );%@NL@%
  8156. %@AS@%     END;%@NL@%
  8157. %@NL@%
  8158. %@NL@%
  8159. %@AS@%     PROCEDURE show_mode( which : Char );%@NL@%
  8160. %@AS@%     { Shows the different video modes. }%@NL@%
  8161. %@NL@%
  8162. %@AS@%     VAR%@NL@%
  8163. %@AS@%         nc, i  : Integer;%@NL@%
  8164. %@AS@%         height : Integer;%@NL@%
  8165. %@AS@%         width  : Integer;%@NL@%
  8166. %@AS@%         mode   : STRING;%@NL@%
  8167. %@AS@%         r : Real;%@NL@%
  8168. %@AS@%         e,m : Integer;%@NL@%
  8169. %@NL@%
  8170. %@AS@%     BEGIN%@NL@%
  8171. %@AS@%         mode := which;%@NL@%
  8172. %@AS@%         IF (mode < '0') OR (mode > '9') THEN%@NL@%
  8173. %@AS@%            IF mode = 'a' THEN%@NL@%
  8174. %@AS@%                mode := '10'%@NL@%
  8175. %@AS@%            ELSE IF mode = 'b' THEN%@NL@%
  8176. %@AS@%                 mode := '11'%@NL@%
  8177. %@AS@%                ELSE Halt; { Exit procedure }%@NL@%
  8178. %@AS@%         Val( mode, r, e );%@NL@%
  8179. %@AS@%         m := Trunc( r );%@NL@%
  8180. %@AS@%         a :=  _SetVideoMode( modes[m] );%@NL@%
  8181. %@AS@%         IF (a <> 0) THEN%@NL@%
  8182. %@AS@%             BEGIN%@NL@%
  8183. %@AS@%             _GetVideoConfig( vc );%@NL@%
  8184. %@AS@%             nc := vc.NumColors;%@NL@%
  8185. %@AS@%             width := vc.NumXPixels DIV nc;%@NL@%
  8186. %@AS@%             height := vc.NumYPixels DIV 2;%@NL@%
  8187. %@AS@%             FOR i := 1 TO ( nc - 1 ) DO%@NL@%
  8188. %@AS@%                 BEGIN%@NL@%
  8189. %@AS@%                 _SetColor( i );%@NL@%
  8190. %@AS@%                 _Rectangle( _GFillInterior, i * width,%@NL@%
  8191. %@AS@%                             0, ( i + 1 ) * width, height );%@NL@%
  8192. %@AS@%                 END;%@NL@%
  8193. %@AS@%             END { IF a not equal to 0 }%@NL@%
  8194. %@AS@%         ELSE%@NL@%
  8195. %@AS@%             BEGIN%@NL@%
  8196. %@AS@%             Writeln( 'Video mode ', which, ' is not available.' );%@NL@%
  8197. %@AS@%             Writeln( 'Please press ENTER.' );%@NL@%
  8198. %@AS@%             END;%@NL@%
  8199. %@NL@%
  8200. %@AS@%         Readln;  { Wait for ENTER to be pressed }%@NL@%
  8201. %@AS@%         a := _SetVideoMode( _DefaultMode );%@NL@%
  8202. %@AS@%         print_menu;%@NL@%
  8203. %@AS@%     END;%@NL@%
  8204. %@NL@%
  8205. %@NL@%
  8206. %@AS@%     BEGIN  { Begin main program }%@NL@%
  8207. %@NL@%
  8208. %@AS@%         key := ' ';%@NL@%
  8209. %@AS@%         _ClearScreen( _GClearScreen );%@NL@%
  8210. %@AS@%         print_menu;%@NL@%
  8211. %@AS@%         WHILE ( key <> 'x' ) DO%@NL@%
  8212. %@AS@%             BEGIN%@NL@%
  8213. %@AS@%             key := ReadKey;%@NL@%
  8214. %@AS@%             show_mode( key );%@NL@%
  8215. %@AS@%             END;%@NL@%
  8216. %@AS@%     END.%@NL@%
  8217. %@NL@%
  8218. %@NL@%
  8219. %@CR:MQPD3200@%%@3@%%@AB@%13.3.2  CGA Color Graphics Modes%@AE@%%@EH@%%@NL@%
  8220. %@NL@%
  8221. %@CR:MQPD3201@%%@4@%The CGA color graphics modes %@AB@%_MRes4Color%@AE@% and %@AB@%_MResNoColor%@AE@% display four%@EH@%
  8222. colors selected from one of several predefined palettes of colors. They
  8223. display these foreground colors against a  background color that can be any
  8224. one of the 16 available colors. With the CGA hardware, the palette of
  8225. foreground colors is predefined and cannot be changed. Each palette number
  8226. is an integer as shown in Table 13.4%@BO:   65aa1@%.%@NL@%
  8227. %@NL@%
  8228. %@CR:MQPDT400@%%@4@%%@AB@%Table 13.4  Available CGA Colors%@AE@%%@EH@%%@NL@%
  8229. %@NL@%
  8230. %@AB@%Palette%@AE@%     ┌────────────────%@AB@%Color Index%@AE@%────────────┐%@NL@%
  8231. %@AB@%Number      1                   2                   3%@AE@%%@NL@%
  8232. %@NL@%
  8233. 0           Green               Red                 Brown%@NL@%
  8234. 1           Cyan                Magenta             Light Gray%@NL@%
  8235. 2           Light Green         Light Red           Yellow%@NL@%
  8236. 3           Light Cyan          Light Magenta       White%@NL@%
  8237. %@NL@%
  8238. %@NL@%
  8239. %@CR:MQPD3202@%%@4@%The %@AB@%_MResNoColor%@AE@% graphics mode produces palettes containing various shades%@EH@%
  8240. of gray on black-and-white monitors. The %@AB@%_MResNoColor%@AE@% mode displays colors
  8241. when used with a color display. However, only two palettes are available
  8242. with a color display. You can use the %@AB@%_SelectPalette%@AE@% function to select one
  8243. of these predefined palettes. Table 13.5%@BO:   65e9f@% shows the correspondence between
  8244. the color indexes and the palettes.%@NL@%
  8245. %@NL@%
  8246. %@CR:MQPDT500@%%@4@%%@AB@%Table 13.5  CGA Colors:  _MResNoColor Mode%@AE@%%@EH@%%@NL@%
  8247. %@NL@%
  8248. %@AB@%Palette%@AE@%     ┌────────────────%@AB@%Color Index%@AE@%────────────┐%@NL@%
  8249. %@AB@%Number      1                   2                   3%@AE@%%@NL@%
  8250. %@NL@%
  8251. 0           Blue                Red                 Light Gray%@NL@%
  8252. 1           Light Blue          Light               Red White%@NL@%
  8253. %@NL@%
  8254. %@NL@%
  8255. %@CR:MQPD3203@%%@4@%You may use the %@AB@%_SelectPalette%@AE@% function in conjunction with the %@AB@%_MRes4Color%@AE@%,%@EH@%
  8256. %@AB@%_MResNoColor%@AE@%, and %@AB@%_OResColor%@AE@% graphics modes. To change palettes in other
  8257. graphics modes, use the %@AB@%_RemapPalette%@AE@% or %@AB@%_RemapAllPalette%@AE@% routines.%@NL@%
  8258. %@NL@%
  8259. %@CR:MQPD3204@%%@4@%In %@AB@%_OResColor%@AE@% mode, you can choose one of 16 foreground colors by passing a%@EH@%
  8260. value in the range 0-15 to the %@AB@%_SelectPalette%@AE@% function. The background color
  8261. is always black.%@NL@%
  8262. %@NL@%
  8263. %@CR:MQPD3205@%%@4@%The following program sets the video mode to %@AB@%_MRes4Color%@AE@% and then cycles%@EH@%
  8264. through background colors and palette combinations. It works on computers
  8265. equipped with CGA, EGA, MCGA, or VGA cards. A color monitor is required.%@NL@%
  8266. %@NL@%
  8267. %@AS@%     PROGRAM cga;%@NL@%
  8268. %@AS@%     { Demonstrates CGA colors }%@NL@%
  8269. %@NL@%
  8270. %@AS@%     USES%@NL@%
  8271. %@AS@%         MSGraph;%@NL@%
  8272. %@NL@%
  8273. %@AS@%     CONST%@NL@%
  8274. %@AS@%         bkcolor : ARRAY [0..7] OF LongInt = (_Black, _Blue, _Green, _Cyan,%@NL@%
  8275. %@AS@%                   _Red, _Magenta, _Brown, _White);%@NL@%
  8276. %@NL@%
  8277. %@AS@%         bkcolor_name : ARRAY [0..7] OF STRING = ('BLACK  ', 'BLUE   ',%@NL@%
  8278. %@AS@%                        'GREEN  ', 'CYAN   ', 'RED    ', 'MAGENTA',%@NL@%
  8279. %@AS@%                        'BROWN  ', 'WHITE  ');%@NL@%
  8280. %@NL@%
  8281. %@AS@%     VAR%@NL@%
  8282. %@AS@%         a, i, j, k : Integer;%@NL@%
  8283. %@NL@%
  8284. %@AS@%     BEGIN  { Begin main program }%@NL@%
  8285. %@AS@%         a := _SetVideoMode( _MRes4Color );%@NL@%
  8286. %@AS@%         FOR i := 0 TO 3 DO%@NL@%
  8287. %@AS@%             BEGIN%@NL@%
  8288. %@AS@%             a := _SelectPalette( i );%@NL@%
  8289. %@AS@%             FOR k := 0 TO 7 DO%@NL@%
  8290. %@AS@%                 BEGIN%@NL@%
  8291. %@AS@%                 _SetBkColor( bkcolor[k] );%@NL@%
  8292. %@AS@%                 FOR j := 0 TO 3 DO%@NL@%
  8293. %@AS@%                     BEGIN%@NL@%
  8294. %@AS@%                     _SetTextPosition( 1, 1 );%@NL@%
  8295. %@AS@%                     Writeln( 'Background color: ', bkcolor_name[k] );%@NL@%
  8296. %@AS@%                     Writeln( '   Palette: ', i );%@NL@%
  8297. %@AS@%                     Writeln( '   Number: ', j );%@NL@%
  8298. %@AS@%                     _SetColor( j );%@NL@%
  8299. %@AS@%                     _Rectangle( _GFillInterior, 160, 100, 320, 200 );%@NL@%
  8300. %@AS@%                     Readln;  { Wait for ENTER to be pressed }%@NL@%
  8301. %@AS@%                     END; { for j }%@NL@%
  8302. %@AS@%                 END; { for k }%@NL@%
  8303. %@AS@%             END; { for i }%@NL@%
  8304. %@NL@%
  8305. %@AS@%         a := _SetVideoMode( _DefaultMode ); { restore original palette }%@NL@%
  8306. %@AS@%     END.%@NL@%
  8307. %@NL@%
  8308. %@NL@%
  8309. %@CR:MQPD3300@%%@3@%%@AB@%13.3.3  EGA, MCGA, and VGA Palettes%@AE@%%@EH@%%@NL@%
  8310. %@NL@%
  8311. %@CR:MQPD3301@%%@4@%The beginning of this chapter mentioned the difference between color indexes%@EH@%
  8312. and color values. An analogy might make things clearer. Imagine a painter
  8313. who owns 64 tubes of paint and a painter's palette that has room for only 16
  8314. globs of paint at any one time. A painting created under these constraints
  8315. could contain only 16 colors (selected from a total of 64). The EGA graphics
  8316. modes (such as %@AB@%_EResColor%@AE@%) are similar: they have 16 color indexes chosen
  8317. from a total of 64 color values.%@NL@%
  8318. %@NL@%
  8319. %@CR:MQPD3302@%%@4@%The color values available in the EGA, MCGA, and VGA palettes are not%@EH@%
  8320. predetermined like the CGA palettes. Instead, the color values available in
  8321. EGA, MCGA, and VGA palettes are created by a process of "color mixing" of
  8322. red, green, and blue elements. The next two sections describe color mixing.%@NL@%
  8323. %@NL@%
  8324. %@CR:MQPD3310@%%@4@%%@AB@%VGA Color Mixing%@AE@%%@EH@%%@NL@%
  8325. %@NL@%
  8326. %@CR:MQPD3311@%%@4@%VGA offers the widest variety of color values: 262,144 (256K). Depending on%@EH@%
  8327. the graphics mode, the VGA palette size may be 2, 16, or 256. When you
  8328. select a color value, you specify a level of intensity ranging from 0-63 for
  8329. each of the red, green, and blue color values. The long integer that defines
  8330. a color value consists of four bytes (32 bits):%@NL@%
  8331. %@NL@%
  8332.      MSB                             LSB%@NL@%
  8333.      zzzzzzzz zzBBBBBB zzGGGGGG zzRRRRRR%@NL@%
  8334. %@NL@%
  8335. %@CR:MQPD3312@%%@4@%The most-significant byte must contain all zeros. The two high bits in the%@EH@%
  8336. remaining three bytes must also be 0. To mix a light red (pink), turn red
  8337. all the way up, and mix in some green and blue:%@NL@%
  8338. %@NL@%
  8339.      00000000 00100000 00100000 00111111%@NL@%
  8340. %@NL@%
  8341. %@CR:MQPD3313@%%@4@%To represent this value in hexadecimal, use the number %@AS@%$0020203F%@AE@%.%@EH@%%@NL@%
  8342. %@NL@%
  8343. %@CR:MQPD3314@%%@4@%For white, turn all the elements on; for black, set all elements to 0.%@EH@%%@NL@%
  8344. %@NL@%
  8345. %@CR:MQPD3320@%%@4@%%@AB@%EGA Color Mixing%@AE@%%@EH@%%@NL@%
  8346. %@NL@%
  8347. %@CR:MQPD3321@%%@4@%Mixing colors in EGA modes is similar to the mixing described above, but%@EH@%
  8348. there are fewer intensities for the red, green, and blue components. In the
  8349. modes that offer 64 colors, the R, G, and B values cover 2 bits and can
  8350. range from 0-3. The long integer that defines an RGB color looks like this:%@NL@%
  8351. %@NL@%
  8352.      MSB                             LSB%@NL@%
  8353.      zzzzzzzz zzBB???? zzGG???? zzRR????%@NL@%
  8354. %@NL@%
  8355. %@CR:MQPD3322@%%@4@%The bits marked %@AS@%z%@AE@% must be zeros and the bits marked with question marks can%@EH@%
  8356. be any value. This format is used for compatibility with VGA color mixing.
  8357. To form a pure red color value, you would use the constant %@AS@%$00000030%@AE@%. For
  8358. cyan (blue plus green), use %@AS@%$00303000%@AE@%.%@NL@%
  8359. %@NL@%
  8360. %@NL@%
  8361. %@CR:MQPD3400@%%@3@%%@AB@%13.3.4  EGA Color Graphics Modes%@AE@%%@EH@%%@NL@%
  8362. %@NL@%
  8363. %@CR:MQPD3401@%%@4@%If you have an EGA adapter, you should use the video mode %@AB@%_MRes16Color%@AE@%,%@EH@%
  8364. %@AB@%_HRes16Color%@AE@%, or %@AB@%_EResColor%@AE@% for the best color-graphics results. The CGA
  8365. modes also display on the EGA but with the lower CGA resolution and
  8366. decreased color options.%@NL@%
  8367. %@NL@%
  8368. %@CR:MQPD3402@%%@4@%The %@AB@%_RemapPalette%@AE@% function assigns a new color value to a color index. For%@EH@%
  8369. example, when you first enter an EGA graphics mode, color index 1 equals the
  8370. color value blue. To reassign the pure red color value to color index 1, you
  8371. could use this line:%@NL@%
  8372. %@NL@%
  8373. %@AS@%     a := _RemapPalette( 1, $000030 );%@NL@%
  8374. %@NL@%
  8375. %@CR:MQPD3403@%%@4@%Or, use the symbolic constant %@AB@%_Red%@AE@%, which is defined using the %@AB@%MSGraph%@AE@% unit:%@EH@%%@NL@%
  8376. %@NL@%
  8377. %@AS@%     a := _RemapPalette( 1, _Red );%@NL@%
  8378. %@NL@%
  8379. %@CR:MQPD3404@%%@4@%After this function call, any object currently drawn in color index 1%@EH@%
  8380. instantly switches from blue to red.%@NL@%
  8381. %@NL@%
  8382. %@CR:MQPD3405@%%@4@%The first value is an %@AB@%Integer%@AE@% in the range 0-15 and the second value is a%@EH@%
  8383. %@AB@%LongInt%@AE@% defined as a mixture of red, green, and blue (you may also use
  8384. symbolic constants such as %@AB@%_Red%@AE@%).%@NL@%
  8385. %@NL@%
  8386. %@CR:MQPD3406@%%@4@%The %@AB@%_RemapAllPalette%@AE@% procedure changes all of the color indexes%@EH@%
  8387. simultaneously. You pass it an array of color values. The first color value
  8388. in the list becomes the new color associated with the color index 0.%@NL@%
  8389. %@NL@%
  8390. %@CR:MQPD3407@%%@4@%The number in a function call that sets the color (such as %@AB@%_SetColor%@AE@%) is an%@EH@%
  8391. index into the palette of available colors. In the default text palette, an
  8392. index of 1 refers to blue but the palette could be remapped to change index
  8393. 1 to any other available color. As a result, the color produced by that
  8394. pixel value also changes. The number of color indexes depends on the number
  8395. of colors supported by the current video mode.%@NL@%
  8396. %@NL@%
  8397. %@CR:MQPD3408@%%@4@%The %@AB@%_RemapPalette%@AE@% and %@AB@%_RemapAllPalette%@AE@% routines work in all modes but only%@EH@%
  8398. with the EGA, MCGA, or VGA hardware. The %@AB@%_RemapPalette%@AE@% fails, returning a
  8399. value of -1 when you attempt to remap a palette without the EGA, MCGA, or
  8400. VGA hardware.%@NL@%
  8401. %@NL@%
  8402. %@CR:MQPD3409@%%@4@%The following program draws a rectangle with a red interior. In the default%@EH@%
  8403. EGA palette, the color index 4 is red. This color index is changed to %@AB@%_Blue%@AE@%
  8404. in this program.%@NL@%
  8405. %@NL@%
  8406. %@AS@%     PROGRAM ega;%@NL@%
  8407. %@AS@%     { Demonstrates EGA/VGA palettes }%@NL@%
  8408. %@NL@%
  8409. %@AS@%     USES%@NL@%
  8410. %@AS@%         MSGraph;%@NL@%
  8411. %@NL@%
  8412. %@AS@%     CONST%@NL@%
  8413. %@AS@%         crlf = #13 + #10;%@NL@%
  8414. %@NL@%
  8415. %@AS@%     VAR%@NL@%
  8416. %@AS@%         a : LongInt;%@NL@%
  8417. %@AS@%         m : Integer;%@NL@%
  8418. %@NL@%
  8419. %@AS@%     BEGIN  { Begin main program }%@NL@%
  8420. %@NL@%
  8421. %@AS@%         m := _SetVideoMode( _MaxColorMode );%@NL@%
  8422. %@AS@%         _SetColor( 4 );%@NL@%
  8423. %@AS@%         _Rectangle( _GFillInterior, 50, 50, 150, 150 );%@NL@%
  8424. %@NL@%
  8425. %@AS@%         _SetTextPosition( 1, 1 );%@NL@%
  8426. %@AS@%         _OutText( 'Normal palette' + crlf );%@NL@%
  8427. %@AS@%         _OutText( 'Press ENTER' );%@NL@%
  8428. %@AS@%         Readln;%@NL@%
  8429. %@NL@%
  8430. %@AS@%         a := _RemapPalette( 4, _Blue );%@NL@%
  8431. %@NL@%
  8432. %@AS@%         _SetTextPosition( 1, 1 );%@NL@%
  8433. %@AS@%         _OutText( 'Remapped palette' + crlf );%@NL@%
  8434. %@AS@%         _OutText( 'Press ENTER' );%@NL@%
  8435. %@AS@%         Readln;%@NL@%
  8436. %@NL@%
  8437. %@AS@%         a := _RemapPalette( 4, _Red );%@NL@%
  8438. %@NL@%
  8439. %@AS@%         _SetTextPosition( 1, 1 );%@NL@%
  8440. %@AS@%         _OutText( 'Restored palette' + crlf );%@NL@%
  8441. %@AS@%         _OutText( 'Press ENTER to clear the screen' );%@NL@%
  8442. %@AS@%         Readln;%@NL@%
  8443. %@NL@%
  8444. %@AS@%         _ClearScreen( _GClearScreen );%@NL@%
  8445. %@AS@%         m := _SetVideoMode( _DefaultMode );%@NL@%
  8446. %@AS@%     END.%@NL@%
  8447. %@NL@%
  8448. %@NL@%
  8449. %@CR:MQPD3500@%%@3@%%@AB@%13.3.5  VGA Color Graphics Modes%@AE@%%@EH@%%@NL@%
  8450. %@NL@%
  8451. %@CR:MQPD3501@%%@4@%The VGA card adds graphics modes %@AB@%_VRes2Color%@AE@%, %@AB@%_VRes16Color%@AE@%, and%@EH@%
  8452. %@AB@%_MRes256Color%@AE@% to your repertoire. EGA and CGA modes can also be used with
  8453. the VGA hardware, but with either lower resolution or fewer color choices.%@NL@%
  8454. %@NL@%
  8455. %@CR:MQPD3502@%%@4@%The VGA color graphics modes operate with a range of 262,144 (256K) color%@EH@%
  8456. values. The %@AB@%_VRes2Color%@AE@% graphics mode displays two colors, the %@AB@%_VRes16Color%@AE@%
  8457. graphics mode displays 16 colors, and the %@AB@%_MRes256Color%@AE@% graphics mode
  8458. displays 256 colors from the available VGA colors.%@NL@%
  8459. %@NL@%
  8460. %@CR:MQPD3503@%%@4@%The %@AB@%_RemapPalette%@AE@% function changes a color index to a specified color value.%@EH@%
  8461. The function below remaps the color index 1 to the color value given by the
  8462. symbolic constant %@AB@%_Red%@AE@% (which represents red). After this statement is
  8463. executed, whatever was displayed as blue now appears as red:%@NL@%
  8464. %@NL@%
  8465. %@AS@%     { reassign color index 1 to VGA red }%@NL@%
  8466. %@AS@%     a := _RemapPalette( 1, _Red );%@NL@%
  8467. %@NL@%
  8468. %@CR:MQPD3504@%%@4@%Use the %@AB@%_RemapAllPalette%@AE@% procedure to remap all of the available color%@EH@%
  8469. indexes simultaneously. The procedure's argument references an array of
  8470. color values that reflects the remapping. The first color number in the list
  8471. becomes the new color associated with color index 0.%@NL@%
  8472. %@NL@%
  8473. %@CR:MQPD3505@%%@4@%Symbolic constants for the default color numbers are supplied so that the%@EH@%
  8474. remapping of VGA colors is compatible with EGA practice. The names of these
  8475. constants are self-explanatory. For example, the color numbers for black,
  8476. red, and light yellow are represented by the symbolic constants %@AB@%_Black%@AE@%,
  8477. %@AB@%_Red%@AE@%, and %@AB@%_Yellow%@AE@%.%@NL@%
  8478. %@NL@%
  8479. %@CR:MQPD3506@%%@4@%All of the VGA display modes operate with any VGA video monitor. Colors are%@EH@%
  8480. displayed as shades of gray when a monochrome analog display is connected.%@NL@%
  8481. %@NL@%
  8482. %@CR:MQPD3507@%%@4@%The program HORIZON.PAS illustrates what can be done with the range of 256%@EH@%
  8483. colors if you have a VGA card:%@NL@%
  8484. %@NL@%
  8485. %@AS@%     PROGRAM horizon; { Demonstrates VGA graphics with cycling of 256 colors}%@NL@%
  8486. %@NL@%
  8487. %@AS@%     USES%@NL@%
  8488. %@AS@%         Crt, MSGraph;%@NL@%
  8489. %@AS@%     CONST%@NL@%
  8490. %@AS@%         Red = $00002a;%@NL@%
  8491. %@AS@%         GRN = $002a00;%@NL@%
  8492. %@AS@%         BLU = $2a0000;%@NL@%
  8493. %@AS@%         WHT = $2a2a2a;%@NL@%
  8494. %@AS@%         step = 21;%@NL@%
  8495. %@AS@%     VAR%@NL@%
  8496. %@AS@%         vc : _VideoConfig;%@NL@%
  8497. %@AS@%         rainbow : ARRAY [1..512] OF LongInt;%@NL@%
  8498. %@AS@%         i, a      : Integer;%@NL@%
  8499. %@AS@%         col, gray : LongInt;%@NL@%
  8500. %@AS@%         rec : _XYCoord;%@NL@%
  8501. %@NL@%
  8502. %@AS@%     BEGIN  { Begin main program }%@NL@%
  8503. %@AS@%         a := _SetVideoMode( _MRes256Color );%@NL@%
  8504. %@AS@%         IF (a = 0) THEN%@NL@%
  8505. %@AS@%             BEGIN%@NL@%
  8506. %@AS@%             Writeln( 'This program requires a VGA or MCGA card' );%@NL@%
  8507. %@AS@%             Halt( 0 );%@NL@%
  8508. %@AS@%             END;%@NL@%
  8509. %@NL@%
  8510. %@AS@%         FOR col := 0 TO 63 DO%@NL@%
  8511. %@AS@%             BEGIN%@NL@%
  8512. %@AS@%             gray := col OR (col SHL 8) OR (col SHL 16);%@NL@%
  8513. %@AS@%             rainbow[col] :=   BLU AND gray;%@NL@%
  8514. %@AS@%             rainbow[col + 256] := BLU AND gray;%@NL@%
  8515. %@AS@%             rainbow[col + 64] := BLU OR gray;%@NL@%
  8516. %@AS@%             rainbow[col + 64 + 256] := BLU OR gray;%@NL@%
  8517. %@AS@%             rainbow[col + 128] := Red OR (WHT AND NOT gray);%@NL@%
  8518. %@AS@%             rainbow[col + 128 + 256] := Red  OR (WHT AND NOT gray);%@NL@%
  8519. %@AS@%             rainbow[col + 192] := Red OR NOT gray;%@NL@%
  8520. %@AS@%             rainbow[col + 192 + 256] := Red OR NOT gray;%@NL@%
  8521. %@AS@%             END;%@NL@%
  8522. %@NL@%
  8523. %@AS@%     _SetViewOrg( 160, 85, rec );%@NL@%
  8524. %@NL@%
  8525. %@AS@%         FOR i := 0 TO 254 DO%@NL@%
  8526. %@AS@%             BEGIN%@NL@%
  8527. %@AS@%             _SetColor( 255 - i );%@NL@%
  8528. %@AS@%             _MoveTo( i, i - 255 );%@NL@%
  8529. %@AS@%             _LineTo( -i, 255 - i );%@NL@%
  8530. %@AS@%             _MoveTo( -i, i - 255 );%@NL@%
  8531. %@AS@%             _LineTo( i, 255 - i );%@NL@%
  8532. %@AS@%             _Ellipse( _GBorder, -i, -i DIV 2, i, i DIV 2 );%@NL@%
  8533. %@AS@%             END;%@NL@%
  8534. %@NL@%
  8535. %@AS@%         i := 0;%@NL@%
  8536. %@AS@%         WHILE NOT KeyPressed DO%@NL@%
  8537. %@AS@%             BEGIN%@NL@%
  8538. %@AS@%             _RemapAllPalette( rainbow[i] );%@NL@%
  8539. %@AS@%             i := i + step;%@NL@%
  8540. %@AS@%             IF (i >= 256) THEN i := 0;%@NL@%
  8541. %@AS@%             END;%@NL@%
  8542. %@NL@%
  8543. %@AS@%         a := _SetVideoMode( _DefaultMode );%@NL@%
  8544. %@AS@%     END.%@NL@%
  8545. %@NL@%
  8546. %@NL@%
  8547. %@CR:MQPD3600@%%@3@%%@AB@%13.3.6  Using the Color Video Text Modes%@AE@%%@EH@%%@NL@%
  8548. %@NL@%
  8549. %@CR:MQPD3601@%%@4@%All video adapters offer support for video text modes (%@AB@%_TextC40%@AE@%,%@EH@%
  8550. %@AB@%_TextC80%@AE@%, %@AB@%_TextBW40%@AE@%, %@AB@%_TextBW80%@AE@%, %@AB@%_TextMono%@AE@% ). Using the video text modes, you
  8551. can display color text without having to enter a graphics mode. On a color
  8552. monitor, you can display normal or blinking text in any of 16 foreground
  8553. colors with any of 8 background colors. On a monochrome monitor, you can
  8554. specify text "colors" in exactly the same way, although the color values are
  8555. interpreted differently by the hardware.%@NL@%
  8556. %@NL@%
  8557. %@CR:MQPD3602@%%@4@%The text procedures and functions described in this section can be used in%@EH@%
  8558. the video text modes as well as in all of the graphics modes.%@NL@%
  8559. %@NL@%
  8560. %@CR:MQPD3610@%%@4@%%@AB@%Selecting Text Colors%@AE@%%@EH@%%@NL@%
  8561. %@NL@%
  8562. %@CR:MQPD3611@%%@4@%In a video text mode, each displayed character requires two bytes of video%@EH@%
  8563. memory. The first byte contains the ASCII code representing the character
  8564. and the second byte contains the display attribute. In the CGA color video
  8565. text modes, the attribute byte determines the color and whether it will
  8566. blink. Sixteen colors are available: the CGA indexes, and the default EGA
  8567. and VGA indexes. Since the EGA and VGA palettes can be remapped, these
  8568. values can be made to correspond to any set of 16 colors with the
  8569. appropriate palette mapping.%@NL@%
  8570. %@NL@%
  8571. %@CR:MQPD3620@%%@4@%%@AB@%Using Text Colors%@AE@%%@EH@%%@NL@%
  8572. %@NL@%
  8573. %@CR:MQPD3621@%%@4@%Use the %@AB@%_GetTextColor%@AE@% and %@AB@%_GetBkColor%@AE@% functions to find foreground and%@EH@%
  8574. background colors of the current text.%@NL@%
  8575. %@NL@%
  8576. %@CR:MQPD3622@%%@4@%Values in the range 0-15 are interpreted as normal color. Values in the%@EH@%
  8577. range 16-31 are the same colors as those in the range 0-15 but with blinking
  8578. text.%@NL@%
  8579. %@NL@%
  8580. %@CR:MQPD3623@%%@4@%Set the foreground and background colors in a video text mode with the%@EH@%
  8581. %@AB@%_SetTextColor%@AE@% and %@AB@%_SetBkColor%@AE@% functions. These functions use a single
  8582. argument that specifies the index to be used for text displayed with the
  8583. %@AB@%_OutText%@AE@% procedure. The color indexes for color video text modes are defined
  8584. in Table 13.6%@BO:   6a0ff@%.%@NL@%
  8585. %@NL@%
  8586. %@CR:MQPDT600@%%@4@%%@AB@%Table 13.6  Text Colors%@AE@%%@EH@%%@NL@%
  8587. %@NL@%
  8588. %@AB@%Number      Color       Number     Color%@AE@%%@NL@%
  8589. %@NL@%
  8590. 0           Black       8          Gray%@NL@%
  8591. 1           Blue        9          Light Blue%@NL@%
  8592. 2           Green       10         Light Green%@NL@%
  8593. 3           Cyan        11         Light Cyan%@NL@%
  8594. 4           Red         12         Light Red%@NL@%
  8595. 5           Magenta     13         Light Magenta%@NL@%
  8596. 6           Brown       14         Yellow%@NL@%
  8597. 7           White       15         Light White%@NL@%
  8598. %@NL@%
  8599. %@CR:MQPD3624@%%@4@%On monochrome displays, you can select text attributes in the same way as%@EH@%
  8600. for color displays. For underlined text, use Blue or Light Blue. For
  8601. highlighted text, use any color from Light Green to White. For blinking
  8602. text, add 16 to the color constant.%@NL@%
  8603. %@NL@%
  8604. %@CR:MQPD3630@%%@4@%%@AB@%Displaying Text Colors%@AE@%%@EH@%%@NL@%
  8605. %@NL@%
  8606. %@CR:MQPD3631@%%@4@%The %@AB@%_SetTextPosition%@AE@% procedure moves the cursor to a row and column for%@EH@%
  8607. displaying color text. The %@AB@%_OutText%@AE@% procedure displays the text.%@NL@%
  8608. %@NL@%
  8609. %@CR:MQPD3632@%%@4@%The following program displays a chart showing all possible combinations of%@EH@%
  8610. text and background colors:%@NL@%
  8611. %@NL@%
  8612. %@AS@%     PROGRAM coltext;  { Displays text in color }%@NL@%
  8613. %@NL@%
  8614. %@AS@%     USES%@NL@%
  8615. %@AS@%         Crt, MSGraph;%@NL@%
  8616. %@NL@%
  8617. %@AS@%     VAR%@NL@%
  8618. %@AS@%         message1, s, t : STRING;%@NL@%
  8619. %@AS@%         blink, fgd, bgd : Integer;%@NL@%
  8620. %@AS@%         a : Integer;%@NL@%
  8621. %@NL@%
  8622. %@AS@%     BEGIN  { Begin main program }%@NL@%
  8623. %@NL@%
  8624. %@AS@%         _ClearScreen( _GClearScreen );%@NL@%
  8625. %@AS@%         _OutText( 'Color text attributes:' );%@NL@%
  8626. %@NL@%
  8627. %@AS@%         FOR blink := 0 TO 1 DO%@NL@%
  8628. %@AS@%             FOR bgd := 0 TO 6 DO%@NL@%
  8629. %@AS@%                 BEGIN%@NL@%
  8630. %@AS@%                 _SetBkColor( bgd );%@NL@%
  8631. %@AS@%                 _SetTextPosition( bgd + (blink  * 9) + 3, 1 );%@NL@%
  8632. %@AS@%                 _SetTextColor( 7 );%@NL@%
  8633. %@AS@%                 Str( bgd, s );%@NL@%
  8634. %@AS@%                 message1 := 'Bgd: ';%@NL@%
  8635. %@AS@%                 _OutText( message1 );%@NL@%
  8636. %@AS@%                 _OutText( s );%@NL@%
  8637. %@AS@%                 s := s + ' ';%@NL@%
  8638. %@AS@%                 message1 := '  Fgd: ';%@NL@%
  8639. %@AS@%                 _OutText( message1 );%@NL@%
  8640. %@AS@%                 FOR fgd := 0 TO 15 DO%@NL@%
  8641. %@AS@%                     BEGIN%@NL@%
  8642. %@AS@%                     _SetTextColor( fgd + (blink*16) );%@NL@%
  8643. %@AS@%                     a := fgd + (blink*16);%@NL@%
  8644. %@AS@%                     Str( a, s );%@NL@%
  8645. %@AS@%                     s := s + '  ';%@NL@%
  8646. %@AS@%                     _OutText( s );%@NL@%
  8647. %@AS@%                     END;%@NL@%
  8648. %@AS@%                 END; { FOR loops }%@NL@%
  8649. %@NL@%
  8650. %@AS@%         REPEAT UNTIL KeyPressed;%@NL@%
  8651. %@AS@%         a := _SetVideoMode( _DefaultMode );%@NL@%
  8652. %@NL@%
  8653. %@AS@%     END.%@NL@%
  8654. %@NL@%
  8655. %@NL@%
  8656. %@CR:MQPD4000@%%@2@%%@AB@%13.4  Understanding Coordinate Systems%@AE@%%@EH@%%@NL@%
  8657. %@NL@%
  8658. %@CR:MQPD4001@%%@4@%Before you can write a program to print a word or to display graphics on the%@EH@%
  8659. screen, you need a system that describes exactly where to print or display
  8660. the item.%@NL@%
  8661. %@NL@%
  8662. %@CR:MQPD4002@%%@4@%QuickPascal provides several coordinate systems. The physical coordinate%@EH@%
  8663. system has already been used in the program 1STGRAPH.PAS. This section
  8664. discusses the four coordinate systems supported by QuickPascal and shows how
  8665. to translate between systems.%@NL@%
  8666. %@NL@%
  8667. %@CR:MQPD4003@%%@4@%The coordinate systems supported by QuickPascal are:%@EH@%%@NL@%
  8668. %@NL@%
  8669. %@CR:MQPD4004@%  ■  Text coordinates%@NL@%
  8670. %@NL@%
  8671.   ■  Physical coordinates%@NL@%
  8672. %@NL@%
  8673.   ■  Viewport coordinates%@NL@%
  8674. %@NL@%
  8675.   ■  Real coordinates in a window%@NL@%
  8676. %@NL@%
  8677. %@NL@%
  8678. %@CR:MQPD4100@%%@3@%%@AB@%13.4.1  Text Coordinates%@AE@%%@EH@%%@NL@%
  8679. %@NL@%
  8680. %@CR:MQPD4101@%%@4@%QuickPascal divides the text screen into rows and columns. See Figure 13.1%@EH@%%@FN@%
  8681. Figure 13.1 is found on page 193 in the printed version of this book.%@EF@%.%@NL@%
  8682. %@NL@%
  8683. %@CR:MQPD4102@%%@4@%Two important conventions to keep in mind about video text mode are:%@EH@%%@NL@%
  8684. %@NL@%
  8685. %@CR:MQPD4103@%  1. Numbering starts at 1, not 0. An 80-column screen contains columns%@NL@%
  8686.      1-80.%@NL@%
  8687. %@NL@%
  8688.   2. The row is always listed before the column.%@NL@%
  8689. %@NL@%
  8690. %@CR:MQPD4104@%%@4@%If the screen is in a video text mode that displays 25 rows and 80 columns%@EH@%
  8691. (as in Figure 13.1%@FN@%
  8692. 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
  8693. numbered 1-80. In routines such as %@AB@%_SetTextPosition%@AE@%, which is called in the
  8694. next example program, the parameters you pass are row and column (in that
  8695. order). Some monitors (such as the EGA or VGA) support more than 25 text
  8696. rows. For these monitors, use the %@AB@%_SetVideoModeRows%@AE@% or %@AB@%_SetTextRows%@AE@%
  8697. functions to specify the number of rows to display.%@NL@%
  8698. %@NL@%
  8699. %@NL@%
  8700. %@CR:MQPD4200@%%@3@%%@AB@%13.4.2  Physical Screen Coordinates%@AE@%%@EH@%%@NL@%
  8701. %@NL@%
  8702. %@CR:MQPD4201@%%@4@%Suppose you write a program that calls %@AB@%_SetVideoMode%@AE@% and puts the screen%@EH@%
  8703. into the VGA graphics mode %@AB@%_VRes16Color%@AE@%. This gives you a screen containing
  8704. 640 horizontal pixels and 480 vertical pixels. The individual pixels are
  8705. named by their location relative to the %@AI@%x%@AE@% axis and %@AI@%y%@AE@% axis, as shown in
  8706. Figure 13.2%@FN@%
  8707. Figure 13.2 is found on page 194 in the printed version of this book.%@EF@%. Two important differences between text coordinates and graphics
  8708. coordinates are:%@NL@%
  8709. %@NL@%
  8710. %@CR:MQPD4202@%  1. Numbering starts at 0, not 1. If there are 640 pixels, they're%@NL@%
  8711.      numbered 0-639.%@NL@%
  8712. %@NL@%
  8713.   2. The %@AI@%x%@AE@% coordinate is listed before the %@AI@%y%@AE@% coordinate.%@NL@%
  8714. %@NL@%
  8715. %@CR:MQPD4203@%%@4@%The upper left corner is called the "origin."  The %@AI@%x%@AE@% and %@AI@%y%@AE@% coordinates for%@EH@%
  8716. the origin are always (0, 0). If you use variables to refer to pixel
  8717. locations, declare them as integers. The "viewport" is the region where
  8718. graphics will be displayed.%@NL@%
  8719. %@NL@%
  8720. %@CR:MQPD4210@%%@4@%%@AB@%Changing the Origin with _SetViewOrg%@AE@%%@EH@%%@NL@%
  8721. %@NL@%
  8722. %@CR:MQPD4211@%%@4@%The %@AB@%_SetViewOrg%@AE@% procedure changes the location of the viewport's origin. You%@EH@%
  8723. pass two integers, which represent the %@AI@%x%@AE@% and %@AI@%y%@AE@% coordinates of a physical
  8724. screen location. For example, the following line would move the origin to
  8725. the physical screen location (50, 100):%@NL@%
  8726. %@NL@%
  8727. %@AS@%     _SetViewOrg( 50, 100, xyorg );%@NL@%
  8728. %@NL@%
  8729. %@CR:MQPD4212@%%@4@%The effect on the screen is illustrated in Figure 13.3%@EH@%%@FN@%
  8730. Figure 13.3 is found on page 195 in the printed version of this book.%@EF@%.%@NL@%
  8731. %@NL@%
  8732. %@CR:MQPD4213@%%@4@%The number of pixels hasn't changed, but the names given to the points have%@EH@%
  8733. changed. The %@AI@%x%@AE@% axis now ranges from -50 to +589 instead of 0 to 639. The %@AI@%y%@AE@%
  8734. axis now covers the values -100 to +379. (If you own an adapter other than
  8735. the VGA, the numbers are different but the effect is the same.) All standard
  8736. graphics functions and procedures are affected by the new origin, including
  8737. %@AB@%_MoveTo%@AE@%, %@AB@%_LineTo%@AE@%, %@AB@%_Rectangle%@AE@%, %@AB@%_Ellipse%@AE@%, %@AB@%_Arc%@AE@%, and %@AB@%_Pie%@AE@%.%@NL@%
  8738. %@NL@%
  8739. %@CR:MQPD4214@%%@4@%For example, if you call the %@AB@%_Rectangle%@AE@% procedure after relocating the%@EH@%
  8740. viewport origin, and pass it the coordinate values (0, 0) and (40, 40), the
  8741. rectangle would be drawn 50 pixels from the left edge of the screen and 100
  8742. pixels from the top. It would not appear in the upper left corner.%@NL@%
  8743. %@NL@%
  8744. %@CR:MQPD4215@%%@4@%The values passed to %@AB@%_SetViewOrg%@AE@% are always physical screen locations.%@EH@%
  8745. Suppose you called the same procedure twice:%@NL@%
  8746. %@NL@%
  8747. %@AS@%     _SetViewOrg( 50, 100, xyorg );%@NL@%
  8748. %@AS@%     _SetViewOrg( 50, 100, xyorg );%@NL@%
  8749. %@NL@%
  8750. %@CR:MQPD4216@%%@4@%The viewport origin would %@AI@%not%@AE@% move to (100, 200). It would remain at the%@EH@%
  8751. physical screen location (50, 100).%@NL@%
  8752. %@NL@%
  8753. %@CR:MQPD4220@%%@4@%%@AB@%Defining a Clipping Region with _SetClipRgn%@AE@%%@EH@%%@NL@%
  8754. %@NL@%
  8755. %@CR:MQPD4221@%%@4@%The %@AB@%_SetClipRgn%@AE@% procedure creates an invisible rectangular area on the%@EH@%
  8756. screen called a "clipping region." Attempts to draw inside the clipping
  8757. region are successful, while attempts to draw outside the region are not.%@NL@%
  8758. %@NL@%
  8759. %@CR:MQPD4222@%%@4@%When you first enter a graphics mode, the default clipping region is the%@EH@%
  8760. entire screen. QuickPascal ignores any attempts to draw outside the clipping
  8761. region.%@NL@%
  8762. %@NL@%
  8763. %@CR:MQPD4223@%%@4@%Changing the clipping region requires one call to %@AB@%_SetClipRgn%@AE@%. Suppose%@EH@%
  8764. you've entered the CGA graphics mode %@AB@%_MRes4Color%@AE@%, which has a screen
  8765. resolution of 320 x 200. If you draw a diagonal line from the top left to
  8766. the bottom right corner, the screen looks like Figure 13.4%@FN@%
  8767. Figure 13.4 is found on page 196 in the printed version of this book.%@EF@%. You could
  8768. create a clipping region with the following:%@NL@%
  8769. %@NL@%
  8770. %@AS@%     _SetClipRgn( 10, 10, 309, 189 );%@NL@%
  8771. %@NL@%
  8772. %@CR:MQPD4224@%%@4@%Then draw a line with the statement:%@EH@%%@NL@%
  8773. %@NL@%
  8774. %@AS@%     _LineTo( 0, 0, 319, 199 );%@NL@%
  8775. %@NL@%
  8776. %@CR:MQPD4225@%%@4@%With the clipping region in effect, the same %@AB@%_LineTo%@AE@% command given above%@EH@%
  8777. would put the line shown in Figure 13.5%@FN@%
  8778. Figure 13.5 is found on page 197 in the printed version of this book.%@EF@% on the screen.%@NL@%
  8779. %@NL@%
  8780. %@CR:MQPD4226@%%@4@%The broken lines don't actually appear on the screen. They indicate the%@EH@%
  8781. outer bounds of the clipping region.%@NL@%
  8782. %@NL@%
  8783. %@NL@%
  8784. %@CR:MQPD4300@%%@3@%%@AB@%13.4.3  Viewport Coordinates%@AE@%%@EH@%%@NL@%
  8785. %@NL@%
  8786. %@CR:MQPD4301@%%@4@%Viewport coordinates are yet another coordinate system supported by%@EH@%
  8787. QuickPascal. You can establish a new viewport within the boundaries of the
  8788. physical screen by using the %@AB@%_SetViewport%@AE@% procedure. A standard viewport has
  8789. two distinguishing features:%@NL@%
  8790. %@NL@%
  8791. %@CR:MQPD4302@%  1. The origin of a viewport is in the upper left corner.%@NL@%
  8792. %@NL@%
  8793.   2. The clipping region matches the outer boundaries of the viewport.%@NL@%
  8794. %@NL@%
  8795. %@CR:MQPD4303@%%@4@%The %@AB@%_SetViewport%@AE@% procedure does the same thing as calling %@AB@%_SetViewOrg%@AE@% and%@EH@%
  8796. %@AB@%_SetClipRgn%@AE@% together.%@NL@%
  8797. %@NL@%
  8798. %@NL@%
  8799. %@CR:MQPD4400@%%@3@%%@AB@%13.4.4  Real Coordinates in a Window%@AE@%%@EH@%%@NL@%
  8800. %@NL@%
  8801. %@CR:MQPD4401@%%@4@%QuickPascal supports a system of real coordinates for use in a window. This%@EH@%
  8802. system lets you use floating-point values in graphics.%@NL@%
  8803. %@NL@%
  8804. %@CR:MQPD4402@%%@4@%Functions and procedures that refer to coordinates on the physical screen%@EH@%
  8805. and within the viewport require integer values. However, in real-life
  8806. graphing applications, you might wish to use floating-point values──stock
  8807. prices, the price of wheat, average rainfall, and so on.%@NL@%
  8808. %@NL@%
  8809. %@CR:MQPD4410@%%@4@%%@AB@%Setting Window Coordinates%@AE@%%@EH@%%@NL@%
  8810. %@NL@%
  8811. %@CR:MQPD4411@%%@4@%The %@AB@%_SetWindow%@AE@% procedure allows you to scale the screen to almost any size.%@EH@%
  8812. In addition, the window-related functions and procedures take
  8813. double-precision floating-point values instead of integers.%@NL@%
  8814. %@NL@%
  8815. %@CR:MQPD4412@%%@4@%If, for example, you wanted to graph 12 months of average temperatures that%@EH@%
  8816. range from -40 to +100, you could add the following line to your program:%@NL@%
  8817. %@NL@%
  8818.      %@AS@%_SetWindow( TRUE, 1.0, -40.0, 12.0, 100.0 );%@AE@%%@NL@%
  8819. %@NL@%
  8820. %@CR:MQPD4413@%%@4@%The first argument is the invert flag, which puts the lowest %@AI@%y%@AE@% value in the%@EH@%
  8821. bottom left corner. The minimum and maximum Cartesian coordinates follow
  8822. (the decimal point marks them as floating-point values). The new
  8823. organization of the screen is shown in Figure 13.6%@FN@%
  8824. Figure 13.6 is found on page 198 in the printed version of this book.%@EF@%.%@NL@%
  8825. %@NL@%
  8826. %@CR:MQPD4414@%%@4@%This procedure makes the temperatures for January and December appear on the%@EH@%
  8827. left and right edges of the screen. In an application like this, it might be
  8828. better to number the %@AI@%x%@AE@% axis from 0.0 to 13.0, to provide some extra space.%@NL@%
  8829. %@NL@%
  8830. %@CR:MQPD4415@%%@4@%If you plot a point with %@AB@%_SetPixel_w%@AE@% or draw a line with %@AB@%_LineTo_w%@AE@%, the%@EH@%
  8831. values are automatically scaled to the established window. You can also find
  8832. the position of the graphics cursor at any time with
  8833. %@AB@%_GetCurrentPosition_wxy%@AE@%.%@NL@%
  8834. %@NL@%
  8835. %@CR:MQPD4420@%%@4@%%@AB@%Programming Real-Coordinate Graphics%@AE@%%@EH@%%@NL@%
  8836. %@NL@%
  8837. %@CR:MQPD4421@%%@4@%The four steps to using real-coordinate graphics are:%@EH@%%@NL@%
  8838. %@NL@%
  8839. %@CR:MQPD4422@%  1. Enter a graphics mode with %@AB@%_SetVideoMode%@AE@%.%@NL@%
  8840. %@NL@%
  8841.   2. Use %@AB@%_SetViewPort%@AE@% to create a viewport area. This step is optional if%@NL@%
  8842.      you plan to use the entire screen.%@NL@%
  8843. %@NL@%
  8844.   3. Create a real-coordinate window with %@AB@%_SetWindow%@AE@%, passing a Boolean%@NL@%
  8845.      invert flag and four %@AB@%Double%@AE@% %@AI@%x%@AE@% and %@AI@%y%@AE@% coordinates for the minimum and%@NL@%
  8846.      maximum values.%@NL@%
  8847. %@NL@%
  8848.   4. Draw graphics shapes with %@AB@%_Rectangle_w%@AE@% and other procedures. Do not%@NL@%
  8849.      confuse %@AB@%_Rectangle%@AE@% (the viewport procedure) with %@AB@%_Rectangle_w%@AE@% (the%@NL@%
  8850.      window procedure for drawing rectangles). All window procedures end%@NL@%
  8851.      with an underscore and a letter %@AB@%w%@AE@% or an underscore and %@AB@%wxy%@AE@%.%@NL@%
  8852. %@NL@%
  8853. %@CR:MQPD4423@%%@4@%Real-coordinate graphics can give you a lot of flexibility. For example, you%@EH@%
  8854. can fit either axis into a small range (such as 151.25 to 151.45) or into a
  8855. large range (-50,000 to +80,000), depending on the type of data you're
  8856. graphing. In addition, by changing the window coordinates, you can create
  8857. the effects of zooming in or panning across a figure.%@NL@%
  8858. %@NL@%
  8859. %@CR:MQPD4430@%%@4@%%@AB@%An Example of Real-Coordinate Graphics%@AE@%%@EH@%%@NL@%
  8860. %@NL@%
  8861. %@CR:MQPD4431@%%@4@%The program below illustrates how to use the real-coordinate window%@EH@%
  8862. routines.%@NL@%
  8863. %@NL@%
  8864. %@AS@%     PROGRAM realg; { Example of real-coordinate graphics }%@NL@%
  8865. %@AS@%     USES%@NL@%
  8866. %@AS@%         MsGraph, Crt;%@NL@%
  8867. %@NL@%
  8868. %@AS@%     CONST%@NL@%
  8869. %@AS@%         bananas : ARRAY[0..20] OF Single =%@NL@%
  8870. %@AS@%             (%@NL@%
  8871. %@AS@%             -0.3,   -0.2, -0.224, -0.1,   -0.5, +0.21, +2.9,%@NL@%
  8872. %@AS@%             +0.3,   +0.2,  0.0,   -0.885, -1.1, -0.3,  -0.2,%@NL@%
  8873. %@AS@%              0.001, 0.005, 0.14,   0.0,   -0.9, -0.13, +0.3%@NL@%
  8874. %@AS@%              );%@NL@%
  8875. %@AS@%     VAR%@NL@%
  8876. %@AS@%         halfx, halfy,%@NL@%
  8877. %@AS@%         a   : Integer;%@NL@%
  8878. %@AS@%         vc  : _VideoConfig;%@NL@%
  8879. %@AS@%         ch  : Char;%@NL@%
  8880. %@NL@%
  8881. %@AS@%     FUNCTION four_colors : Boolean;%@NL@%
  8882. %@AS@%     BEGIN%@NL@%
  8883. %@AS@%         four_colors := False;%@NL@%
  8884. %@AS@%         IF (_SetVideoMode( _MaxColorMode ) > 0) THEN%@NL@%
  8885. %@AS@%             BEGIN%@NL@%
  8886. %@AS@%             _GetVideoConfig( vc );%@NL@%
  8887. %@AS@%             IF (vc.NumColors >= 4) THEN%@NL@%
  8888. %@AS@%                 four_colors := True;%@NL@%
  8889. %@AS@%             END;%@NL@%
  8890. %@NL@%
  8891. %@AS@%     END;%@NL@%
  8892. %@NL@%
  8893. %@AS@%     PROCEDURE grid_shape;%@NL@%
  8894. %@AS@%     VAR%@NL@%
  8895. %@AS@%         i, x1, y1, x2, y2  : Integer;%@NL@%
  8896. %@AS@%         x, y               : Real;%@NL@%
  8897. %@AS@%         s                  : STRING[80];%@NL@%
  8898. %@AS@%     BEGIN%@NL@%
  8899. %@NL@%
  8900. %@AS@%         FOR i := 1 TO vc.NumColors DO%@NL@%
  8901. %@AS@%             BEGIN%@NL@%
  8902. %@AS@%             _SetTextPosition( i, 2 );%@NL@%
  8903. %@AS@%             _SetTextColor( i );%@NL@%
  8904. %@AS@%             Str( i, s );%@NL@%
  8905. %@AS@%             _OutText( 'Color ' + s );%@NL@%
  8906. %@AS@%             END;%@NL@%
  8907. %@NL@%
  8908. %@AS@%         _SetColor( 1 );%@NL@%
  8909. %@AS@%         _Rectangle_w( _GBorder, -1.0,  -1.0,  1.0,  1.0  );%@NL@%
  8910. %@AS@%         _Rectangle_w( _GBorder, -1.02, -1.02, 1.02, 1.02 );%@NL@%
  8911. %@NL@%
  8912. %@AS@%         x := -0.9;%@NL@%
  8913. %@AS@%         i :=  0;%@NL@%
  8914. %@AS@%         WHILE  x < 0.9 DO%@NL@%
  8915. %@AS@%             BEGIN%@NL@%
  8916. %@AS@%             _SetColor( 2 );%@NL@%
  8917. %@AS@%             _MoveTo_w( x, -1.0 );   _LineTo_w( x, 1.0 );%@NL@%
  8918. %@AS@%             _MoveTo_w( -1.0, x );   _LineTo_w( 1.0, x );%@NL@%
  8919. %@AS@%             _SetColor( 3 );%@NL@%
  8920. %@AS@%             _MoveTo_w( x - 0.1, bananas[i] );%@NL@%
  8921. %@AS@%             Inc( i );%@NL@%
  8922. %@AS@%             _LineTo_w( x, bananas[i] );%@NL@%
  8923. %@AS@%             x := x + 0.1;%@NL@%
  8924. %@AS@%             END;%@NL@%
  8925. %@NL@%
  8926. %@AS@%         _MoveTo_w( 0.9, bananas[i] );%@NL@%
  8927. %@AS@%         Inc(i);%@NL@%
  8928. %@AS@%         _LineTo_w( 1.0, bananas[i] );%@NL@%
  8929. %@AS@%         END;%@NL@%
  8930. %@NL@%
  8931. %@AS@%     PROCEDURE three_graphs;%@NL@%
  8932. %@AS@%     VAR%@NL@%
  8933. %@AS@%         upleft, botright : _WXYCoord;%@NL@%
  8934. %@AS@%         xwidth, yheight, cols, rows : Integer;%@NL@%
  8935. %@NL@%
  8936. %@NL@%
  8937. %@AS@%     BEGIN%@NL@%
  8938. %@AS@%         _ClearScreen( _GClearScreen );%@NL@%
  8939. %@AS@%         xwidth  := vc.NumXPixels;%@NL@%
  8940. %@AS@%         yheight := vc.NumYPixels;%@NL@%
  8941. %@AS@%         halfx   := xwidth  DIV 2;%@NL@%
  8942. %@AS@%         halfy   := yheight DIV 2;%@NL@%
  8943. %@AS@%         cols    := vc.NumTextCols;%@NL@%
  8944. %@AS@%         rows    := vc.NumTextRows;%@NL@%
  8945. %@NL@%
  8946. %@AS@%         { first window }%@NL@%
  8947. %@AS@%         _SetViewport( 0, 0, halfx-1, halfy-1 );%@NL@%
  8948. %@AS@%         _SetTextWindow( 1, 1, rows DIV 2, cols DIV 2 );%@NL@%
  8949. %@AS@%         _SetWindow( False, -2.0, -2.0, 2.0, 2.0 );%@NL@%
  8950. %@AS@%         grid_shape;%@NL@%
  8951. %@AS@%         _Rectangle( _GBorder, 0, 0, halfx-1, halfy-1 );%@NL@%
  8952. %@NL@%
  8953. %@AS@%         { second window }%@NL@%
  8954. %@AS@%         _SetViewport( halfx, 0, xwidth-1, halfy-1 );%@NL@%
  8955. %@AS@%         _SetTextWindow( 1, cols DIV 2+1, rows DIV 2, cols );%@NL@%
  8956. %@AS@%         _SetWindow( False, -3.0, -3.0, 3.0, 3.0 );%@NL@%
  8957. %@AS@%         grid_shape;%@NL@%
  8958. %@AS@%         _Rectangle_w( _GBorder, -3.0, -3.0, 3.0, 3.0 );%@NL@%
  8959. %@NL@%
  8960. %@AS@%         { third window }%@NL@%
  8961. %@AS@%         _SetViewport( 0, halfy, xwidth-1, yheight-1 );%@NL@%
  8962. %@AS@%         _SetTextWindow( rows DIV 2+2, 1, rows, cols );%@NL@%
  8963. %@AS@%         _SetWindow( True, -3.0, -1.5, 1.5, 1.5 );%@NL@%
  8964. %@AS@%         grid_shape;%@NL@%
  8965. %@AS@%         upleft.wx   := -3.0;%@NL@%
  8966. %@AS@%         upleft.wy   := -1.5;%@NL@%
  8967. %@AS@%         botright.wx :=  1.5;%@NL@%
  8968. %@AS@%         botright.wy :=  1.5;%@NL@%
  8969. %@AS@%         _Rectangle_wxy( _GBorder, upleft, botright);%@NL@%
  8970. %@NL@%
  8971. %@AS@%     END;%@NL@%
  8972. %@NL@%
  8973. %@AS@%     BEGIN { main program }%@NL@%
  8974. %@NL@%
  8975. %@AS@%     IF four_colors THEN%@NL@%
  8976. %@AS@%       BEGIN%@NL@%
  8977. %@AS@%       _OutText( 'This program requires a CGA, EGA, or VGA graphics card' );%@NL@%
  8978. %@AS@%       three_graphs;%@NL@%
  8979. %@AS@%       END;%@NL@%
  8980. %@NL@%
  8981. %@AS@%     ch := ReadKey;%@NL@%
  8982. %@AS@%     a := _SetVideoMode( _DefaultMode );%@NL@%
  8983. %@NL@%
  8984. %@AS@%     END.%@NL@%
  8985. %@NL@%
  8986. %@CR:MQPD4432@%%@4@%The main body of the program is short. It calls the %@AS@%four_colors%@AE@% function%@EH@%
  8987. (defined below), which attempts to enter a graphics mode in which at least
  8988. four colors are available. If it succeeds, the %@AS@%three_graphs%@AE@% function is
  8989. called. This function uses the numbers in the %@AS@%bananas%@AE@% array to draw three
  8990. graphs. The REALG.PAS screen output is shown in Figure 13.7%@FN@%
  8991. Figure 13.7 is found on page 202 in the printed version of this book.%@EF@%.%@NL@%
  8992. %@NL@%
  8993. %@CR:MQPD4433@%%@4@%It's worth noting that the graphs are all drawn using the same numbers.%@EH@%
  8994. However, the program uses three different real-coordinate windows. The two
  8995. windows in the top half are the same size in physical coordinates, but they
  8996. have different window sizes. In all three cases, the grid is two units wide.
  8997. In the upper left corner, the window is four units wide; in the upper right,
  8998. the window is six units wide, which makes the graph appear smaller.%@NL@%
  8999. %@NL@%
  9000. %@CR:MQPD4434@%%@4@%In two of the three graphs, one of the lines goes off the edge, outside the%@EH@%
  9001. clipping region. The lines do not intrude into the other windows, since
  9002. defining a window creates a clipping region.%@NL@%
  9003. %@NL@%
  9004. %@CR:MQPD4435@%%@4@%Finally, note that the graph on the bottom of the screen seems to be upside%@EH@%
  9005. down with respect to the two graphs above it. This is the result of setting
  9006. the invert flag to %@AB@%True%@AE@%.%@NL@%
  9007. %@NL@%
  9008. %@CR:MQPD4440@%%@4@%%@AB@%Entering a Graphics Mode%@AE@%%@EH@%%@NL@%
  9009. %@NL@%
  9010. %@CR:MQPD4441@%%@4@%The first step in any graphics program is to enter a graphics mode. The%@EH@%
  9011. function %@AS@%four_colors%@AE@% performs this step:%@NL@%
  9012. %@NL@%
  9013. %@AS@%     FUNCTION four_colors : Boolean;%@NL@%
  9014. %@AS@%     BEGIN%@NL@%
  9015. %@AS@%         four_colors := False;%@NL@%
  9016. %@AS@%         IF (_SetVideoMode( _MaxColorMode ) > 0) THEN%@NL@%
  9017. %@AS@%             BEGIN%@NL@%
  9018. %@AS@%             _GetVideoConfig( vc );%@NL@%
  9019. %@AS@%             IF (vc.NumColors >= 4) THEN%@NL@%
  9020. %@AS@%                 four_colors := True;%@NL@%
  9021. %@AS@%             END;%@NL@%
  9022. %@NL@%
  9023. %@AS@%     END;%@NL@%
  9024. %@NL@%
  9025. %@NL@%
  9026. %@CR:MQPD4442@%%@4@%The %@AB@%_GetVideoConfig%@AE@% procedure places some information into the structure%@EH@%
  9027. %@AB@%_VideoConfig%@AE@% called %@AS@%screen%@AE@%. Then you use the member %@AS@%screen.adapter%@AE@% of the
  9028. %@AB@%_VideoConfig%@AE@% structure in a %@AB@%CASE%@AE@% statement construct to turn on the matching
  9029. graphics mode. The symbolic constants %@AB@%_CGA%@AE@% and the rest are defined in the
  9030. %@AB@%MSGraph%@AE@% unit. The modes containing the letter "O" are Olivetti modes.%@NL@%
  9031. %@NL@%
  9032. %@CR:MQPD4443@%%@4@%If the computer is equipped with a color card, this function returns a %@AB@%True%@AE@%.%@EH@%
  9033. If it is not, it returns a %@AB@%False%@AE@%, which causes the program to skip the
  9034. function %@AS@%three_graphs%@AE@% and to end the program.%@NL@%
  9035. %@NL@%
  9036. %@CR:MQPD4444@%%@4@%If the %@AS@%four_colors%@AE@% function works properly, the program calls the function%@EH@%
  9037. below, which prints the three graphs.%@NL@%
  9038. %@NL@%
  9039. %@AS@%     PROCEDURE three_graphs;%@NL@%
  9040. %@AS@%     VAR%@NL@%
  9041. %@AS@%         upleft, botright : _WXYCoord;%@NL@%
  9042. %@AS@%         xwidth, yheight, cols, rows : Integer;%@NL@%
  9043. %@NL@%
  9044. %@AS@%     BEGIN%@NL@%
  9045. %@AS@%         _ClearScreen( _GClearScreen );%@NL@%
  9046. %@AS@%         xwidth  := vc.NumXPixels;%@NL@%
  9047. %@AS@%         yheight := vc.NumYPixels;%@NL@%
  9048. %@AS@%         halfx   := xwidth  DIV 2;%@NL@%
  9049. %@AS@%         halfy   := yheight DIV 2;%@NL@%
  9050. %@AS@%         cols    := vc.NumTextCols;%@NL@%
  9051. %@AS@%         rows    := vc.NumTextRows;%@NL@%
  9052. %@NL@%
  9053. %@NL@%
  9054. %@AS@%         { first window }%@NL@%
  9055. %@AS@%         _SetViewport( 0, 0, halfx-1, halfy-1 );%@NL@%
  9056. %@AS@%         _SetTextWindow( 1, 1, rows DIV 2, cols DIV 2 );%@NL@%
  9057. %@AS@%         _SetWindow( False, -2.0, -2.0, 2.0, 2.0 );%@NL@%
  9058. %@AS@%         grid_shape;%@NL@%
  9059. %@AS@%         _Rectangle( _GBorder, 0, 0, halfx-1, halfy-1 );%@NL@%
  9060. %@NL@%
  9061. %@AS@%         { second window }%@NL@%
  9062. %@AS@%         _SetViewport( halfx, 0, xwidth-1, halfy-1 );%@NL@%
  9063. %@AS@%         _SetTextWindow( 1, cols DIV 2+1, rows DIV 2, cols );%@NL@%
  9064. %@AS@%         _SetWindow( False, -3.0, -3.0, 3.0, 3.0 );%@NL@%
  9065. %@AS@%         grid_shape;%@NL@%
  9066. %@AS@%         _Rectangle_w( _GBorder, -3.0, -3.0, 3.0, 3.0 );%@NL@%
  9067. %@NL@%
  9068. %@AS@%         { third window }%@NL@%
  9069. %@AS@%         _SetViewport( 0, halfy, xwidth-1, yheight-1 );%@NL@%
  9070. %@AS@%         _SetTextWindow( rows DIV 2+2, 1, rows, cols );%@NL@%
  9071. %@AS@%         _SetWindow( True, -3.0, -1.5, 1.5, 1.5 );%@NL@%
  9072. %@AS@%         grid_shape;%@NL@%
  9073. %@AS@%         upleft.wx   := -3.0;%@NL@%
  9074. %@AS@%         upleft.wy   := -1.5;%@NL@%
  9075. %@AS@%         botright.wx :=  1.5;%@NL@%
  9076. %@AS@%         botright.wy :=  1.5;%@NL@%
  9077. %@AS@%         _Rectangle_wxy( _GBorder, upleft, botright);%@NL@%
  9078. %@NL@%
  9079. %@AS@%     END;%@NL@%
  9080. %@NL@%
  9081. %@CR:MQPD4450@%%@4@%%@AB@%Working with Windows%@AE@%%@EH@%%@NL@%
  9082. %@NL@%
  9083. %@CR:MQPD4451@%%@4@%Although entering a graphics mode automatically clears the screen, it%@EH@%
  9084. doesn't hurt to be sure, so %@AS@%three_graphs%@AE@% calls the %@AB@%_ClearScreen%@AE@% procedure:%@NL@%
  9085. %@NL@%
  9086. %@AS@%     _ClearScreen( _GClearScreen );%@NL@%
  9087. %@NL@%
  9088. %@CR:MQPD4452@%%@4@%The %@AB@%_GClearScreen%@AE@% constant causes the entire physical screen to clear.%@EH@%
  9089. Other options include %@AB@%_GViewport%@AE@% and %@AB@%_GWindow%@AE@%, which clear the current
  9090. viewport and the current text window, respectively.%@NL@%
  9091. %@NL@%
  9092. %@4@%%@AB@%The First Window%@AE@%%@EH@%%@NL@%
  9093. %@NL@%
  9094. %@4@%After assigning values to some variables, the procedure %@AS@%three_graphs%@AE@%%@EH@%
  9095. creates the first window:%@NL@%
  9096. %@NL@%
  9097. %@AS@%     _SetViewPort( 0, 0, halfx - 1, halfy - 1 );%@NL@%
  9098. %@AS@%     _SetTextWindow( 1, 1, rows / 2, cols / 2 );%@NL@%
  9099. %@AS@%     _SetWindow( False, -2.0, -2.0, 2.0, 2.0 );%@NL@%
  9100. %@NL@%
  9101. %@4@%First a viewport is defined to cover the upper left quarter of the screen.%@EH@%
  9102. Next, a text window is defined within the boundaries of that border. (Note
  9103. the numbering starts at 1 and the row location precedes the column.)
  9104. Finally, a window is defined. The %@AB@%False%@AE@% constant forces the %@AI@%y%@AE@% axis to
  9105. increase from top to bottom. The corners of the window are (-2.0, -2.0) in
  9106. the upper left and (2.0, 2.0) in the bottom right corner.%@NL@%
  9107. %@NL@%
  9108. %@CR:MQPD4453@%%@4@%Next, the function %@AS@%grid_shape%@AE@% is called, and a border is added to the%@EH@%
  9109. window:%@NL@%
  9110. %@NL@%
  9111. %@AS@%     grid_shape;%@NL@%
  9112. %@AS@%     _Rectangle( _GBorder, 0, 0, halfx-1, halfy-1 );%@NL@%
  9113. %@NL@%
  9114. %@CR:MQPD4454@%%@4@%Note that this is the standard %@AB@%_Rectangle%@AE@% procedure, which takes coordinates%@EH@%
  9115. relative to the viewport (%@AI@%not%@AE@% window coordinates).%@NL@%
  9116. %@NL@%
  9117. %@CR:MQPD4455@%%@4@%%@AB@%Two More Windows%@AE@%%@EH@%%@NL@%
  9118. %@NL@%
  9119. %@CR:MQPD4456@%%@4@%The two other windows are similar to the first. All three call %@AS@%grid_shape%@AE@%%@EH@%
  9120. (defined below), which draws a grid from location (-1.0, -1.0) to (+1.0,
  9121. +1.0). The grid appears in different sizes because the coordinates in the
  9122. windows vary. The second window ranges from (-3.0, -3.0) to (+3.0, +3.0),
  9123. so the width of the grid is one-third the width of the second window, while
  9124. it is one-half the width of the first.%@NL@%
  9125. %@NL@%
  9126. %@CR:MQPD4457@%%@4@%Note also that the third window contains %@AB@%True%@AE@% as the first argument. This%@EH@%
  9127. causes the %@AI@%y%@AE@% axis to increase from bottom to top, instead of top to bottom.
  9128. As a result, this graph appears to be upside down in relation to the other
  9129. two.%@NL@%
  9130. %@NL@%
  9131. %@CR:MQPD4458@%%@4@%After calling %@AS@%grid_shape%@AE@%, the program frames each window with one of the%@EH@%
  9132. following procedures:%@NL@%
  9133. %@NL@%
  9134. %@AS@%     _Rectangle( _GBorder, 0, 0, halfx -1, halfy -1 );%@NL@%
  9135. %@AS@%     _Rectangle_w( _GBorder, -3.0, -3.0, 3.0, 3.0 );%@NL@%
  9136. %@AS@%     _Rectangle_wxy( _GBorder, upleft, botright );%@NL@%
  9137. %@NL@%
  9138. %@CR:MQPD4459@%%@4@%All three procedures contain a fill flag as the first argument. The%@EH@%
  9139. procedure %@AB@%_Rectangle%@AE@% takes integer arguments that refer to the viewport
  9140. screen coordinates. The procedure %@AB@%_Rectangle_w%@AE@% takes four double-precision,
  9141. floating-point values referring to window coordinates: upper left %@AI@%x%@AE@%, upper
  9142. left %@AI@%y%@AE@%, lower right %@AI@%x%@AE@%, and lower right %@AI@%y%@AE@%. The procedure %@AB@%_Rectangle_wxy%@AE@%
  9143. takes two arguments: the addresses of structures of type %@AB@%_WXYCoord%@AE@%, which
  9144. contains two %@AB@%Double%@AE@% types named %@AB@%wx%@AE@% and %@AB@%wy%@AE@%. The structure is defined in the
  9145. %@AB@%MSGraph%@AE@% unit. The values are assigned just before %@AB@%_Rectangle_wxy%@AE@% is called.%@NL@%
  9146. %@NL@%
  9147. %@CR:MQPD4460@%%@4@%%@AB@%Drawing Graphics%@AE@%%@EH@%%@NL@%
  9148. %@NL@%
  9149. %@CR:MQPD4461@%%@4@%The %@AS@%grid_shape%@AE@% procedure is shown here:%@EH@%%@NL@%
  9150. %@NL@%
  9151. %@AS@%     PROCEDURE grid_shape;%@NL@%
  9152. %@AS@%     VAR%@NL@%
  9153. %@AS@%         i, x1, y1, x2, y2  : Integer;%@NL@%
  9154. %@AS@%         x, y               : Real;%@NL@%
  9155. %@AS@%         s                  : STRING[80];%@NL@%
  9156. %@AS@%     BEGIN%@NL@%
  9157. %@NL@%
  9158. %@AS@%         FOR i := 1 TO vc.NumColors DO%@NL@%
  9159. %@AS@%             BEGIN%@NL@%
  9160. %@AS@%             _SetTextPosition( i, 2 );%@NL@%
  9161. %@AS@%             _SetTextColor( i );%@NL@%
  9162. %@AS@%             Str( i, s );%@NL@%
  9163. %@AS@%             _OutText( 'Color ' + s );%@NL@%
  9164. %@AS@%             END;%@NL@%
  9165. %@NL@%
  9166. %@AS@%         _SetColor( 1 );%@NL@%
  9167. %@AS@%         _Rectangle_w( _GBorder, -1.0,  -1.0,  1.0,  1.0  );%@NL@%
  9168. %@AS@%         _Rectangle_w( _GBorder, -1.02, -1.02, 1.02, 1.02 );%@NL@%
  9169. %@NL@%
  9170. %@AS@%         x := -0.9;%@NL@%
  9171. %@AS@%         i :=  0;%@NL@%
  9172. %@AS@%         WHILE  x  0.9 DO%@NL@%
  9173. %@AS@%             BEGIN%@NL@%
  9174. %@AS@%             _SetColor( 2 );%@NL@%
  9175. %@AS@%             _MoveTo_w( x, -1.0 );   _LineTo_w( x, 1.0 );%@NL@%
  9176. %@AS@%             _MoveTo_w( -1.0, x );   _LineTo_w( 1.0, x );%@NL@%
  9177. %@AS@%             _SetColor( 3 );%@NL@%
  9178. %@AS@%             _MoveTo_w( x - 0.1, bananas[i] );%@NL@%
  9179. %@AS@%             Inc( i );%@NL@%
  9180. %@AS@%             _LineTo_w( x, bananas[i] );%@NL@%
  9181. %@AS@%             x := x + 0.1;%@NL@%
  9182. %@AS@%             END;%@NL@%
  9183. %@NL@%
  9184. %@AS@%         _MoveTo_w( 0.9, bananas[i] );%@NL@%
  9185. %@AS@%         Inc(i);%@NL@%
  9186. %@AS@%         _LineTo_w( 1.0, bananas[i] );%@NL@%
  9187. %@AS@%         END;%@NL@%
  9188. %@NL@%
  9189. %@CR:MQPD4462@%%@4@%First, the number of available color indexes is assigned to the %@AS@%numc%@AE@%%@EH@%
  9190. variable and a loop displays all of the available colors:%@NL@%
  9191. %@NL@%
  9192. %@AS@%     FOR i := 1 TO numc DO%@NL@%
  9193. %@NL@%
  9194. %@AS@%         BEGIN%@NL@%
  9195. %@AS@%         _SetTextPosition( i, 2 );%@NL@%
  9196. %@AS@%         _SetTextColor( i );%@NL@%
  9197. %@AS@%         Str(i, s);%@NL@%
  9198. %@AS@%         _OutText( 'Color ' + s );%@NL@%
  9199. %@AS@%         END;%@NL@%
  9200. %@NL@%
  9201. %@CR:MQPD4463@%%@4@%The names of the procedures are self-      explanatory. The advantage of using%@EH@%
  9202. %@AB@%_OutText%@AE@% in graphics mode is that you can control the text color and limit
  9203. output to the currently defined text window.%@NL@%
  9204. %@NL@%
  9205. %@CR:MQPD4464@%%@4@%The procedure and function names that end with %@AB@%_w%@AE@% work the same as their%@EH@%
  9206. viewport equivalents, except you pass double-precision, floating-point
  9207. values instead of integers. For example, you pass integers to %@AB@%_LineTo%@AE@% but
  9208. floating-point values to %@AB@%_LineTo_w.%@AE@%%@NL@%
  9209. %@NL@%
  9210. %@NL@%
  9211. %@CR:MQPD5000@%%@2@%%@AB@%13.5  Animation%@AE@%%@EH@%%@NL@%
  9212. %@NL@%
  9213. %@CR:MQPD5001@%%@4@%The QuickPascal %@AB@%MSGraph%@AE@% unit provides several functions that can be used to%@EH@%
  9214. animate your graphics programs. These functions provide two means of
  9215. animation:%@NL@%
  9216. %@NL@%
  9217. %@CR:MQPD5002@%  1. Video-page animation (also used in text modes)%@NL@%
  9218. %@NL@%
  9219.   2. Bit-mapped animation%@NL@%
  9220. %@NL@%
  9221. %@CR:MQPD5003@%%@4@%"Video-page animation" takes advantage of the fact that the EGA, VGA, and%@EH@%
  9222. Hercules video cards have enough memory to store more than one video
  9223. display page. You can animate by switching between the pages. "Bit-mapped
  9224. animation" captures bit-mapped images of the screen and then stores them in
  9225. a memory buffer. These images can be redisplayed at a new location to
  9226. perform animation.%@NL@%
  9227. %@NL@%
  9228. %@CR:MQPD5004@%%@4@%This section discusses these two animation techniques and shows two sample%@EH@%
  9229. programs that bring your graphics to life.%@NL@%
  9230. %@NL@%
  9231. %@NL@%
  9232. %@CR:MQPD5100@%%@3@%%@AB@%13.5.1  Video-Page Animation%@AE@%%@EH@%%@NL@%
  9233. %@NL@%
  9234. %@CR:MQPD5101@%%@4@%Most video adapters contain enough memory so that more than one display page%@EH@%
  9235. can be stored at a time. The %@AB@%MSGraph%@AE@% unit provides several functions that
  9236. allow you to manipulate these video pages. Two terms are used to describe
  9237. these pages──the "active page" is the page where text and graphics commands
  9238. operate; the "visual page" is the page that you see displayed.%@NL@%
  9239. %@NL@%
  9240. %@CR:MQPD5102@%%@4@%The number of video pages available in an adapter depends on the amount of%@EH@%
  9241. video memory on the adapter and the mode in which the adapter is used. For
  9242. example, the CGA adapter with 16K of video memory supports four video pages
  9243. in the text mode %@AB@%_TextC80%@AE@%. An EGA adapter with a full 256K of video memory
  9244. has room for two video pages even in the high resolution %@AB@%_EResColor%@AE@% mode.
  9245. Virtually all adapters provide for multiple pages in text modes; only the
  9246. EGA and VGA adapters with 256K of video memory support two video pages in
  9247. the high-resolution graphics modes. The Hercules graphics mode (%@AB@%_HercMono%@AE@%)
  9248. can support two pages, but only if it is the only graphics adapter present
  9249. and only when MSHERC.COM is started without the /H option.%@NL@%
  9250. %@NL@%
  9251. %@CR:MQPD5103@%%@4@%Use the procedure %@AB@%_GetVideoConfig%@AE@% to obtain information about the video%@EH@%
  9252. configuration. After calling %@AB@%_GetVideoConfig%@AE@%, use the %@AB@%NumVideoPages%@AE@% element
  9253. of the %@AB@%_VideoConfig%@AE@% structure to determine the number of video pages
  9254. supported.%@NL@%
  9255. %@NL@%
  9256. %@CR:MQPD5104@%%@4@%A simple use of video pages is to draw graphics offscreen (on the active%@EH@%
  9257. page) and then make this active page the visual page. In this way, you do
  9258. not see the process of creating the graphics; you only see the final result.
  9259. This process of drawing offscreen and then switching can be extended to
  9260. provide animation.%@NL@%
  9261. %@NL@%
  9262. %@CR:MQPD5105@%%@4@%The procedure %@AB@%_SetVisualPage%@AE@% changes the page that you see. The procedure %@EH@%
  9263. %@AB@%_SetActivePage%@AE@% changes the page where drawing takes place. The first page in
  9264. any graphics system is number 0, the second is number 1, and so on. A
  9265. corresponding set of functions %@AB@%_GetActivePage%@AE@% and %@AB@%_GetVisualPage%@AE@% return the
  9266. value of the current active or visual page, respectively.%@NL@%
  9267. %@NL@%
  9268. %@CR:MQPD5106@%%@4@%To animate any sequence of screens using video-page animation, use the%@EH@%
  9269. following steps:%@NL@%
  9270. %@NL@%
  9271. %@CR:MQPD5107@%  1. Perform regular graphics initialization (select video mode, check for%@NL@%
  9272.      error, and so on).%@NL@%
  9273. %@NL@%
  9274.   2. Draw on the active page.%@NL@%
  9275. %@NL@%
  9276.   3. Swap the visual and active pages.%@NL@%
  9277. %@NL@%
  9278.   4. Repeat steps 2 and 3 until finished with animation.%@NL@%
  9279. %@NL@%
  9280.   5. Restore the screen and exit the program.%@NL@%
  9281. %@NL@%
  9282. %@CR:MQPD5108@%%@4@%The example program PAGES.PAS uses four video pages to animate a simple set%@EH@%
  9283. of character images in text mode.%@NL@%
  9284. %@NL@%
  9285. %@AS@%     PROGRAM page_animation;%@NL@%
  9286. %@AS@%     { PAGES.PAS: Use video pages to animate screens }%@NL@%
  9287. %@NL@%
  9288. %@AS@%     USES%@NL@%
  9289. %@AS@%         MSGraph, Crt;%@NL@%
  9290. %@NL@%
  9291. %@AS@%     CONST%@NL@%
  9292. %@AS@%         jumper   :  ARRAY[0..3] OF STRING =%@NL@%
  9293. %@AS@%                  ('/O\',  '-O-', '\O/', 'WOW');%@NL@%
  9294. %@AS@%     VAR%@NL@%
  9295. %@AS@%         a, i     :  Integer;%@NL@%
  9296. %@AS@%         oldvpage :  Integer;%@NL@%
  9297. %@AS@%         oldapage :  Integer;%@NL@%
  9298. %@AS@%         vc : _VideoConfig;%@NL@%
  9299. %@AS@%         oldcursor : Boolean;%@NL@%
  9300. %@NL@%
  9301. %@AS@%     BEGIN  { Begin main program }%@NL@%
  9302. %@NL@%
  9303. %@AS@%         _ClearScreen( _GClearScreen);%@NL@%
  9304. %@NL@%
  9305. %@AS@%         oldapage  := _GetActivePage;%@NL@%
  9306. %@AS@%         oldvpage  := _GetVisualPage;%@NL@%
  9307. %@NL@%
  9308. %@AS@%         { Set the video mode for a large text size }%@NL@%
  9309. %@AS@%         a := _SetVideoModeRows( _TextBW40, 25 );%@NL@%
  9310. %@AS@%         _GetVideoConfig( vc );%@NL@%
  9311. %@NL@%
  9312. %@AS@%         IF ((a = 0) OR (vc.NumVideoPages < 4)) THEN%@NL@%
  9313. %@AS@%           BEGIN%@NL@%
  9314. %@AS@%           Writeln( '_TEXTBW40 mode not available; hit Return to continue');%@NL@%
  9315. %@AS@%           Readln;%@NL@%
  9316. %@AS@%           a := _SetVideoMode( _DefaultMode );%@NL@%
  9317. %@AS@%           Halt( 0 );%@NL@%
  9318. %@AS@%           END;%@NL@%
  9319. %@NL@%
  9320. %@AS@%         { Turn off flashing cursor. }%@NL@%
  9321. %@AS@%         oldcursor := _DisplayCursor( False );%@NL@%
  9322. %@NL@%
  9323. %@AS@%         { Draw image on each page. }%@NL@%
  9324. %@AS@%         FOR i := 0 TO 3 DO%@NL@%
  9325. %@AS@%             BEGIN%@NL@%
  9326. %@AS@%             _SetActivePage( i );%@NL@%
  9327. %@AS@%             _SetTextPosition( 12, 20 );%@NL@%
  9328. %@AS@%             _OutText( jumper[i] );%@NL@%
  9329. %@AS@%             END;%@NL@%
  9330. %@NL@%
  9331. %@AS@%         { Cycle through pages 0 to 3. }%@NL@%
  9332. %@AS@%         REPEAT%@NL@%
  9333. %@AS@%             FOR i := 0 TO 3 DO%@NL@%
  9334. %@AS@%                 BEGIN%@NL@%
  9335. %@AS@%                 _SetVisualPage( i );%@NL@%
  9336. %@AS@%                 Delay( 500 );%@NL@%
  9337. %@AS@%                 END;%@NL@%
  9338. %@AS@%         UNTIL KeyPressed;%@NL@%
  9339. %@NL@%
  9340. %@AS@%         { Restore everything before ending the program. }%@NL@%
  9341. %@AS@%         a := _SetVideoMode( _DefaultMode );%@NL@%
  9342. %@AS@%         _SetActivePage( oldapage );%@NL@%
  9343. %@AS@%         _SetVisualPage( oldvpage );%@NL@%
  9344. %@NL@%
  9345. %@AS@%     END.%@NL@%
  9346. %@NL@%
  9347. %@CR:MQPD5109@%%@4@%The program PAGES.PAS begins with a call to %@AB@%_ClearScreen%@AE@% and then sets the%@EH@%
  9348. video mode using the %@AB@%_SetVideoModeRows%@AE@% function. The cursor is turned off
  9349. with the %@AB@%_DisplayCursor%@AE@% function.%@NL@%
  9350. %@NL@%
  9351. %@CR:MQPD510A@%%@4@%The %@AB@%FOR%@AE@% loop draws a graphics image on each of four pages. The loop goes to%@EH@%
  9352. each of the video pages and outputs the graphics image using the %@AB@%_OutText%@AE@%
  9353. procedure. When you run this program, notice that you don't see any of this
  9354. activity. Since the drawing is taking place on the active pages, it is not
  9355. visible on the screen (the visual page).%@NL@%
  9356. %@NL@%
  9357. %@CR:MQPD510B@%%@4@%Once the pages have been drawn, the %@AB@%REPEAT%@AE@% loop cycles through each page and%@EH@%
  9358. makes it the visual page (so you can see it) and then delays 500
  9359. milliseconds between calls to %@AB@%_SetVisualPage%@AE@%.%@NL@%
  9360. %@NL@%
  9361. %@CR:MQPD510C@%%@4@%Finally, when a key is pressed, the program ends by restoring the video mode%@EH@%
  9362. to %@AB@%_DefaultMode%@AE@% using the %@AB@%_SetVideoMode%@AE@% function.%@NL@%
  9363. %@NL@%
  9364. %@NL@%
  9365. %@CR:MQPD5200@%%@3@%%@AB@%13.5.2  Bit-Mapped Animation%@AE@%%@EH@%%@NL@%
  9366. %@NL@%
  9367. %@CR:MQPD5201@%%@4@%Bit-mapped animation gives you the ability to draw graphics figures and%@EH@%
  9368. store them in memory for later use in animation. The %@AB@%_ImageSize%@AE@% function
  9369. determines the amount of memory required to store a specified bit-mapped
  9370. image. The image is specified in terms of a bounding rectangle. The
  9371. %@AB@%_GetImage%@AE@% procedure copies the bit map of pixels inside a specified
  9372. rectangle to a buffer area in memory. The %@AB@%_PutImage%@AE@% procedure copies a
  9373. bit-mapped image from a memory buffer to the screen at a location specified
  9374. by the program.%@NL@%
  9375. %@NL@%
  9376. %@CR:MQPD5202@%%@4@%The %@AB@%_PutImage%@AE@% procedure uses a %@AI@%CopyMode%@AE@% argument to control how the stored%@EH@%
  9377. image interacts with what is already on the screen. The %@AI@%CopyMode%@AE@% argument
  9378. specifies one of the following screen display operations:%@NL@%
  9379. %@NL@%
  9380. %@CR:MQPD5203@%%@AB@%Constant                    Action     %@AE@%%@NL@%
  9381. %@NL@%
  9382. %@AB@%_Gand%@AE@%                       Logical AND of the transfer image and screen%@NL@%
  9383.                             image%@NL@%
  9384. %@NL@%
  9385. %@AB@%_Gor%@AE@%                        Superimposition of the transfer image onto the%@NL@%
  9386.                             existing screen image%@NL@%
  9387. %@NL@%
  9388. %@AB@%_GPReset%@AE@%                    Direct transfer from memory to screen; color%@NL@%
  9389.                             inverted%@NL@%
  9390. %@NL@%
  9391. %@AB@%_GPSet%@AE@%                      Direct transfer from memory to screen%@NL@%
  9392. %@NL@%
  9393. %@AB@%_Gxor%@AE@%                       Screen inversion only where a point exists in%@NL@%
  9394.                             the transfer image%@NL@%
  9395. %@NL@%
  9396. %@CR:MQPD5204@%%@4@%The two %@AI@%CopyMode%@AE@% arguments best suited for animation are %@AB@%_Gxor%@AE@% and %@AB@%_GPSet%@AE@%.%@EH@%%@NL@%
  9397. %@NL@%
  9398. %@CR:MQPD5205@%%@4@%Animation done using %@AB@%_GPSet%@AE@% is faster, but erases the screen background. In%@EH@%
  9399. contrast, %@AB@%_Gxor%@AE@% is slower, but preserves the screen background.%@NL@%
  9400. %@NL@%
  9401. %@CR:MQPD5206@%%@4@%Animation with %@AB@%_Gxor%@AE@% is done with the following four steps:%@EH@%%@NL@%
  9402. %@NL@%
  9403. %@CR:MQPD5207@%  1. Put the object on the screen with %@AB@%_Gxor%@AE@%.%@NL@%
  9404. %@NL@%
  9405.   2. Calculate the new position of the object.%@NL@%
  9406. %@NL@%
  9407.   3. Put the object on the screen a second time at the old location, using%@NL@%
  9408.      %@AB@%_Gxor%@AE@% again──this time to remove the old image.%@NL@%
  9409. %@NL@%
  9410.   4. Go to step 1, but this time put the object at the new location.%@NL@%
  9411. %@NL@%
  9412. %@CR:MQPD5208@%%@4@%Movement done with these four steps leaves the background unchanged after%@EH@%
  9413. step 3. Flicker can be reduced by minimizing the time between steps 4 and 1,
  9414. and by making sure that there is enough time delay between steps 1 and 3. If
  9415. more than one object is being animated, every object should be processed at
  9416. once, one step at a time.%@NL@%
  9417. %@NL@%
  9418. %@CR:MQPD5209@%%@4@%If it is not important to preserve the background, animation can be%@EH@%
  9419. performed using the %@AB@%_GPSet%@AE@% option. If the border of the bounding rectangle
  9420. around the image is as large as or larger than the maximum distance the
  9421. object will move, then each time the image is put in a new location, the
  9422. border will erase all traces of the image in the old location.%@NL@%
  9423. %@NL@%
  9424. %@CR:MQPD5210@%%@4@%%@AB@%Using Bit-Mapped Images%@AE@%%@EH@%%@NL@%
  9425. %@NL@%
  9426. %@CR:MQPD5211@%%@4@%The process of animating using bit-mapped images follows these eight steps:%@EH@%%@NL@%
  9427. %@NL@%
  9428. %@CR:MQPD5212@%  1. Perform regular graphics initialization (select graphics mode, check%@NL@%
  9429.      for error, and so on).%@NL@%
  9430. %@NL@%
  9431.   2. Draw the graphics image using the %@AB@%MSGraph%@AE@% unit procedures and%@NL@%
  9432.      functions.%@NL@%
  9433. %@NL@%
  9434.   3. Use the %@AB@%_ImageSize%@AE@% function to determine the amount of memory required%@NL@%
  9435.      to store the image.%@NL@%
  9436. %@NL@%
  9437.   4. Use the %@AB@%GetMem%@AE@% procedure to allocate the amount of memory needed (as%@NL@%
  9438.      found in step 2).%@NL@%
  9439. %@NL@%
  9440.   5. Call %@AB@%_GetImage%@AE@% to copy the bit map of pixels from the screen to the%@NL@%
  9441.      memory buffer created in step 3.%@NL@%
  9442. %@NL@%
  9443.   6. Call %@AB@%_PutImage%@AE@% to display the image stored in memory. This display can%@NL@%
  9444.      be at any location on the screen.%@NL@%
  9445. %@NL@%
  9446.   7. Repeat steps 3 through 6 (possibly with different images) until%@NL@%
  9447.      finished with animation.%@NL@%
  9448. %@NL@%
  9449.   8. Restore the screen and exit the program.%@NL@%
  9450. %@NL@%
  9451. %@CR:MQPD5220@%%@4@%%@AB@%An Example of Bit-Mapped Animation%@AE@%%@EH@%%@NL@%
  9452. %@NL@%
  9453. %@CR:MQPD5221@%%@4@%The program ANIMATE.PAS demonstrates this process, drawing a rectangle and%@EH@%
  9454. then redisplaying it at random locations on the screen.%@NL@%
  9455. %@NL@%
  9456. %@AS@%     PROGRAM Animate;%@NL@%
  9457. %@AS@%     { ANIMATE.PAS: Demonstrates animation using image buffers }%@NL@%
  9458. %@NL@%
  9459. %@AS@%     USES%@NL@%
  9460. %@AS@%         MSGraph, Crt;%@NL@%
  9461. %@NL@%
  9462. %@AS@%     CONST%@NL@%
  9463. %@AS@%         max_buffer = 65520;%@NL@%
  9464. %@NL@%
  9465. %@AS@%     VAR%@NL@%
  9466. %@AS@%         q      : Integer;%@NL@%
  9467. %@AS@%         vc     : _VideoConfig;%@NL@%
  9468. %@AS@%         buffer : POINTER;%@NL@%
  9469. %@AS@%         imsize : LongInt;%@NL@%
  9470. %@AS@%         x0, y0 : Integer;%@NL@%
  9471. %@AS@%         x, y   : Integer;%@NL@%
  9472. %@NL@%
  9473. %@AS@%     BEGIN  { Begin main program. }%@NL@%
  9474. %@NL@%
  9475. %@AS@%         _ClearScreen( _GClearScreen);%@NL@%
  9476. %@NL@%
  9477. %@AS@%         { Set the video mode and check for success }%@NL@%
  9478. %@AS@%         q := _SetVideoMode( _MaxResMode );%@NL@%
  9479. %@AS@%         IF (q = 0) THEN%@NL@%
  9480. %@AS@%             BEGIN%@NL@%
  9481. %@AS@%             Writeln( 'Graphics mode unavailable; hit Return to continue' );%@NL@%
  9482. %@AS@%             Readln;%@NL@%
  9483. %@AS@%             q := _SetVideoMode( _DefaultMode );%@NL@%
  9484. %@AS@%             Halt( 0 );%@NL@%
  9485. %@AS@%             END;%@NL@%
  9486. %@NL@%
  9487. %@AS@%         { Find out some screen characteristics. }%@NL@%
  9488. %@AS@%         _GetVideoConfig( vc );%@NL@%
  9489. %@NL@%
  9490. %@AS@%         { Draw and store a simple figure. }%@NL@%
  9491. %@AS@%         _SetColor( 3 );%@NL@%
  9492. %@AS@%         x := vc.NumXPixels DIV 4;%@NL@%
  9493. %@AS@%         y := vc.NumYPixels DIV 4;%@NL@%
  9494. %@NL@%
  9495. %@AS@%         _Rectangle( _GFillInterior, 0, 0, x, y );%@NL@%
  9496. %@AS@%         imsize := _ImageSize( 0, 0, x, y );%@NL@%
  9497. %@AS@%         IF (imsize > max_buffer) THEN%@NL@%
  9498. %@AS@%             BEGIN%@NL@%
  9499. %@AS@%             Writeln( 'Image too big.' );%@NL@%
  9500. %@AS@%             Readln;%@NL@%
  9501. %@AS@%             Halt( 0 );%@NL@%
  9502. %@AS@%             END%@NL@%
  9503. %@AS@%         ELSE%@NL@%
  9504. %@AS@%             BEGIN%@NL@%
  9505. %@AS@%             GetMem( buffer, imsize );%@NL@%
  9506. %@AS@%             IF (buffer = NIL) THEN%@NL@%
  9507. %@AS@%                 BEGIN%@NL@%
  9508. %@AS@%                 Writeln( 'Not enough heap memory.' );%@NL@%
  9509. %@AS@%                 Readln;%@NL@%
  9510. %@AS@%                 Halt( 0 );%@NL@%
  9511. %@AS@%                 END;%@NL@%
  9512. %@AS@%             END;%@NL@%
  9513. %@NL@%
  9514. %@AS@%         _GetImage( 0, 0, x, y, buffer^ );%@NL@%
  9515. %@AS@%         _ClearScreen( _GClearScreen );%@NL@%
  9516. %@NL@%
  9517. %@AS@%         { Draw axes centered on the screen }%@NL@%
  9518. %@AS@%         _SetColor (2);%@NL@%
  9519. %@AS@%         x0 := vc.NumXPixels DIV 2 -1;%@NL@%
  9520. %@AS@%         y0 := vc.NumYPixels DIV 2 -1;%@NL@%
  9521. %@AS@%         _MoveTo ( x0 ,0);%@NL@%
  9522. %@AS@%         _LineTo( x0, vc.NumYPixels );%@NL@%
  9523. %@AS@%         _MoveTo( 0, y0 );%@NL@%
  9524. %@AS@%         _LineTo( vc.NumXPixels, y0 );%@NL@%
  9525. %@NL@%
  9526. %@AS@%         _SetTextPosition(1,1);%@NL@%
  9527. %@AS@%         _OutText( '_Gxor');%@NL@%
  9528. %@AS@%         WHILE NOT KeyPressed DO%@NL@%
  9529. %@AS@%             BEGIN%@NL@%
  9530. %@AS@%             _PutImage( Random( vc.NumXPixels - x ),%@NL@%
  9531. %@AS@%                       Random( vc.NumYPixels - y ), buffer^, _Gxor );%@NL@%
  9532. %@AS@%             Delay( 500 );%@NL@%
  9533. %@AS@%             END;%@NL@%
  9534. %@NL@%
  9535. %@AS@%         _ClearScreen( _GClearScreen );%@NL@%
  9536. %@AS@%         q := _SetVideoMode( _DefaultMode );%@NL@%
  9537. %@AS@%     END.%@NL@%
  9538. %@NL@%
  9539. %@CR:MQPD5230@%%@4@%%@AB@%Initializing Graphics and Drawing the Image%@AE@%%@EH@%%@NL@%
  9540. %@NL@%
  9541. %@CR:MQPD5231@%%@4@%The ANIMATE.PAS program begins by clearing the screen, initializing the%@EH@%
  9542. random-number generator, and setting the video mode to the highest
  9543. resolution possible.%@NL@%
  9544. %@NL@%
  9545. %@CR:MQPD5232@%%@4@%The following code fragment draws and stores a simple image:%@EH@%%@NL@%
  9546. %@NL@%
  9547. %@AS@%        { Draw and store a simple figure. }%@NL@%
  9548. %@AS@%         _SetColor( 3 );%@NL@%
  9549. %@AS@%         x := vc.NumXPixels DIV 4;%@NL@%
  9550. %@AS@%         y := vc.NumYPixels DIV 4;%@NL@%
  9551. %@NL@%
  9552. %@AS@%         _Rectangle( _GFillInterior, 0, 0, x, y );%@NL@%
  9553. %@AS@%         imsize := _ImageSize( 0, 0, x, y );%@NL@%
  9554. %@AS@%         IF (imsize > max_buffer) THEN%@NL@%
  9555. %@AS@%             BEGIN%@NL@%
  9556. %@AS@%             Writeln( 'Image too big.' );%@NL@%
  9557. %@AS@%             Readln;%@NL@%
  9558. %@AS@%             Halt( 0 );%@NL@%
  9559. %@AS@%             END%@NL@%
  9560. %@AS@%         ELSE%@NL@%
  9561. %@AS@%             BEGIN%@NL@%
  9562. %@AS@%             GetMem( buffer, imsize );%@NL@%
  9563. %@AS@%             IF (buffer = NIL) THEN%@NL@%
  9564. %@AS@%                 BEGIN%@NL@%
  9565. %@AS@%                 Writeln( 'Not enough heap memory.' );%@NL@%
  9566. %@AS@%                 Readln;%@NL@%
  9567. %@AS@%                 Halt( 0 );%@NL@%
  9568. %@AS@%                 END;%@NL@%
  9569. %@AS@%             END;%@NL@%
  9570. %@NL@%
  9571. %@AS@%         _GetImage( 0, 0, x, y, buffer^ );%@NL@%
  9572. %@AS@%         _ClearScreen( _GClearScreen );%@NL@%
  9573. %@NL@%
  9574. %@4@%%@AB@%Allocating Memory%@AE@%%@EH@%%@NL@%
  9575. %@NL@%
  9576. %@4@%The %@AB@%_Rectangle%@AE@% procedure draws a rectangle that is about one-sixteenth the%@EH@%
  9577. size of the screen. The %@AB@%_ImageSize%@AE@% function uses the same bounding rectangle
  9578. measurements to determine the amount of memory required to hold this figure.
  9579. The %@AB@%GetMem%@AE@% procedure then allocates the necessary memory space for the
  9580. image. Because %@AB@%GetMem%@AE@% can allocate at most 65,520 bytes (64K-16), you must
  9581. check the image size before requesting the buffer. If the image is larger
  9582. than 65,520 bytes, you will need to allocate additional buffers and copy
  9583. part of the image to each buffer.%@NL@%
  9584. %@NL@%
  9585. %@CR:MQPD5222@%%@4@%The %@AB@%_GetImage%@AE@% procedure copies the image from the screen and stores it into%@EH@%
  9586. the memory area specified by %@AS@%buffer%@AE@%. Finally, the %@AB@%_ClearScreen%@AE@% procedure
  9587. clears this image off the screen. A more complex program could make use of
  9588. the active and visual pages discussed in the previous section so that the
  9589. image is drawn on the active page and the %@AB@%_ClearScreen%@AE@% procedure is not
  9590. needed.%@NL@%
  9591. %@NL@%
  9592. %@CR:MQPD5223@%%@4@%Next, the program draws a coordinate axis centered on the screen. This will%@EH@%
  9593. clarify later how the stored image interacts with images already displayed
  9594. on the screen.%@NL@%
  9595. %@NL@%
  9596. %@4@%%@AB@%Displaying the Image%@AE@%%@EH@%%@NL@%
  9597. %@NL@%
  9598. %@4@%The program then repeatedly calls %@AB@%_PutImage%@AE@% to display the stored image at%@EH@%
  9599. random locations on the screen. The process ends when a key is pressed. Once
  9600. a key is pressed, the program ends with a call to restore the video mode.%@NL@%
  9601. %@NL@%
  9602. %@AS@%         WHILE NOT KeyPressed DO%@NL@%
  9603. %@AS@%             BEGIN%@NL@%
  9604. %@AS@%             _PutImage( Random( vc.NumXPixels - x ),%@NL@%
  9605. %@AS@%                  Random( vc.NumYPixels - y ), buffer^, _Gxor );%@NL@%
  9606. %@AS@%             Delay( 500 );%@NL@%
  9607. %@AS@%             END;%@NL@%
  9608. %@NL@%
  9609. %@AS@%         _ClearScreen( _GClearScreen );%@NL@%
  9610. %@AS@%         q := _SetVideoMode( _DefaultMode );%@NL@%
  9611. %@AS@%     END.%@NL@%
  9612. %@NL@%
  9613. %@4@%The %@AB@%_PutImage%@AE@% procedure takes four arguments. The first two specify the %@AI@%x%@AE@%%@EH@%
  9614. and %@AI@%y%@AE@% coordinates of the upper left corner where the image is to be
  9615. displayed from the memory buffer. The third argument specifies the memory
  9616. buffer created by %@AB@%GetMem%@AE@% and used by %@AB@%_GetImage%@AE@% to store the bit map.
  9617. Finally, the last argument specifies the interaction between the stored
  9618. image and the currently displayed image. Notice that in this case (using the
  9619. %@AB@%_Gxor%@AE@% argument) that the image is inverted when it overlaps a currently
  9620. displayed figure (like the axes or another rectangle).%@NL@%
  9621. %@NL@%
  9622. %@NL@%
  9623. %@CR:MQPE0000@%%@1@%%@AB@%Chapter 14  Using Fonts%@AE@%%@EH@%%@NL@%
  9624. ───────────────────────────────────────────────────────────────────────────%@NL@%
  9625. %@NL@%
  9626. %@CR:MQPE0001@%%@4@%You can write QuickPascal programs that generate graphics and display text.%@EH@%
  9627. In any graphics image, QuickPascal can display various styles and sizes of
  9628. type. These collections of stylized text characters are called "fonts."
  9629. Fonts are simple to learn and easy to use. Yet they can add a touch of
  9630. polish to your program.%@NL@%
  9631. %@NL@%
  9632. %@CR:MQPE0002@%%@4@%This chapter explains how to use fonts. It assumes you have already read%@EH@%
  9633. Chapter 13%@BO:   5dac7@%, "Using Graphics." You should understand such terms as "graphics
  9634. mode" and "text mode," and be familiar with such procedures as %@AB@%_SetVideoMode%@AE@%
  9635. and %@AB@%_MoveTo%@AE@%.%@NL@%
  9636. %@NL@%
  9637. %@CR:MQPE0003@%%@4@%Note that the QuickPascal fonts can be used only in graphics modes. Fonts%@EH@%
  9638. cannot be used in text modes.%@NL@%
  9639. %@NL@%
  9640. %@NL@%
  9641. %@CR:MQPE1000@%%@2@%%@AB@%14.1  Overview of QuickPascal Fonts%@AE@%%@EH@%%@NL@%
  9642. %@NL@%
  9643. %@CR:MQPE1001@%%@4@%Each font in QuickPascal consists of a typeface and several type sizes.%@EH@%%@NL@%
  9644. %@NL@%
  9645. %@CR:MQPE1002@%%@4@%"Typeface" is a printer's term that refers to the style of the displayed%@EH@%
  9646. text── Courier, for example, or Roman. The list on the following page shows
  9647. six of the typefaces available with the QuickPascal font functions.%@NL@%
  9648. %@NL@%
  9649. %@CR:MQPE1003@%%@4@%"Type size" measures the screen area occupied by individual characters. This%@EH@%
  9650. term is also borrowed from the printer's lexicon, but for our purposes, it
  9651. is specified in units of screen pixels. For example, "Courier 169" denotes
  9652. text of Courier typeface, with each character occupying a screen area of 16
  9653. vertical pixels by 9 horizontal pixels.%@NL@%
  9654. %@NL@%
  9655. %@CR:MQPE1004@%%@4@%The QuickPascal font functions use two methods to create fonts. The first%@EH@%
  9656. technique generates the typefaces Courier, Helv, and Tms Rmn through a
  9657. "bit-mapping" technique. Bit mapping defines character images with binary
  9658. data. Each bit in the map corresponds to a screen pixel. If a bit is 1, its
  9659. associated pixel is set to the current screen color. A bit value of 0 clears
  9660. the pixel. Video adapters use this same technique to display text in
  9661. graphics mode.%@NL@%
  9662. %@NL@%
  9663. %@CR:MQPE1005@%%@4@%The second method creates the remaining three type styles──Modern, Script,%@EH@%
  9664. and Roman──as "vector mapped" fonts. Vector mapping represents each
  9665. character in terms of lines and arcs. In a literal sense, vector-mapped
  9666. characters are drawn on the screen. You might think of bit-mapped characters
  9667. as being stenciled.%@NL@%
  9668. %@NL@%
  9669. %@CR:MQPE1006@%%@4@%Each method of creating fonted text has advantages and disadvantages.%@EH@%
  9670. Bit-mapped characters are formed more completely since the pixel mapping is
  9671. predetermined. However, they cannot be scaled to arbitrary sizes.
  9672. Vector-mapped text can be scaled to any size, but the characters lack the
  9673. solid appearance of the bit-mapped characters.%@NL@%
  9674. %@NL@%
  9675. %@CR:MQPE1007@%%@4@%Any function or procedure affecting the current graphics position (such as%@EH@%
  9676. the %@AB@%_MoveTo%@AE@% procedure or the %@AB@%_LineTo%@AE@% procedure) will also affect the font
  9677. display when %@AB@%_OutGText%@AE@% is called. Other routines (such as %@AB@%_SetColor%@AE@% or
  9678. %@AB@%_RemapPalette%@AE@%) that affect drawing characteristics also affect font text
  9679. output.%@NL@%
  9680. %@NL@%
  9681. %@CR:MQPE1008@%%@4@%The QuickPascal fonts appear on your screen as shown on page 216 in the%@EH@%
  9682. printed version of this book.%@NL@%
  9683. %@NL@%
  9684. %@CR:MQPE1009@%%@4@%Table 14.1%@BO:   7735c@% describes the characteristics of each font. Notice that%@EH@%
  9685. bit-mapped fonts come in preset sizes as measured in pixels. The exact size
  9686. of any font character depends on the screen resolution and display type.%@NL@%
  9687. %@NL@%
  9688. %@CR:MQPET100@%%@4@%%@AB@%Table 14.1  Typefaces and Type Sizes in QuickPascal%@AE@%%@EH@%%@NL@%
  9689. %@NL@%
  9690. %@AB@%Typeface        Mapping           Size (in Pixels)         Spacing%@AE@%%@NL@%
  9691. %@NL@%
  9692. Courier         Bit               138, 169, 2012           Fixed%@NL@%
  9693. %@NL@%
  9694. Helv            Bit               135, 167, 208            Proportional%@NL@%
  9695.                                   1315, 166, 198%@NL@%
  9696. %@NL@%
  9697. Tms Rmn         Bit               105, 126, 158            Proportional%@NL@%
  9698.                                   169, 2012, 2616%@NL@%
  9699. %@NL@%
  9700. Modern          Vector            Scaled                   Proportional%@NL@%
  9701. %@NL@%
  9702. Script          Vector            Scaled                   Proportional%@NL@%
  9703. %@NL@%
  9704. Roman           Vector            Scaled                   Proportional%@NL@%
  9705. %@NL@%
  9706. %@NL@%
  9707. %@CR:MQPE2000@%%@2@%%@AB@%14.2  Using Fonts in QuickPascal%@AE@%%@EH@%%@NL@%
  9708. %@NL@%
  9709. %@CR:MQPE2001@%%@4@%Data for both bit-mapped and vector-mapped fonts reside in files on disk. A%@EH@%
  9710. .FON extension identifies the files. The names of the .FON files indicate
  9711. their content. For example, the MODERN.FON, ROMAN.FON, and SCRIPT.FON files
  9712. hold data for the three vector-mapped fonts.%@NL@%
  9713. %@NL@%
  9714. %@CR:MQPE2002@%%@4@%The QuickPascal .FON files are identical to the font files supplied with%@EH@%
  9715. Microsoft QuickC(R), Version 2.0, as well as being identical to the .FON
  9716. files used in the Microsoft Windows operating environment. Consequently, you
  9717. can use any of the Windows .FON files with the QuickPascal font functions.
  9718. The Windows .FON files are also available for purchase separately. In
  9719. addition, several vendors offer software that create or modify .FON files,
  9720. allowing you to design your own fonts.%@NL@%
  9721. %@NL@%
  9722. %@CR:MQPE2003@%%@4@%Your programs should follow these four steps to display fonted text:%@EH@%%@NL@%
  9723. %@NL@%
  9724. %@CR:MQPE2004@%  1. Set a graphics video mode%@NL@%
  9725. %@NL@%
  9726.   2. Register fonts%@NL@%
  9727. %@NL@%
  9728.   3. Set the current font from the register%@NL@%
  9729. %@NL@%
  9730.   4. Display text using the current font%@NL@%
  9731. %@NL@%
  9732. %@CR:MQPE2005@%%@4@%Sections 14.2.1%@BO:   77ccb@%-14.2.3 describe each of the font-specific steps in detail.%@EH@%
  9733. The procedure for using video modes for graphics is discussed in Section
  9734. 13.3%@BO:   63072@%. An example program in the final section of this chapter demonstrates
  9735. how to display the various fonts available in the QuickPascal .FON files.%@NL@%
  9736. %@NL@%
  9737. %@NL@%
  9738. %@CR:MQPE2100@%%@3@%%@AB@%14.2.1  Registering Fonts%@AE@%%@EH@%%@NL@%
  9739. %@NL@%
  9740. %@CR:MQPE2101@%%@4@%The fonts you plan to use must be organized into a list in memory, a process%@EH@%
  9741. called "registering." The register list contains information about the
  9742. available .FON files. You register fonts by calling the function
  9743. %@AB@%_RegisterFonts%@AE@%. This function reads header information from the specified
  9744. .FON files. It builds a list of file information but does not read mapping
  9745. data from the files.%@NL@%
  9746. %@NL@%
  9747. %@CR:MQPE2102@%%@4@%The %@AB@%MSGraph%@AE@% unit defines the %@AB@%_RegisterFonts%@AE@% function as%@EH@%%@NL@%
  9748. %@NL@%
  9749.      %@AI@%Function%@AE@% %@AB@%_RegisterFonts( %@AE@%%@AI@%PathName%@AE@% %@AB@%: CSTRING ) : %@AE@%%@AI@%Integer%@AE@%%@NL@%
  9750. %@NL@%
  9751. %@CR:MQPE2103@%%@4@%The argument %@AI@%PathName%@AE@% is a string containing a file name. The file name is%@EH@%
  9752. the name of the .FON file for the desired font. The file name can include
  9753. wild cards, allowing you to register several fonts with one call to
  9754. %@AB@%_RegisterFonts%@AE@%. For example, the function call below registers all of the
  9755. .FON files in the current directory and checks for a successful
  9756. registration:%@NL@%
  9757. %@NL@%
  9758. %@AS@%     result := _RegisterFonts( '*.FON' );%@NL@%
  9759. %@AS@%     IF (result < 0) THEN%@NL@%
  9760. %@AS@%         BEGIN%@NL@%
  9761. %@AS@%         Writeln( 'Unable to register fonts');%@NL@%
  9762. %@AS@%         Halt( 0 );%@NL@%
  9763. %@AS@%         END;%@NL@%
  9764. %@NL@%
  9765. %@AS@%     { the rest of your fonts program goes here }%@NL@%
  9766. %@NL@%
  9767. %@CR:MQPE2104@%%@4@%As illustrated above, the %@AB@%_RegisterFonts%@AE@% function returns a negative number%@EH@%
  9768. if it is unable to register any fonts or if the .FON file is corrupt. If it
  9769. successfully reads one or more .FON files, %@AB@%_RegisterFonts%@AE@% returns the number
  9770. of fonts registered.%@NL@%
  9771. %@NL@%
  9772. %@NL@%
  9773. %@CR:MQPE2200@%%@3@%%@AB@%14.2.2  Setting the Current Font%@AE@%%@EH@%%@NL@%
  9774. %@NL@%
  9775. %@CR:MQPE2201@%%@4@%To set a font as the current font, call the function %@AB@%_SetFont%@AE@%. This%@EH@%
  9776. function checks to see if the requested font is registered, then reads the
  9777. mapping data from the appropriate .FON file. A font must be registered and
  9778. marked current before your program can display text using that font.%@NL@%
  9779. %@NL@%
  9780. %@CR:MQPE2202@%%@4@%The %@AB@%MSGraph%@AE@% unit defines the %@AB@%_SetFont%@AE@% function as%@EH@%%@NL@%
  9781. %@NL@%
  9782.      %@AI@%Function%@AE@% %@AB@%_SetFont( %@AE@%%@AI@%Options%@AE@% %@AB@%: CSTRING ) :%@AE@%%@AI@%Integer%@AE@%%@NL@%
  9783. %@NL@%
  9784. %@CR:MQPE2203@%%@4@%The %@AI@%Options%@AE@% argument is a string that describes the desired characteristics%@EH@%
  9785. of the font. The string uses letter codes that describe the desired font, as
  9786. outlined here:%@NL@%
  9787. %@NL@%
  9788. %@CR:MQPE2204@%%@AB@%Option Code                 Meaning%@AE@%%@NL@%
  9789. %@NL@%
  9790. %@AB@%t'%@AE@%%@AI@%FontName%@AE@%%@AB@%'%@AE@%                 Typeface of the font in single quotes. The%@NL@%
  9791.                             %@AI@%FontName%@AE@% string is one of the following:%@NL@%
  9792. %@NL@%
  9793.                                  courier          modern
  9794.                                  helv             script
  9795.                                  tms rmn          roman%@NL@%
  9796. %@NL@%
  9797.                             Notice that the %@AI@%FontName%@AE@% string is surrounded by%@NL@%
  9798.                             a pair of two single quotes. This is necessary%@NL@%
  9799.                             to embed the %@AI@%FontName%@AE@% string within the %@AI@%Options%@AE@%%@NL@%
  9800.                             string, and Pascal uses single quotes to specify%@NL@%
  9801.                             a string. Notice the space in "tms rmn."%@NL@%
  9802. %@NL@%
  9803.                             Other products' font files use other names for %@AI@%%@AE@%%@NL@%
  9804.                             %@AI@%FontName%@AE@%. Refer to the vendor's documentation%@NL@%
  9805.                             for these names.%@NL@%
  9806. %@NL@%
  9807. %@AB@%h%@AE@%%@AI@%y%@AE@%                          Character height, where %@AI@%y%@AE@% is the height in%@NL@%
  9808.                             pixels.%@NL@%
  9809. %@NL@%
  9810. %@AB@%w%@AE@%%@AI@%x%@AE@%                          Character width, where %@AI@%x%@AE@% is the width in pixels.%@NL@%
  9811. %@NL@%
  9812. %@AB@%f%@AE@%                           Select only a fixed-spaced font.%@NL@%
  9813. %@NL@%
  9814. %@AB@%p%@AE@%                           Select only a proportional-spaced font.%@NL@%
  9815. %@NL@%
  9816. %@AB@%v%@AE@%                           Select only a vector-mapped font.%@NL@%
  9817. %@NL@%
  9818. %@AB@%r%@AE@%                           Select only a bit-mapped font.%@NL@%
  9819. %@NL@%
  9820. %@AB@%b%@AE@%                           Select the best fit from the registered fonts.%@NL@%
  9821.                             This option instructs %@AB@%_SetFont%@AE@% to accept the%@NL@%
  9822.                             closest-fitting font if a font of the specified%@NL@%
  9823.                             size is not registered.%@NL@%
  9824. %@NL@%
  9825.                             If at least one font is registered, the %@AB@%b%@AE@% option%@NL@%
  9826.                             always guarantees that %@AB@%_SetFont%@AE@% will be able to%@NL@%
  9827.                             set a current font. If you do not specify the %@AB@%b%@AE@%%@NL@%
  9828.                             option and an exact matching font is not%@NL@%
  9829.                             registered, %@AB@%_SetFont%@AE@% will fail. In this case,%@NL@%
  9830.                             any existing current font remains current.%@NL@%
  9831. %@NL@%
  9832.                             The %@AB@%_SetFont%@AE@% function uses four criteria for%@NL@%
  9833.                             selecting the best fit. In descending order of%@NL@%
  9834.                             precedence the four criteria are pixel height,%@NL@%
  9835.                             typeface, pixel width, and spacing (fixed or%@NL@%
  9836.                             proportional). If you request a vector-mapped%@NL@%
  9837.                             font, %@AB@%_SetFont%@AE@% sizes the font to correspond with%@NL@%
  9838.                             the specified pixel height and width. If you%@NL@%
  9839.                             request a bit-mapped font, %@AB@%_SetFont%@AE@% chooses the%@NL@%
  9840.                             closest available size. If the requested type%@NL@%
  9841.                             size for a bit-mapped font fits exactly between%@NL@%
  9842.                             two registered fonts, the smaller size takes%@NL@%
  9843.                             precedence.%@NL@%
  9844. %@NL@%
  9845. %@AB@%n%@AE@%%@AI@%x%@AE@%                          Select font number %@AI@%x%@AE@%, where %@AI@%x%@AE@% is less than or%@NL@%
  9846.                             equal to the value returned by %@AB@%_RegisterFonts%@AE@%.%@NL@%
  9847.                             For example, the option %@AB@%n3%@AE@% makes the third%@NL@%
  9848.                             registered font current, assuming that three or%@NL@%
  9849.                             more fonts are registered.%@NL@%
  9850. %@NL@%
  9851.                             This option is primarily useful for cycling%@NL@%
  9852.                             through all registered fonts in a loop. Because%@NL@%
  9853.                             .FON files often contain several fonts, and the%@NL@%
  9854.                             files are loaded into memory in reverse order%@NL@%
  9855.                             from which they are registered, it is difficult%@NL@%
  9856.                             to know which font will be number 3.%@NL@%
  9857. %@NL@%
  9858. %@CR:MQPE2205@%%@4@%Option codes are not case-sensitive and can be listed in any order. You can%@EH@%
  9859. separate codes with spaces or any other character that is not a valid option
  9860. code. The %@AB@%_SetFont%@AE@% function ignores all invalid codes.%@NL@%
  9861. %@NL@%
  9862. %@CR:MQPE2206@%%@4@%For example, the function call below specifies that the font should be a%@EH@%
  9863. "script" typeface with a character height of 30 pixels and a character width
  9864. of 24 pixels. If the function is unable to do this, a "best fit" font is
  9865. requested. The multiple single quotes around %@AS@%script%@AE@% are required since the
  9866. entire argument used by %@AB@%_SetFont%@AE@% is a string. The double single quote
  9867. specifies to QuickPascal that the string contains a single quote.%@NL@%
  9868. %@NL@%
  9869. %@AS@%     result := _SetFont( 't''script''h30w24b' );%@NL@%
  9870. %@AS@%     IF (result =  -1) THEN%@NL@%
  9871. %@AS@%         BEGIN%@NL@%
  9872. %@AS@%         Writeln( 'Unable to set requested font');%@NL@%
  9873. %@AS@%         Halt( 0 );%@NL@%
  9874. %@AS@%         END;%@NL@%
  9875. %@NL@%
  9876. %@AS@%     Writeln( 'Font set' );%@NL@%
  9877. %@AS@%     { the rest of your font program goes here }%@NL@%
  9878. %@NL@%
  9879. %@CR:MQPE2207@%%@4@%As illustrated above, the %@AB@%_SetFont%@AE@% function returns a %@AS@%-1%@AE@% if it is unable to%@EH@%
  9880. set the requested font. If it successfully sets a current font, the value %@AS@%0%@AE@%
  9881. is returned.%@NL@%
  9882. %@NL@%
  9883. %@CR:MQPE2208@%%@4@%Once a font is set as the current font, the %@AB@%_SetFont%@AE@% function updates a data%@EH@%
  9884. area with the parameters of the current font. The data area is in the form
  9885. of a %@AB@%_FontInfo%@AE@% record, defined in the %@AB@%MSGraph%@AE@% unit as%@NL@%
  9886. %@NL@%
  9887. %@AS@%   { structure for GetFontInfo }%@NL@%
  9888. %@NL@%
  9889. %@AS@%       _FontInfo = RECORD%@NL@%
  9890. %@AS@%           fonttype  : Integer;      { b0 set = vector,clear = bit map     }%@NL@%
  9891. %@AS@%           ascent    : Integer;      { pix dist from top to baseline       }%@NL@%
  9892. %@AS@%           pixwidth  : Integer;      { character width in pixels, 0 = prop }%@NL@%
  9893. %@AS@%           pixheight : Integer;      { character height in pixels          }%@NL@%
  9894. %@AS@%           avgwidth  : Integer;      { average character width in pixels   }%@NL@%
  9895. %@AS@%           filename  : CSTRING[81];  { file name including path            }%@NL@%
  9896. %@AS@%           facename  : CSTRING[32];  { font name                           }%@NL@%
  9897. %@AS@%           END;%@NL@%
  9898. %@NL@%
  9899. %@CR:MQPE2209@%%@4@%If you wish to retrieve the parameters of the current font, call the%@EH@%
  9900. function %@AB@%_GetFontInfo%@AE@%, which is defined in the %@AB@%MSGraph%@AE@% unit as%@NL@%
  9901. %@NL@%
  9902.      %@AI@%Function%@AE@% %@AB@%_GetFontInfo( VAR %@AE@%%@AI@%FInfo%@AE@% %@AB@%: _FontInfo ) : %@AE@%%@AI@%Integer%@AE@%%@NL@%
  9903. %@NL@%
  9904. %@NL@%
  9905. %@CR:MQPE2300@%%@3@%%@AB@%14.2.3  Displaying Text Using the Current Font%@AE@%%@EH@%%@NL@%
  9906. %@NL@%
  9907. %@CR:MQPE2301@%%@4@%Now you can display the font-based text. This step consists of two parts:%@EH@%%@NL@%
  9908. %@NL@%
  9909. %@CR:MQPE2302@%  1. Select a screen position for the text with the graphics procedure%@NL@%
  9910.      %@AB@%_MoveTo%@AE@%. Note that all of the font-based text is displayed using%@NL@%
  9911.      graphics functions. Consequently, the %@AB@%_MoveTo%@AE@% procedure (rather than%@NL@%
  9912.      the text procedure %@AB@%_SetTextPosition%@AE@%) positions the text. The %@AB@%_MoveTo%@AE@%%@NL@%
  9913.      procedure takes pixel coordinates as arguments. The coordinates specify%@NL@%
  9914.      the upper left point of the first character in the text string.%@NL@%
  9915.      Optionally, you can use the procedure %@AB@%_SetGTextVector%@AE@% to change the%@NL@%
  9916.      orientation of the text on the screen.%@NL@%
  9917. %@NL@%
  9918.   2. Display the font-based text at that position with the procedure%@NL@%
  9919.      %@AB@%_OutGText%@AE@%.%@NL@%
  9920. %@NL@%
  9921. %@NL@%
  9922. %@CR:MQPE3000@%%@2@%%@AB@%14.3  A Few Hints on Using Fonts%@AE@%%@EH@%%@NL@%
  9923. %@NL@%
  9924. %@CR:MQPE3001@%%@4@%Fonted text is simply another form of graphics, and using fonts effectively%@EH@%
  9925. requires little programming effort. Still, there are a few things to watch:%@NL@%
  9926. %@NL@%
  9927. %@CR:MQPE3002@%  ■  Remember that the video mode should be set only once to establish a%@NL@%
  9928.      graphics mode. If you generate an image (as with the %@AB@%_Rectangle%@AE@%%@NL@%
  9929.      procedure) and wish to incorporate fonted text above it as a title,%@NL@%
  9930.      don't reset the video mode prior to calling the font routines. Doing so%@NL@%
  9931.      will blank the screen, destroying the original image.%@NL@%
  9932. %@NL@%
  9933.   ■  The %@AB@%_SetFont%@AE@% function reads specified .FON files to obtain mapping data%@NL@%
  9934.      for the current font. Each call to %@AB@%_SetFont%@AE@% causes a disk access and%@NL@%
  9935.      overwrites the old font data in memory. If you wish to show text of%@NL@%
  9936.      different styles on the same screen, display all of the text of one%@NL@%
  9937.      font before moving on to the others. By minimizing the number of calls%@NL@%
  9938.      to %@AB@%_SetFont%@AE@%, you'll save time spent in disk I/O and memory reloads.%@NL@%
  9939. %@NL@%
  9940.   ■  When your program finishes with the fonts, you might want to free the%@NL@%
  9941.      memory occupied by the register list. Call the %@AB@%_UnRegisterFonts%@AE@%%@NL@%
  9942.      procedure to do this. As its name implies, this procedure frees the%@NL@%
  9943.      memory previously allocated by %@AB@%_RegisterFonts%@AE@%. The register information%@NL@%
  9944.      for each type size of each font takes up approximately 140 bytes of%@NL@%
  9945.      memory. Thus the amount of memory returned by %@AB@%_UnRegisterFonts%@AE@% is%@NL@%
  9946.      significant only if you have many fonts registered.%@NL@%
  9947. %@NL@%
  9948.   ■  As for screen aesthetics, the same suggestions for the printed page%@NL@%
  9949.      apply to fonted screen text. Typefaces are more effective when they are%@NL@%
  9950.      not competing with each other for attention. Restricting the number of%@NL@%
  9951.      styles per screen to one or two generally results in a more pleasing,%@NL@%
  9952.      less cluttered image.%@NL@%
  9953. %@NL@%
  9954. %@NL@%
  9955. %@CR:MQPE4000@%%@2@%%@AB@%14.4  Example Program%@AE@%%@EH@%%@NL@%
  9956. %@NL@%
  9957. %@CR:MQPE4001@%%@4@%The QuickPascal font functions shine when they are used in conjunction with%@EH@%
  9958. your other graphics functions. They allow you to dress up any image on the
  9959. screen, yet they can make a visual impression when used by themselves, as
  9960. the example program SAMPLER.PAS illustrates. This program displays sample
  9961. text in all of the available fonts, then exits when a key is pressed. Make
  9962. sure the .FON files are in the current directory before running the program.%@NL@%
  9963. %@NL@%
  9964. %@CR:MQPE4002@%%@4@%Notice that SAMPLER.PAS calls the graphics procedure %@AB@%_MoveTo%@AE@% to establish%@EH@%
  9965. the starting position for each text string. Section 13.4%@BO:   6ac8a@% "Understanding
  9966. Coordinate Systems," describes the %@AB@%_MoveTo%@AE@% procedure. The function %@AB@%_SetFont%@AE@%
  9967. takes a character string as an argument. The string is an options list that
  9968. specifies typeface and the best fit for a character height of 30 pixels and
  9969. a width of 24 pixels.%@NL@%
  9970. %@NL@%
  9971. %@AS@%     PROGRAM sampler;  { Demonstrates using different fonts }%@NL@%
  9972. %@NL@%
  9973. %@AS@%     USES%@NL@%
  9974. %@AS@%          Crt, MSGraph;%@NL@%
  9975. %@NL@%
  9976. %@AS@%     CONST%@NL@%
  9977. %@AS@%          CRLF = #13 + #10;%@NL@%
  9978. %@AS@%          nfonts = 6;%@NL@%
  9979. %@NL@%
  9980. %@AS@%          texttypes : ARRAY[ 1..2, 1..nfonts ] OF CSTRING[8] =%@NL@%
  9981. %@AS@%             (%@NL@%
  9982. %@AS@%             ( 'roman', 'courier', 'helv', 'tms rmn', 'modern', 'script' ),%@NL@%
  9983. %@AS@%             ( 'ROMAN', 'COURIER', 'HELV', 'TMS RMN', 'MODERN', 'SCRIPT' )%@NL@%
  9984. %@AS@%             );%@NL@%
  9985. %@NL@%
  9986. %@AS@%          faces : ARRAY[ 1..nfonts ] OF CSTRING[12] =%@NL@%
  9987. %@AS@%               (%@NL@%
  9988. %@AS@%                ' t''roman''',%@NL@%
  9989. %@AS@%                ' t''cour''',%@NL@%
  9990. %@AS@%                ' t''helv''',%@NL@%
  9991. %@AS@%                ' t''tms rmn''',%@NL@%
  9992. %@AS@%                ' t''modern''',%@NL@%
  9993. %@AS@%                ' t''script'''%@NL@%
  9994. %@AS@%               );%@NL@%
  9995. %@AS@%          fontpath : CSTRING = '*.FON';%@NL@%
  9996. %@AS@%     VAR%@NL@%
  9997. %@AS@%         list : CSTRING;%@NL@%
  9998. %@AS@%         vc   : _VideoConfig;%@NL@%
  9999. %@AS@%         i, a : Integer;%@NL@%
  10000. %@AS@%         stra : STRING[3];%@NL@%
  10001. %@AS@%         ch   : Char;%@NL@%
  10002. %@NL@%
  10003. %@NL@%
  10004. %@AS@%     BEGIN  { Begin main program }%@NL@%
  10005. %@NL@%
  10006. %@AS@%          { Read header information from all .FON files in%@NL@%
  10007. %@AS@%            the current directory%@NL@%
  10008. %@AS@%          }%@NL@%
  10009. %@AS@%          a := _RegisterFonts( fontpath );%@NL@%
  10010. %@AS@%          IF  a < 0 THEN%@NL@%
  10011. %@AS@%              BEGIN%@NL@%
  10012. %@AS@%              _OutText('Error: Cannot register fonts.' + CRLF);%@NL@%
  10013. %@AS@%              Halt(1);%@NL@%
  10014. %@AS@%              END;%@NL@%
  10015. %@NL@%
  10016. %@AS@%          { Set the highest available video mode }%@NL@%
  10017. %@AS@%          a := _SetVideoMode( _MaxResMode );%@NL@%
  10018. %@AS@%          Str( a, stra );%@NL@%
  10019. %@AS@%          _OutText( 'MaxresMode = ' + stra );%@NL@%
  10020. %@NL@%
  10021. %@AS@%          { Copy video configuration into structure vc }%@NL@%
  10022. %@AS@%          _GetVideoConfig(vc);%@NL@%
  10023. %@NL@%
  10024. %@AS@%          { Display six lines of sample text }%@NL@%
  10025. %@AS@%          FOR i := 1 TO nfonts DO%@NL@%
  10026. %@AS@%               BEGIN%@NL@%
  10027. %@AS@%               list := faces[i] + 'bh24w24' ;%@NL@%
  10028. %@AS@%               a:= _SetFont( list );%@NL@%
  10029. %@NL@%
  10030. %@AS@%               IF ( a <> -1) THEN%@NL@%
  10031. %@AS@%                    BEGIN%@NL@%
  10032. %@AS@%                    _SetColor( i + 1);%@NL@%
  10033. %@AS@%                    _MoveTo( 0, i * 30 );%@NL@%
  10034. %@AS@%                    _OutGText( texttypes[2,i] );%@NL@%
  10035. %@AS@%                    _MoveTo( vc.NumXPixels DIV 2, i * 30 );%@NL@%
  10036. %@AS@%                    _OutGText( texttypes[1,i]+CRLF );%@NL@%
  10037. %@AS@%                    END%@NL@%
  10038. %@AS@%               ELSE%@NL@%
  10039. %@AS@%                    BEGIN%@NL@%
  10040. %@AS@%                    a := _SetVideoMode(_DefaultMode);%@NL@%
  10041. %@AS@%                    _OutText('Error: Cannot set font.');%@NL@%
  10042. %@AS@%                    Halt(1);%@NL@%
  10043. %@AS@%                    END;%@NL@%
  10044. %@AS@%              END;%@NL@%
  10045. %@NL@%
  10046. %@AS@%          ch := ReadKey;%@NL@%
  10047. %@NL@%
  10048. %@AS@%          a := _SetVideoMode(_DefaultMode);%@NL@%
  10049. %@NL@%
  10050. %@AS@%          _UnRegisterFonts;  { Returns memory used by fonts }%@NL@%
  10051. %@NL@%
  10052. %@AS@%     END.%@NL@%
  10053. %@NL@%
  10054. %@NL@%
  10055. %@CR:MQPF0000@%%@1@%%@AB@%Chapter 15  Object-Oriented Programming%@AE@%%@EH@%%@NL@%
  10056. ───────────────────────────────────────────────────────────────────────────%@NL@%
  10057. %@NL@%
  10058. %@CR:MQPF0001@%%@4@%Object-oriented programming is widely hailed as the programming style of the%@EH@%
  10059. future. QuickPascal offers you object-oriented programming today, through
  10060. its object extensions to standard Pascal. Although they make only a few
  10061. syntactic additions to the language, the QuickPascal object extensions
  10062. provide a powerful and efficient framework for creating programs.%@NL@%
  10063. %@NL@%
  10064. %@NL@%
  10065. %@CR:MQPF1000@%%@2@%%@AB@%15.1  Overview%@AE@%%@EH@%%@NL@%
  10066. %@NL@%
  10067. %@CR:MQPF1001@%%@4@%Standard Pascal programs, along with programs written in other procedural%@EH@%
  10068. languages, are organized around a set of data structures, with separate
  10069. procedures and functions manipulating the data. An example is a graphics
  10070. program that declares each shape as a unique %@AB@%TYPE%@AE@%. Various routines draw,
  10071. erase, and move the shapes, likely using a %@AB@%CASE%@AE@% statement to differentiate
  10072. between them.%@NL@%
  10073. %@NL@%
  10074. %@CR:MQPF1002@%%@4@%Object-oriented programs operate differently. Instead of being organized%@EH@%
  10075. around data, they are organized around a set of "objects." An object is a
  10076. structure that combines both data and routines into one type. It is similar
  10077. to a Pascal %@AB@%RECORD%@AE@% type, but can store both functions and procedures as well
  10078. as data.%@NL@%
  10079. %@NL@%
  10080. %@CR:MQPF1003@%%@4@%Objects have a property called "inheritance." Once an object has been%@EH@%
  10081. declared, another object can be derived that inherits all of the data and
  10082. routines associated with the parent type. New data and routines can be
  10083. added, or existing inherited routines modified.%@NL@%
  10084. %@NL@%
  10085. %@CR:MQPF1004@%%@4@%A graphics program that was written with object extensions to QuickPascal%@EH@%
  10086. would declare an initial "generic shape" object. The generic shape would
  10087. define all of the data and routines──such as draw, erase, and size──that
  10088. were common to every shape. New shapes would be derived from the generic
  10089. shape, and then these new shapes would declare additional data fields,
  10090. override existing routines, and add new ones.%@NL@%
  10091. %@NL@%
  10092. %@CR:MQPF1005@%%@4@%One of the primary benefits of object-oriented programming is the ease with%@EH@%
  10093. which programs can be changed and portions reused. In the hypothetical
  10094. standard Pascal graphics application, to add an octagon shape to the
  10095. program, you would need to declare an entire new type as well as modify each
  10096. routine that dealt with the shapes. With object extensions to QuickPascal,
  10097. you would define an octagon object, already derived from the generic shape
  10098. object, and add or modify any data or routines the octagon exclusively used.
  10099. The old routines would still operate the same way on old types of objects.
  10100. Instead of making changes throughout the entire program, all of the changes
  10101. would occur in one localized area and apply only to that object or its
  10102. descendants.%@NL@%
  10103. %@NL@%
  10104. %@CR:MQPF1006@%%@4@%The example in Section 15.5%@BO:   8198a@% demonstrates basic object-oriented programming%@EH@%
  10105. techniques.%@NL@%
  10106. %@NL@%
  10107. %@NL@%
  10108. %@CR:MQPF2000@%%@2@%%@AB@%15.2  Object Programming Concepts%@AE@%%@EH@%%@NL@%
  10109. %@NL@%
  10110. %@CR:MQPF2001@%%@4@%Object-oriented extensions are based on four concepts: classes, objects,%@EH@%
  10111. methods, and inheritance. A "class" is similar to a Pascal %@AB@%RECORD%@AE@%. It
  10112. describes an overall structure for any number of types based upon it. The
  10113. main difference between a class and a record is that a class combines data
  10114. fields (called "instance variables") and procedures and functions (called
  10115. "methods") that act upon the data. Instance variables can include standard
  10116. Pascal data types as well as objects.%@NL@%
  10117. %@NL@%
  10118. %@CR:MQPF2002@%%@4@%An "object" is a variable of a class (often called a class instance). Like a%@EH@%
  10119. class, an object is declared as a %@AB@%TYPE%@AE@%. All objects derived from a class are
  10120. considered members of that class and share similar characteristics of the
  10121. superclass.%@NL@%
  10122. %@NL@%
  10123. %@CR:MQPF2003@%%@4@%"Methods" are procedures and functions encapsulated in a class or object.%@EH@%
  10124. Calling a method is referred to as "passing a message to an object." The
  10125. object extensions to QuickPascal create programs that do most of their work
  10126. by sending messages to objects, and by instructing objects to send messages
  10127. to each other. Methods are stored in an object-type method table and do not
  10128. occupy memory when an object is declared as a variable.%@NL@%
  10129. %@NL@%
  10130. %@CR:MQPF2004@%%@4@%Members of the same class exhibit similar behavior through inheritance. This%@EH@%
  10131. means the variable instances and methods found in a superclass are also
  10132. present in objects derived from the superclass. Additionally, objects have
  10133. their own space for storing data and methods local to the object. If
  10134. necessary, an object can also override a parent class's method, replacing
  10135. the inherited method's instructions with its own. If it does, only the
  10136. descendant object's methods are altered, while the parent's remain
  10137. unchanged.%@NL@%
  10138. %@NL@%
  10139. %@NL@%
  10140. %@CR:MQPF3000@%%@2@%%@AB@%15.3  Using Objects%@AE@%%@EH@%%@NL@%
  10141. %@NL@%
  10142. %@CR:MQPF3001@%%@4@%As mentioned before, the object extensions to QuickPascal add only a few new%@EH@%
  10143. keywords and types. All of the standard Pascal identifiers, constructs, and
  10144. routines are available when programming with objects. The differences in
  10145. using object extensions are in the areas of declaring class and object data
  10146. structures and of calling procedures and functions through methods.%@NL@%
  10147. %@NL@%
  10148. %@NL@%
  10149. %@CR:MQPF3100@%%@3@%%@AB@%15.3.1  Setting the Method Compiler Directive%@AE@%%@EH@%%@NL@%
  10150. %@NL@%
  10151. %@CR:MQPF3101@%%@4@%The first step in using object extensions is to enable the Method compiler%@EH@%
  10152. directive. The %@AB@%{$M+}%@AE@% directive should appear at the beginning of any source
  10153. file that uses objects. (The %@AB@%{$M+}%@AE@% directive is enabled by default.) This
  10154. directive instructs the compiler to check whether or not memory for an
  10155. object has been allocated before the object's method is executed. See
  10156. Appendix B%@BO:   857d9@%, "Compiler Directives," for more information.%@NL@%
  10157. %@NL@%
  10158. %@NL@%
  10159. %@CR:MQPF3200@%%@3@%%@AB@%15.3.2  Creating Classes%@AE@%%@EH@%%@NL@%
  10160. %@NL@%
  10161. %@CR:MQPF3201@%%@4@%Since all objects are derived from classes, classes are created first. A%@EH@%
  10162. class should incorporate all data and methods that descendant objects will
  10163. have in common.%@NL@%
  10164. %@NL@%
  10165. %@CR:MQPF3202@%%@4@%You use the following syntax to declare an object class:%@EH@%%@NL@%
  10166. %@NL@%
  10167.      %@AB@%TYPE%@AE@%%@NL@%
  10168.        %@AI@%ClassName%@AE@% %@AB@%= OBJECT%@AE@%%@NL@%
  10169.           %@AI@%DataFields%@AE@%%@NL@%
  10170.             %@AB@%{PROCEDURE|FUNCTION}%@AE@%«%@AI@%Methods%@AE@%»%@NL@%
  10171.         %@AB@%END;%@AE@%%@NL@%
  10172. %@NL@%
  10173. %@CR:MQPF3203@%%@4@%The parts of the syntax are defined below:%@EH@%%@NL@%
  10174. %@NL@%
  10175. %@CR:MQPF3204@%%@AB@%Argument                    Discription     %@AE@%%@NL@%
  10176. %@NL@%
  10177. %@AI@%ClassName%@AE@%                   A unique name that identifies the class.%@NL@%
  10178. %@NL@%
  10179. %@AB@%OBJECT%@AE@%                      A QuickPascal keyword that instructs the%@NL@%
  10180.                             compiler to treat the structure as an object.%@NL@%
  10181. %@NL@%
  10182. %@AI@%DataFields%@AE@%                  The declaration of one or more data structures.%@NL@%
  10183.                             The syntax is the same as that used for%@NL@%
  10184.                             declaring the fields of a record.%@NL@%
  10185. %@NL@%
  10186. %@AI@%Methods%@AE@%                     A list of method declarations. Each method%@NL@%
  10187.                             declaration is like a procedure or function%@NL@%
  10188.                             heading, except that the name may be qualified%@NL@%
  10189.                             with the name of the class:%@NL@%
  10190.                             %@AI@%ClassName.MethodName%@AE@%. Although not required,%@NL@%
  10191.                             such a qualification is good programming style.%@NL@%
  10192.                             Methods are declared immediately following the%@NL@%
  10193.                             class and object type declarations.%@NL@%
  10194. %@NL@%
  10195. %@CR:MQPF3205@%%@4@%For example, the following code fragment creates a generic shape for a%@EH@%
  10196. graphics program:%@NL@%
  10197. %@NL@%
  10198. %@AS@%     TYPE%@NL@%
  10199. %@AS@%          shape = OBJECT%@NL@%
  10200. %@AS@%               color: colors;%@NL@%
  10201. %@AS@%               height, width: Integer;%@NL@%
  10202. %@AS@%               PROCEDURE shape.init;%@NL@%
  10203. %@AS@%               PROCEDURE shape.draw;%@NL@%
  10204. %@AS@%               PROCEDURE shape.move(hoz, vert: Integer);%@NL@%
  10205. %@AS@%               FUNCTION shape.area: Integer;%@NL@%
  10206. %@AS@%          END;%@NL@%
  10207. %@NL@%
  10208. %@AS@%          PROCEDURE shape.init%@NL@%
  10209. %@AS@%              BEGIN { code for init method here }%@NL@%
  10210. %@AS@%              .%@NL@%
  10211. %@AS@%              .%@NL@%
  10212. %@AS@%              .%@NL@%
  10213. %@AS@%              END;%@NL@%
  10214. %@NL@%
  10215. %@AS@%          PROCEDURE shape.draw;%@NL@%
  10216. %@AS@%              BEGIN  { code for draw method here }%@NL@%
  10217. %@AS@%              .      { remainder of methods }%@NL@%
  10218. %@AS@%              .%@NL@%
  10219. %@AS@%              .%@NL@%
  10220. %@AS@%              END;%@NL@%
  10221. %@NL@%
  10222. %@NL@%
  10223. %@CR:MQPF3300@%%@3@%%@AB@%15.3.3  Creating Subclasses%@AE@%%@EH@%%@NL@%
  10224. %@NL@%
  10225. %@CR:MQPF3301@%%@4@%Once a class has been created, subclasses can be defined. The syntax for%@EH@%
  10226. creating a subclass is similar to that of a class:%@NL@%
  10227. %@NL@%
  10228.      %@AB@%TYPE%@AE@%%@NL@%
  10229.        %@AI@%ObjectName%@AE@%%@AB@% = OBJECT( %@AE@%%@AI@%ParentClass%@AE@% %@AB@%)%@AE@%%@NL@%
  10230.           %@AI@%DataFields%@AE@%%@NL@%
  10231.            %@AB@%{PROCEDURE|FUNCTION}%@AE@%«%@AI@%Methods%@AE@%» «%@AB@%; OVERRIDE%@AE@% »%@NL@%
  10232.         %@AB@%END;%@AE@%%@NL@%
  10233. %@NL@%
  10234. %@CR:MQPF3302@%%@4@%The two special aspects of declaring objects are the use of parent class and%@EH@%
  10235. of overriding inherited methods. The argument %@AI@%ParentClass%@AE@% is the name of a
  10236. parent class. Since the subclass is derived from a class, you would enclose
  10237. the name of the class in parentheses.%@NL@%
  10238. %@NL@%
  10239. %@CR:MQPF3303@%%@4@%If the subclass redefines a method from the parent class, the %@AB@%OVERRIDE%@AE@%%@EH@%
  10240. statement should appear after the method header.%@NL@%
  10241. %@NL@%
  10242. %@CR:MQPF3304@%%@4@%For example, the following code fragment declares a descendant of the %@AS@%shape%@AE@%%@EH@%
  10243. class:%@NL@%
  10244. %@NL@%
  10245. %@AS@%     TYPE%@NL@%
  10246. %@AS@%          circle = OBJECT(shape)%@NL@%
  10247. %@AS@%               radius: Integer;%@NL@%
  10248. %@AS@%               PROCEDURE circle.init; OVERRIDE;%@NL@%
  10249. %@AS@%               PROCEDURE circle.draw; OVERRIDE;%@NL@%
  10250. %@AS@%               FUNCTION circle.area: Integer; OVERRIDE;%@NL@%
  10251. %@AS@%               PROCEDURE circle.changeradius(new_radius: Integer);%@NL@%
  10252. %@AS@%          END;%@NL@%
  10253. %@NL@%
  10254. %@CR:MQPF3305@%%@4@%Because the  circle type is being derived from the %@AS@%shape%@AE@% class, there is no%@EH@%
  10255. need to declare all of the instance variables and methods from %@AS@%shape%@AE@%. The
  10256. only variables and methods that need declaring are those that are new and
  10257. exclusive to the %@AS@%circle%@AE@% object. In this case, the new items are the %@AS@%radius%@AE@%
  10258. field and the %@AS@%changeradius%@AE@% method. A %@AS@%circle%@AE@% object will have color, height,
  10259. width, and radius fields.%@NL@%
  10260. %@NL@%
  10261. %@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@%
  10262. they were for %@AS@%shape%@AE@%, the %@AB@%OVERRIDE%@AE@% keyword instructs the compiler to use the
  10263. method local to %@AS@%circle%@AE@% when one of these messages is passed to the object.%@NL@%
  10264. %@NL@%
  10265. %@NL@%
  10266. %@CR:MQPF3400@%%@3@%%@AB@%15.3.4  Defining Methods%@AE@%%@EH@%%@NL@%
  10267. %@NL@%
  10268. %@CR:MQPF3401@%%@4@%After a method has been associated with an object, it must be defined.%@EH@%
  10269. Methods are defined with the %@AB@%PROCEDURE%@AE@% or %@AB@%FUNCTION%@AE@% keywords. The actual
  10270. statements that compose the method are defined after all classes and
  10271. subclasses have been created. Either the %@AB@%PROCEDURE%@AE@% or %@AB@%FUNCTION%@AE@% keyword
  10272. precedes the object name, followed by a period (.) and the method name.
  10273. Methods that are overridden follow the same syntax. (See the example at the
  10274. end of the chapter%@BO:   8198a@%.)%@NL@%
  10275. %@NL@%
  10276. %@CR:MQPF3402@%%@4@%The first method you should define is one that initializes all of the%@EH@%
  10277. object's data fields, allocates memory, or performs any other actions the
  10278. object may need before being used. This method should be called immediately
  10279. after space has been allocated for the object.%@NL@%
  10280. %@NL@%
  10281. %@CR:MQPF3403@%%@4@%Instance variables that belong to the object can be accessed from within a%@EH@%
  10282. method by using their identifier preceded by the pseudovariable %@AB@%Self%@AE@%, as
  10283. shown below:%@NL@%
  10284. %@NL@%
  10285. %@AS@%     PROCEDURE circle.init;%@NL@%
  10286. %@AS@%         BEGIN%@NL@%
  10287. %@AS@%              Self.color  := blue;%@NL@%
  10288. %@AS@%              Self.height := 20;%@NL@%
  10289. %@AS@%              Self.width  := 20;%@NL@%
  10290. %@AS@%              Self.radius := 0;%@NL@%
  10291. %@AS@%         END;%@NL@%
  10292. %@NL@%
  10293. %@CR:MQPF3404@%%@4@%%@AB@%Self%@AE@% simply instructs the object to operate on itself.%@EH@%%@NL@%
  10294. %@NL@%
  10295. %@CR:MQPF3405@%%@4@%An object's data may be accessed by a program directly, as if the object%@EH@%
  10296. were a record:%@NL@%
  10297. %@NL@%
  10298. %@AS@%     the_radius := circle.radius;%@NL@%
  10299. %@NL@%
  10300. %@CR:MQPF3406@%%@4@%Also, to call a method belonging to the object from within a different%@EH@%
  10301. method, you may precede it with the %@AB@%Self%@AE@% variable. In the code fragment
  10302. below, %@AS@%Self.draw%@AE@% is equivalent to %@AS@%circle.draw%@AE@%.%@NL@%
  10303. %@NL@%
  10304. %@AS@%     PROCEDURE circle.move(hoz, vert: Integer);%@NL@%
  10305. %@AS@%         BEGIN%@NL@%
  10306. %@AS@%         .%@NL@%
  10307. %@AS@%         .%@NL@%
  10308. %@AS@%         .%@NL@%
  10309. %@AS@%              Self.draw;%@NL@%
  10310. %@AS@%         END;%@NL@%
  10311. %@NL@%
  10312. %@CR:MQPF3407@%%@4@%Note that you are not restricted solely to using methods when you use object%@EH@%
  10313. extensions to QuickPascal. Methods are only used with objects. Standard
  10314. Pascal procedures and functions can be implemented to manipulate other forms
  10315. of data.%@NL@%
  10316. %@NL@%
  10317. %@NL@%
  10318. %@CR:MQPF3500@%%@3@%%@AB@%15.3.5  Using INHERITED%@AE@%%@EH@%%@NL@%
  10319. %@NL@%
  10320. %@CR:MQPF3501@%%@4@%The %@AB@%INHERITED%@AE@% keyword negates an override of an inherited method. If the%@EH@%
  10321. class of method performs only a portion of what an object needs to have
  10322. done, the parent method can be called from the descendant method.%@NL@%
  10323. %@NL@%
  10324. %@CR:MQPF3502@%%@4@%For example, suppose that in the %@AS@%shape%@AE@% initialization method, you set the%@EH@%
  10325. following values:%@NL@%
  10326. %@NL@%
  10327. %@AS@%     PROCEDURE shape.init;%@NL@%
  10328. %@AS@%         BEGIN%@NL@%
  10329. %@AS@%              color  := blue;%@NL@%
  10330. %@AS@%              height := 20;%@NL@%
  10331. %@AS@%              width  := 20;%@NL@%
  10332. %@AS@%         END;%@NL@%
  10333. %@NL@%
  10334. %@CR:MQPF3503@%%@4@%If  the %@AS@%circle%@AE@% object used these values, but overrode the method to%@EH@%
  10335. initialize its own data field, %@AB@%INHERITED%@AE@% could be used to call the ancestor
  10336. method. This would initialize the common fields without needing to
  10337. initialize them in the descendant method.%@NL@%
  10338. %@NL@%
  10339. %@AS@%     PROCEDURE circle.init;%@NL@%
  10340. %@AS@%         BEGIN%@NL@%
  10341. %@AS@%              radius := 0;%@NL@%
  10342. %@AS@%              INHERITED Self.init;%@NL@%
  10343. %@AS@%         END;%@NL@%
  10344. %@NL@%
  10345. %@NL@%
  10346. %@CR:MQPF3600@%%@3@%%@AB@%15.3.6  Declaring Objects%@AE@%%@EH@%%@NL@%
  10347. %@NL@%
  10348. %@CR:MQPF3601@%%@4@%Declaring an object is similar to declaring a dynamic variable. The syntax%@EH@%
  10349. is%@NL@%
  10350. %@NL@%
  10351.      %@AB@%VAR%@AE@%%@NL@%
  10352.             %@AI@%ObjectIdentifier%@AE@% %@AB@%:%@AE@% %@AI@%Class%@AE@%%@NL@%
  10353. %@NL@%
  10354. %@CR:MQPF3602@%%@4@%%@AI@%ObjectIdentifier%@AE@% is the QuickPascal identifier for the object, and %@AI@%Class%@AE@% is%@EH@%
  10355. the type of the object.%@NL@%
  10356. %@NL@%
  10357. %@CR:MQPF3603@%%@4@%For example, this code declares an object of the class %@AS@%circle%@AE@%:%@EH@%%@NL@%
  10358. %@NL@%
  10359. %@AS@%     VAR%@NL@%
  10360. %@AS@%         my_circle: circle;%@NL@%
  10361. %@NL@%
  10362. %@NL@%
  10363. %@CR:MQPF3700@%%@3@%%@AB@%15.3.7  Allocating Memory%@AE@%%@EH@%%@NL@%
  10364. %@NL@%
  10365. %@CR:MQPF3701@%%@4@%Before an object can be used in a program, memory space must be allocated%@EH@%
  10366. for it. This is done with the Pascal %@AB@%New%@AE@% procedure:%@NL@%
  10367. %@NL@%
  10368. %@AS@%     New( my_circle );%@NL@%
  10369. %@NL@%
  10370. %@CR:MQPF3702@%%@4@%A common mistake in object-oriented programming is forgetting to allocate%@EH@%
  10371. memory for an object and then trying to access it. Allocating memory for
  10372. objects should be one of the first actions of the program body.%@NL@%
  10373. %@NL@%
  10374. %@NL@%
  10375. %@CR:MQPF3800@%%@3@%%@AB@%15.3.8  Calling Methods%@AE@%%@EH@%%@NL@%
  10376. %@NL@%
  10377. %@CR:MQPF3801@%%@4@%After classes and objects have been declared, and memory has been allocated%@EH@%
  10378. for the object, you can call a method (that is, send a message to the
  10379. object) from within the main body of the program to manipulate the object's
  10380. instance variables. Sending a message is similar to calling a procedure or
  10381. function in standard Pascal. The only difference is that you specify both
  10382. the object and the method.%@NL@%
  10383. %@NL@%
  10384. %@CR:MQPF3802@%%@4@%For example, different methods for %@AS@%my_circle%@AE@% are executed by%@EH@%%@NL@%
  10385. %@NL@%
  10386. %@AS@%     my_circle.draw;%@NL@%
  10387. %@AS@%     my_circle.move( 30, 30 );%@NL@%
  10388. %@AS@%     circle_area := my_circle.area;%@NL@%
  10389. %@NL@%
  10390. %@NL@%
  10391. %@CR:MQPF3900@%%@3@%%@AB@%15.3.9  Testing Membership%@AE@%%@EH@%%@NL@%
  10392. %@NL@%
  10393. %@CR:MQPF3901@%%@4@%The %@AB@%Member%@AE@% function tests if a particular object is in a class, as shown%@EH@%
  10394. below:%@NL@%
  10395. %@NL@%
  10396. %@AS@%     IF Member( a_circle, shape ) THEN%@NL@%
  10397. %@AS@%        num_shapes := num_shapes + 1;%@NL@%
  10398. %@NL@%
  10399. %@CR:MQPF3902@%%@4@%The function is passed the object and the class. It returns %@AB@%True%@AE@% if the%@EH@%
  10400. object is an instance of, or a decendant of, the class.%@NL@%
  10401. %@NL@%
  10402. %@NL@%
  10403. %@CR:MQPF3A00@%%@3@%%@AB@%15.3.10  Disposing of Objects%@AE@%%@EH@%%@NL@%
  10404. %@NL@%
  10405. %@CR:MQPF3A01@%%@4@%When you are finished using an object, the memory allocated for it should be%@EH@%
  10406. freed. This is done with the %@AB@%Dispose%@AE@% procedure:%@NL@%
  10407. %@NL@%
  10408. %@AS@%     Dispose( my_circle );%@NL@%
  10409. %@NL@%
  10410. %@CR:MQPF3A02@%%@4@%Before disposing of an object, be sure it will not be used further in the%@EH@%
  10411. program.%@NL@%
  10412. %@NL@%
  10413. %@CR:MQPF3A03@%%@4@%Often, a free method is declared to reallocate data-structure memory, close%@EH@%
  10414. files, and perform other housecleaning. Such a method should be called
  10415. before using %@AB@%Dispose%@AE@%.%@NL@%
  10416. %@NL@%
  10417. %@NL@%
  10418. %@CR:MQPF4000@%%@2@%%@AB@%15.4  Object Programming Strategies%@AE@%%@EH@%%@NL@%
  10419. %@NL@%
  10420. %@CR:MQPF4001@%%@4@%The greatest difficulty facing programmers who are learning object%@EH@%
  10421. extensions to QuickPascal is the need to plan and write their programs in an
  10422. object-oriented manner. All too often, a programmer's first object-oriented
  10423. programs exhibit a procedural style with objects sprinkled in haphazardly.
  10424. Programming in this fashion reduces the value of object extensions for
  10425. producing efficient and reusable code. Sections 15.4.1%@BO:   80b96@%-15.4.5 discuss
  10426. several issues you should keep in mind as you create object-oriented
  10427. programs.%@NL@%
  10428. %@NL@%
  10429. %@NL@%
  10430. %@CR:MQPF4100@%%@3@%%@AB@%15.4.1  Object Style Conventions%@AE@%%@EH@%%@NL@%
  10431. %@NL@%
  10432. %@CR:MQPF4101@%%@4@%Although style conventions for programs are often a matter of personal%@EH@%
  10433. preference, adoption of certain style conventions for object programming can
  10434. make your source code easier to read. For example, since both a Pascal
  10435. record and an object use a period (%@AB@%.%@AE@%) to access their data fields and
  10436. methods, it can be difficult to distinguish objects from records. This is
  10437. made more complicated by the difficulty telling whether an identifier
  10438. following an object is an instance variable or a method.%@NL@%
  10439. %@NL@%
  10440. %@CR:MQPF4102@%%@4@%Here are some style conventions for object programming:%@EH@%%@NL@%
  10441. %@NL@%
  10442. %@CR:MQPF4103@%  ■  Classes and objects are preceded with an uppercase "T." This identifies%@NL@%
  10443.      the variable as an object type, as shown below:%@NL@%
  10444. %@NL@%
  10445.         %@AS@%Tcircle = OBJECT(Tshape)%@AE@%%@NL@%
  10446. %@NL@%
  10447.   ■  Object instance variables are preceded with a lowercase "f." The "f"%@NL@%
  10448.      indicates at a glance that the identifier is a field. Identifiers%@NL@%
  10449.      without the "f" are methods, as in the following example:%@NL@%
  10450. %@NL@%
  10451.         %@AS@%the_radius := Tcircle.fradius;%@AE@%%@NL@%
  10452.         %@AS@%Tcircle.draw;%@AE@%%@NL@%
  10453. %@NL@%
  10454.   ■  Global variables are preceded with a lowercase "g." This is helpful in%@NL@%
  10455.      identifying objects that can be passed messages from objects outside%@NL@%
  10456.      their own class (see below):%@NL@%
  10457. %@NL@%
  10458.         %@AS@%gTtemp_circle.color := blue;%@AE@%%@NL@%
  10459. %@NL@%
  10460. %@NL@%
  10461. %@CR:MQPF4200@%%@3@%%@AB@%15.4.2  Object Reusability%@AE@%%@EH@%%@NL@%
  10462. %@NL@%
  10463. %@CR:MQPF4201@%%@4@%The essence of object-oriented programming is reusability. When you create%@EH@%
  10464. objects, you should give some thought to their future use, both in terms of
  10465. the current program and for later ones. It's best to create classes from
  10466. which other objects can be derived. Inheriting methods is generally more
  10467. important than inheriting data. On a larger scale, class libraries are
  10468. useful for dealing with common tasks. A set of related classes can reside in
  10469. a %@AB@%UNIT%@AE@% and be called at any time.%@NL@%
  10470. %@NL@%
  10471. %@NL@%
  10472. %@CR:MQPF4300@%%@3@%%@AB@%15.4.3  Modularity%@AE@%%@EH@%%@NL@%
  10473. %@NL@%
  10474. %@CR:MQPF4301@%%@4@%Object extensions to QuickPascal lend themselves to modularized programs. A%@EH@%
  10475. class's methods can easily be kept together, instead of being strung out
  10476. through the source code. A properly constructed object program should
  10477. require only a few localized modifications to add and alter methods.%@NL@%
  10478. %@NL@%
  10479. %@NL@%
  10480. %@CR:MQPF4400@%%@3@%%@AB@%15.4.4  Methods%@AE@%%@EH@%%@NL@%
  10481. %@NL@%
  10482. %@CR:MQPF4401@%%@4@%Methods should be treated as replaceable components of the object building%@EH@%
  10483. blocks of QuickPascal. Methods are designed to serve a single purpose; a
  10484. method that is multipurpose is more difficult to modify because it performs
  10485. a variety of tasks. Whenever you want to perform an action, create a method
  10486. to do it. Methods should be short, at most several dozen statements in
  10487. length.%@NL@%
  10488. %@NL@%
  10489. %@NL@%
  10490. %@CR:MQPF4500@%%@3@%%@AB@%15.4.5  Data Fields%@AE@%%@EH@%%@NL@%
  10491. %@NL@%
  10492. %@CR:MQPF4501@%%@4@%It isn't necessary to declare an instance variable for each data item an%@EH@%
  10493. object may use. If more than one object method uses a specific data item,
  10494. the data should be incorporated as an instance variable. If only a single
  10495. method accesses the data, it can be passed as a parameter to the method. You
  10496. should use object instance variables in place of global variables to promote
  10497. modularity.%@NL@%
  10498. %@NL@%
  10499. %@NL@%
  10500. %@CR:MQPF5000@%%@2@%%@AB@%15.5  Example Program%@AE@%%@EH@%%@NL@%
  10501. %@NL@%
  10502. %@CR:MQPF5001@%%@4@%This example shows how a typical object-oriented program works. A class is%@EH@%
  10503. declared (%@AS@%geo_shape%@AE@%), with two subclasses ( %@AS@%rectangle%@AE@% and %@AS@%circle%@AE@%). Both the
  10504. subclasses demonstrate how to add instance variables and methods and how to
  10505. override existing parent methods. The body of the OBJECTDE.PAS program has
  10506. examples of defining methods, accessing instance variables, and declaring
  10507. and disposing of objects.%@NL@%
  10508. %@NL@%
  10509. %@AS@%     Program objectdemo;%@NL@%
  10510. %@AS@%     { Demonstrates object techniques with geometric shapes }%@NL@%
  10511. %@NL@%
  10512. %@AS@%     {M+}%@NL@%
  10513. %@NL@%
  10514. %@AS@%     TYPE%@NL@%
  10515. %@NL@%
  10516. %@AS@%          geo_shape = OBJECT%@NL@%
  10517. %@AS@%                      area: Real;%@NL@%
  10518. %@AS@%                      height: Real;%@NL@%
  10519. %@AS@%                      what: STRING;%@NL@%
  10520. %@AS@%                      PROCEDURE geo_shape.init;%@NL@%
  10521. %@AS@%                      PROCEDURE geo_shape.say_what;%@NL@%
  10522. %@AS@%                      FUNCTION geo_shape.get_area : Real;%@NL@%
  10523. %@AS@%          END;%@NL@%
  10524. %@NL@%
  10525. %@AS@%          rectangle = OBJECT(geo_shape)%@NL@%
  10526. %@AS@%                      len: Real;%@NL@%
  10527. %@AS@%                      FUNCTION rectangle.is_square : Boolean;%@NL@%
  10528. %@AS@%                      PROCEDURE rectangle.init; OVERRIDE;%@NL@%
  10529. %@AS@%                      FUNCTION rectangle.get_area : Real; OVERRIDE;%@NL@%
  10530. %@AS@%          END;%@NL@%
  10531. %@NL@%
  10532. %@AS@%          circle = OBJECT(geo_shape)%@NL@%
  10533. %@AS@%                   radius: Real;%@NL@%
  10534. %@AS@%                   PROCEDURE circle.init; OVERRIDE;%@NL@%
  10535. %@AS@%                   FUNCTION circle.get_area : Real; OVERRIDE;%@NL@%
  10536. %@AS@%          END;%@NL@%
  10537. %@NL@%
  10538. %@AS@%     PROCEDURE geo_shape.init;%@NL@%
  10539. %@AS@%     BEGIN%@NL@%
  10540. %@AS@%         Self.area := 0;%@NL@%
  10541. %@AS@%         Self.height := 0;%@NL@%
  10542. %@AS@%         Self.what := 'Geometric shape';%@NL@%
  10543. %@AS@%     END;%@NL@%
  10544. %@NL@%
  10545. %@AS@%     PROCEDURE geo_shape.say_what;%@NL@%
  10546. %@AS@%     BEGIN%@NL@%
  10547. %@AS@%         Writeln(Self.what);%@NL@%
  10548. %@AS@%     END;%@NL@%
  10549. %@NL@%
  10550. %@AS@%     FUNCTION geo_shape.get_area : Real;%@NL@%
  10551. %@AS@%     BEGIN%@NL@%
  10552. %@AS@%         Self.area := Self.height * Self.height;%@NL@%
  10553. %@AS@%         get_area := Self.height;%@NL@%
  10554. %@AS@%     END;%@NL@%
  10555. %@NL@%
  10556. %@AS@%     PROCEDURE circle.init;%@NL@%
  10557. %@AS@%     BEGIN%@NL@%
  10558. %@AS@%         INHERITED Self.init;%@NL@%
  10559. %@AS@%         Self.radius := 4;%@NL@%
  10560. %@AS@%         Self.what := 'circle';%@NL@%
  10561. %@AS@%     END;%@NL@%
  10562. %@NL@%
  10563. %@AS@%     FUNCTION circle.get_area: Real;%@NL@%
  10564. %@AS@%     BEGIN%@NL@%
  10565. %@AS@%         Self.area := ( Pi * Sqr( Self.radius ) );%@NL@%
  10566. %@AS@%         get_area := Self.area;%@NL@%
  10567. %@AS@%     END;%@NL@%
  10568. %@NL@%
  10569. %@AS@%     PROCEDURE rectangle.init;%@NL@%
  10570. %@AS@%     BEGIN%@NL@%
  10571. %@AS@%         INHERITED Self.init;%@NL@%
  10572. %@AS@%         Self.height := 5;%@NL@%
  10573. %@AS@%         Self.len := 5;%@NL@%
  10574. %@AS@%         Self.what := 'Rectangle';%@NL@%
  10575. %@AS@%     END;%@NL@%
  10576. %@NL@%
  10577. %@AS@%     FUNCTION rectangle.is_square: Boolean;%@NL@%
  10578. %@AS@%     BEGIN%@NL@%
  10579. %@AS@%         is_square := False;%@NL@%
  10580. %@AS@%         IF Self.len = Self.height THEN%@NL@%
  10581. %@AS@%         is_square := True;%@NL@%
  10582. %@AS@%     END;%@NL@%
  10583. %@NL@%
  10584. %@AS@%     FUNCTION rectangle.get_area: Real;%@NL@%
  10585. %@AS@%     BEGIN%@NL@%
  10586. %@AS@%         Self.area := ( Self.len * Self.height );%@NL@%
  10587. %@AS@%         get_area := Self.area;%@NL@%
  10588. %@AS@%     END;%@NL@%
  10589. %@NL@%
  10590. %@AS@%     VAR%@NL@%
  10591. %@NL@%
  10592. %@AS@%         the_circle : circle;%@NL@%
  10593. %@AS@%         the_rect : rectangle;%@NL@%
  10594. %@NL@%
  10595. %@AS@%     BEGIN%@NL@%
  10596. %@AS@%         New( the_circle );%@NL@%
  10597. %@AS@%         the_circle.init;%@NL@%
  10598. %@AS@%         New( the_rect );%@NL@%
  10599. %@AS@%         the_rect.init;%@NL@%
  10600. %@NL@%
  10601. %@AS@%         the_circle.say_what;%@NL@%
  10602. %@AS@%         Writeln( 'area: ', the_circle.get_area );%@NL@%
  10603. %@NL@%
  10604. %@AS@%         Writeln;%@NL@%
  10605. %@NL@%
  10606. %@AS@%         the_rect.say_what;%@NL@%
  10607. %@AS@%         Writeln( 'area: ', the_rect.get_area );%@NL@%
  10608. %@NL@%
  10609. %@AS@%         Dispose( the_circle );%@NL@%
  10610. %@AS@%         Dispose( the_rect );%@NL@%
  10611. %@AS@%     END.%@NL@%
  10612. %@NL@%
  10613. %@NL@%
  10614. %@CR:MQPa0000@%%@1@%%@AB@%Appendix A  ASCII Character Codes and Extended Key Codes%@AE@%%@EH@%%@NL@%
  10615. ───────────────────────────────────────────────────────────────────────────%@NL@%
  10616. %@NL@%
  10617. %@NL@%
  10618. %@CR:MQPa1000@%%@2@%%@AB@%A.1  ASCII Character Codes%@AE@%%@EH@%%@NL@%
  10619. %@NL@%
  10620. %@CR:MQPa1001@%%@4@%The ASCII character codes for printable and control characters are listed on%@EH@%
  10621. the following two pages. The value of each character is its ordinal value
  10622. within the type %@AB@%Char%@AE@%. For example, Ord ( 'P' ) returns the decimal value
  10623. 80.%@NL@%
  10624. %@NL@%
  10625. %@AB@%Ctl%@AE@%%@FN@%
  10626. Control Code%@EF@% %@AB@%D%@AE@%%@FN@%
  10627. Decimal%@EF@%  %@AB@%H%@AE@%%@FN@%
  10628. Hexidecimal%@EF@%  %@AB@%O%@AE@%%@FN@%
  10629. Octal%@EF@%  %@AB@%C%@AE@%%@FN@%
  10630. Character%@EF@% %@AB@%Code%@AE@%  %@AB@%D%@AE@%%@FN@%
  10631. Decimal%@EF@%  %@AB@%H%@AE@%%@FN@%
  10632. Hexidecimal%@EF@%  %@AB@%O%@AE@%%@FN@%
  10633. Octal%@EF@%   %@AB@%C%@AE@%%@FN@%
  10634. Character%@EF@%   %@AB@%D%@AE@%%@FN@%
  10635. Decimal%@EF@%  %@AB@%H%@AE@%%@FN@%
  10636. Hexideciaml%@EF@%  %@AB@%O%@AE@%%@FN@%
  10637. Octal%@EF@%   %@AB@%C%@AE@%%@FN@%
  10638. Character%@EF@%   %@AB@%D%@AE@%%@FN@%
  10639. Decimal%@EF@%  %@AB@%H%@AE@%%@FN@%
  10640. Hexidecimal%@EF@%  %@AB@%O%@AE@%%@FN@%
  10641. Octal%@EF@%   %@AB@%C%@AE@%%@FN@%
  10642. Character%@EF@%%@NL@%
  10643. %@NL@%
  10644. ^@   0  00  000     NUL│  32  20  040    │  64  40  100  @ │  96  60  140  `%@NL@%
  10645. ^A   1  01  001    SOH│  33  21  041  ! │  65  41  101  A │  97  61  141  a%@NL@%
  10646. ^B   2  02  002    STX│  34  22  042  " │  66  42  102  B │  98  62  142  b%@NL@%
  10647. ^C   3  03  003    ETX│  35  23  043  # │  67  43  103  C │  99  63  143  c%@NL@%
  10648. ^D   4  04  004    EOT│  36  24  044  $ │  68  44  104  D │ 100  64  144  d%@NL@%
  10649. ^E   5  05  005    ENQ│  37  25  045  % │  69  45  105  E │ 101  65  145  e%@NL@%
  10650. ^F   6  06  006    ACK│  38  26  046  & │  70  46  106  F │ 102  66  146  f%@NL@%
  10651. ^G   7  07  007    BEL│  39  27  047  ' │  71  47  107  G │ 103  67  147  g%@NL@%
  10652. ^H   8  08  010    BS │  40  28  050  ( │  72  48  110  H │ 104  68  150  h%@NL@%
  10653. ^I   9  09  011     HT │  41  29  051  ) │  73  49  111  I │ 105  69  151  i%@NL@%
  10654. ^J  10  0A  012     LF │  42  2A  052  * │  74  4A  112  J │ 106  6A  152  j%@NL@%
  10655. ^K  11  0B  013     VT │  43  2B  053  + │  75  4B  113  K │ 107  6B  153  k%@NL@%
  10656. ^L  12  0C  014     FF │  44  2C  054  , │  76  4C  114  L │ 108  6C  154  l%@NL@%
  10657. ^M  13  0D  015     CR │  45  2D  055  - │  77  4D  115  M │ 109  6D  155  m%@NL@%
  10658. ^N  14  0E  016    SO │  46  2E  056  . │  78  4E  116  N │ 110  6E  156  n%@NL@%
  10659. ^O  15  0F  017    SI │  47  2F  057  / │  79  4F  117  O │ 111  6F  157  o%@NL@%
  10660. ^P  16  10  020    DLE│  48  30  060  0 │  80  50  120  P │ 112  70  160  p%@NL@%
  10661. ^Q  17  11  021    DC1│  49  31  061  1 │  81  51  121  Q │ 113  71  161  q%@NL@%
  10662. ^R  18  12  022    DC2│  50  32  062  2 │  82  52  122  R │ 114  72  162  r%@NL@%
  10663. ^S  19  13  023    DC3│  51  33  063  3 │  83  53  123  S │ 115  73  163  s%@NL@%
  10664. ^T  20  14  024    DC4│  52  34  064  4 │  84  54  124  T │ 116  74  164  t%@NL@%
  10665. ^U  21  15  025    NAK│  53  35  065  5 │  85  55  125  U │ 117  75  165  u%@NL@%
  10666. ^V  22  16  026    SYN│  54  36  066  6 │  86  56  126  V │ 118  76  166  v%@NL@%
  10667. ^W  23  17  027    ETB│  55  37  067  7 │  87  57  127  W │ 119  77  167  w%@NL@%
  10668. ^X  24  18  030    CAN│  56  38  070  8 │  88  58  130  X │ 120  78  170  x%@NL@%
  10669. ^Y  25  19  031    EM │  57  39  071  9 │  89  59  131  Y │ 121  79  171  y%@NL@%
  10670. ^Z  26  1A  032     SUB│  58  3A  072  : │  90  5A  132  Z │ 122  7A  172  z%@NL@%
  10671. ^[  27  1B  033    ESC│  59  3B  073  ; │  91  5B  133  [ │ 123  7B  173  {%@NL@%
  10672. ^\  28  1C  034    FS │  60  3C  074  < │  92  5C  134  \ │ 124  7C  174  |%@NL@%
  10673. ^]  29  1D  035    GS │  61  3D  075  = │  93  5D  135  ] │ 125  7D  175  }%@NL@%
  10674. ^^  30  1E  036    RS │  62  3E  076  > │  94  5E  136  ^ │ 126  7E  176  ~%@NL@%
  10675. ^_  31  1F  037    US │  63  3F  077  ? │  95  5F  137  _ │ 127  7F  177 %@FN@%
  10676. ASCII code 127 has the code DEL. Under DOS, this code has the same effect as
  10677. ASCII 8 (BS). The DEL code can be generated by the CTRL+BKSP key
  10678. combination.%@EF@%%@NL@%
  10679. %@NL@%
  10680. %@NL@%
  10681. %@NL@%
  10682. %@AB@%D%@AE@%%@FN@%
  10683. Decimal%@EF@%   %@AB@%H%@AE@%%@FN@%
  10684. Hexidecimal%@EF@%  %@AB@%O%@FN@%
  10685. Octal%@EF@%   %@AB@%C%@AE@%%@FN@%
  10686. Character%@EF@%  %@AB@%D%@AE@%%@FN@%
  10687. Decimal%@EF@%   %@AB@%H%@AE@%%@FN@%
  10688. Hexidecimal%@EF@%  %@AB@%O%@AE@%%@FN@%
  10689. Octal%@EF@%   %@AB@%C%@AE@%%@FN@%
  10690. Character%@EF@%  %@AB@%D%@AE@%%@FN@%
  10691. Decimal%@EF@%   %@AB@%H%@AE@%%@FN@%
  10692. Hexidecimal%@EF@%  %@AB@%O%@AE@%%@FN@%
  10693. Octal%@EF@%   %@AB@%C%@AE@%%@FN@%
  10694. Character%@EF@%  %@AB@%D%@AE@%%@FN@%
  10695. Decimal%@EF@%   %@AB@%H%@AE@%%@FN@%
  10696. Hexidecimal%@EF@%  %@AB@%O%@AE@%%@FN@%
  10697. Octal%@EF@%   %@AB@%C%@AE@%%@FN@%
  10698. Character%@EF@%%@NL@%
  10699. %@NL@%
  10700. 128  80  200  Ç │ 160  A0  240  á │ 192  C0  300  └ │ 224  E0  340  α%@NL@%
  10701. 129  81  201  ü │ 161  A1  241  í │ 193  C1  301  ┴ │ 225  E1  341  ß%@NL@%
  10702. 130  82  202  é │ 162  A2  242  ó │ 194  C2  302  ┬ │ 226  E2  342  Γ%@NL@%
  10703. 131  83  203  â │ 163  A3  243  ú │ 195  C3  303  ├ │ 227  E3  343  π%@NL@%
  10704. 132  84  204  ä │ 164  A4  244  ñ │ 196  C4  304  ─ │ 228  E4  344  Σ%@NL@%
  10705. 133  85  205  à │ 165  A5  245  Ñ │ 197  C5  305  ┼ │ 229  E5  345  σ%@NL@%
  10706. 134  86  206  å │ 166  A6  246  ª │ 198  C6  306  ╞ │ 230  E6  346  µ%@NL@%
  10707. 135  87  207  ç │ 167  A7  247  º │ 199  C7  307  ╟ │ 231  E7  347  τ%@NL@%
  10708. 136  88  210  ê │ 168  A8  250  ¿ │ 200  C8  310  ╚ │ 232  E8  350  Φ%@NL@%
  10709. 137  89  211  ë │ 169  A9  251  ⌐ │ 201  C9  311  ╔ │ 233  E9  351  Θ%@NL@%
  10710. 138  8A  212  è │ 170  AA  252  ¬ │ 202  CA  312  ╩ │ 234  EA  352  Ω%@NL@%
  10711. 139  8B  213  ï │ 171  AB  253  ½ │ 203  CB  313  ╦ │ 235  EB  353  δ%@NL@%
  10712. 140  8C  214  î │ 172  AC  254  ¼ │ 204  CC  314  ╠ │ 236  EC  354  ∞%@NL@%
  10713. 141  8D  215  ì │ 173  AD  255  ¡ │ 205  CD  315  ═ │ 237  ED  355  φ%@NL@%
  10714. 142  8E  216  Ä │ 174  AE  256  « │ 206  CE  316  ╬ │ 238  EE  356  ε%@NL@%
  10715. 143  8F  217  Å │ 175  AF  257  » │ 207  CF  317  ╧ │ 239  EF  357  ∩%@NL@%
  10716. 144  90  220  É │ 176  B0  260  ░ │ 208  D0  320  ╨ │ 240  F0  360  ≡%@NL@%
  10717. 145  91  221  æ │ 177  B1  261  ▒ │ 209  D1  321  ╤ │ 241  F1  361  ±%@NL@%
  10718. 146  92  222  Æ │ 178  B2  262  ▓ │ 210  D2  322  ╥ │ 242  F2  362  ≥%@NL@%
  10719. 147  93  223  ô │ 179  B3  263  │ │ 211  D3  323  ╙ │ 243  F3  363  ≤%@NL@%
  10720. 148  94  224  ö │ 180  B4  264  ┤ │ 212  D4  324  ╘ │ 244  F4  364  ⌠%@NL@%
  10721. 149  95  225  ò │ 181  B5  265  ╡ │ 213  D5  325  ╒ │ 245  F5  365  ⌡%@NL@%
  10722. 150  96  226  û │ 182  B6  266  ╢ │ 214  D6  326  ╓ │ 246  F6  366  ÷%@NL@%
  10723. 151  97  227  ù │ 183  B7  267  ╖ │ 215  D7  327  ╫ │ 247  F7  367  ≈%@NL@%
  10724. 152  98  230  ÿ │ 184  B8  270  ╕ │ 216  D8  330  ╪ │ 248  F8  370  °%@NL@%
  10725. 153  99  231  Ö │ 185  B9  271  ╣ │ 217  D9  331  ┘ │ 249  F9  371  ∙%@NL@%
  10726. 154  9A  232  Ü │ 186  BA  272  ║ │ 218  DA  332  ┌ │ 250  FA  372  ·%@NL@%
  10727. 155  9B  233  ¢ │ 187  BB  273  ╗ │ 219  DB  333  █ │ 251  FB  373  √%@NL@%
  10728. 156  9C  234  £ │ 188  BC  274  ╝ │ 220  DC  334  ▄ │ 252  FC  374  ⁿ%@NL@%
  10729. 157  9D  235  ¥ │ 189  BD  275  ╜ │ 221  DD  335  ▌ │ 253  FD  375  ²%@NL@%
  10730. 158  9E  236  ₧ │ 190  BE  276  ╛ │ 222  DE  336  ▐ │ 254  FE  376  ■%@NL@%
  10731. 159  9F  237  ƒ │ 191  BF  277  ┐ │ 223  DF  337  ▀ │ 255  FF  377   %@NL@%
  10732. %@NL@%
  10733. %@NL@%
  10734. %@NL@%
  10735. %@CR:MQPa2000@%%@2@%%@AB@%A.2  Extended-Key Codes%@AE@%%@EH@%%@NL@%
  10736. %@NL@%
  10737. %@CR:MQPa2001@%%@4@%The %@AB@%Crt%@AE@% unit's %@AB@%ReadKey%@AE@% function returns a pair of values (instead of a%@EH@%
  10738. single ASCII character) when a key on an extended keyboard is pressed. The
  10739. first code is a null character (ASCII 0), which indicates that the next
  10740. character will be an extended-key code.%@NL@%
  10741. %@NL@%
  10742. %@CR:MQPa2002@%%@4@%This table lists the key or key combination along with the decimal%@EH@%
  10743. extended-key code. This information is also available in the on-line help
  10744. (in a form that can be pasted directly into your program).%@NL@%
  10745. %@CR:MQPaT100@%%@NL@%
  10746. %@TH:   63   4000  2 17 16 17 16 10 @%
  10747. %@AB@%Key Type         Extended Key    Code             Extended Key    Code%@AE@%
  10748.  
  10749. %@AB@%Arrow%@AE@%            UP               72              DOWN             80
  10750.                  LEFT             75              RIGHT            77
  10751.                  PGUP             73              PGDN             81
  10752.                  HOME             71              END              79
  10753.                  INS              82              DEL              83
  10754.  
  10755. %@AB@%CTRL +%@AE@%           CTRL+PRTSC      114              CTRL+HOME       119
  10756. %@AB@%Arrow%@AE@%            CTRL+LEFT       115              CTRL+END        117
  10757.                  CTRL+RIGHT      116
  10758.                  CTRL+PGUP       132              Null key          3
  10759.                  CTRL+PGDN       118              SHIFT+TAB        15
  10760.  
  10761. %@AB@%ALT +%@AE@%            ALT+A            30              ALT+N            49
  10762. %@AB@%Letter%@AE@%           ALT+B            48              ALT+O            24
  10763.                  ALT+C            46              ALT+P            25
  10764.                  ALT+D            32              ALT+Q            16
  10765.                  ALT+E            18              ALT+R            19
  10766.                  ALT+F            33              ALT+S            31
  10767.                  ALT+G            34              ALT+T            20
  10768.                  ALT+H            35              ALT+U            22
  10769.                  ALT+I            23              ALT+V            47
  10770.                  ALT+J            36              ALT+W            17
  10771.                  ALT+K            37              ALT+X            45
  10772.                  ALT+L            38              ALT+Y            21
  10773.                  ALT+M            50              ALT+Z            44
  10774.  
  10775. %@AB@%ALT +%@AE@%            ALT+1           120              ALT+6           125
  10776. %@AB@%Number%@AE@%           ALT+2           121              ALT+7           126
  10777.                  ALT+3           122              ALT+8           127
  10778.                  ALT+4           123              ALT+9           128
  10779.                  ALT+5           124              ALT+0           129
  10780.                  ALT+MINUS       130              ALT+=           131
  10781.  
  10782. %@AB@%Function%@AE@%         F1               59              F6               64
  10783.                  F2               60              F7               65
  10784.                  F3               61              F8               66
  10785.                  F4               62              F9               67
  10786.                  F5               63              F10              68
  10787.  
  10788. %@AB@%SHIFT +%@AE@%          SHIFT+F1         84              SHIFT+F6         89
  10789. %@AB@%Function%@AE@%         SHIFT+F2         85              SHIFT+F7         90
  10790.                  SHIFT+F3         86              SHIFT+F8         91
  10791.                  SHIFT+F4         87              SHIFT+F9         92
  10792.                  SHIFT+F5         88              SHIFT+F10        93
  10793.  
  10794. %@AB@%CTRL +%@AE@%           CTRL+F1          94              CTRL+F6          99
  10795. %@AB@%Function%@AE@%         CTRL+F2          95              CTRL+F7         100
  10796.                  CTRL+F3          96              CTRL+F8         101
  10797.                  CTRL+F4          97              CTRL+F9         102
  10798.                  CTRL+F5          98              CTRL+F10        103
  10799.  
  10800. %@AB@%ALT +%@AE@%            ALT+F1          104              ALT+F6          109
  10801. %@AB@%Function%@AE@%         ALT+F2          105              ALT+F7          110
  10802.                  ALT+F3          106              ALT+F8          111
  10803.                  ALT+F4          107              ALT+F9          112
  10804.                  ALT+F5          108              ALT+F10         113
  10805.  
  10806. %@AB@%Extended%@AE@%         F11             133              F12             134
  10807. %@AB@%Function%@AE@%         SHIFT+F11       135              SHIFT+F12       136
  10808.                  CTRL+F11        137              CTRL+F12        138
  10809.                  ALT+F11         139              ALT+F12         140
  10810. %@TE:   63   4000  2 17 16 17 16 10 @%
  10811. %@NL@%
  10812. %@NL@%
  10813. %@NL@%
  10814. %@CR:MQPb0000@%%@1@%%@AB@%Appendix B  Compiler Directives%@AE@%%@EH@%%@NL@%
  10815. ───────────────────────────────────────────────────────────────────────────%@NL@%
  10816. %@NL@%
  10817. %@CR:MQPb0001@%%@4@%QuickPascal uses a variety of compiler directives to affect code output.%@EH@%
  10818. They can be classed as%@NL@%
  10819. %@NL@%
  10820. %@CR:MQPb0002@%  ■  Switch Directives (on and off switches that control compiler options)%@NL@%
  10821. %@NL@%
  10822.   ■  Parameter Directives (commands that require numbers or a file name)%@NL@%
  10823. %@NL@%
  10824.   ■  Conditional Directives (commands that compile specific portions of the%@NL@%
  10825.      source file, depending if certain conditions are met)%@NL@%
  10826. %@NL@%
  10827. %@CR:MQPb0003@%%@4@%Compiler directives can be specified in the source file, in the QuickPascal%@EH@%
  10828. environment, or at the DOS command line.%@NL@%
  10829. %@NL@%
  10830. %@NL@%
  10831. %@CR:MQPb1000@%%@2@%%@AB@%B.1  Switch Directives%@AE@%%@EH@%%@NL@%
  10832. %@NL@%
  10833. %@CR:MQPb1001@%%@4@%Switch directives are identified by a single letter enclosed in braces. The%@EH@%
  10834. letter is preceded by a dollar sign ($) and is followed by either a plus (+)
  10835. that enables the switch, or a minus (-) that disables it. If you do not
  10836. specify a switch directive, the default setting will automatically be used.%@NL@%
  10837. %@NL@%
  10838. %@CR:MQPb1002@%%@4@%A space must not come between the left brace and the dollar sign. If one%@EH@%
  10839. does, the compiler considers the line to be a comment. This is useful for
  10840. commenting out directives.%@NL@%
  10841. %@NL@%
  10842. %@CR:MQPb1003@%%@4@%Multiple switches can be set in a single statement. For example,%@EH@%%@NL@%
  10843. %@NL@%
  10844.      {$A-,S+,R-,V+}%@NL@%
  10845. %@NL@%
  10846. %@CR:MQPb1004@%%@4@%Certain switch directives must be declared globally at the beginning of the%@EH@%
  10847. program, just after the header. That is, they must appear before any data
  10848. declaration or code. Other switch directives can occur locally, anywhere
  10849. within the source file.%@NL@%
  10850. %@NL@%
  10851. %@CR:MQPb1005@%%@4@%The individual switch directives are described below.%@EH@%%@NL@%
  10852. %@NL@%
  10853. %@CR:MQPb1006@%%@4@%%@AB@%Align Data%@AE@%%@EH@%%@NL@%
  10854. %@NL@%
  10855. %@CR:MQPb1007@%%@AB@%{$A+}%@AE@% or %@AB@%{$A-}%@AE@%%@NL@%
  10856. Default: %@AB@%{$A+}%@AE@%%@NL@%
  10857. Type: Local%@NL@%
  10858. %@NL@%
  10859. %@CR:MQPb1008@%%@4@%Changes from byte alignment to word alignment of typed constants and%@EH@%
  10860. variables. When the align data directive is enabled, all typed constants and
  10861. variables larger than one byte are aligned on a machine-word boundary.
  10862. Although word alignment does not affect program execution on the 8088
  10863. processor, on 80x86 processors, programs can execute faster since word-sized
  10864. items are accessed in one memory cycle.%@NL@%
  10865. %@NL@%
  10866. %@CR:MQPb1009@%%@4@%When the directive is disabled, no alignment occurs, and all typed constants%@EH@%
  10867. and variables are placed at the next available memory address.%@NL@%
  10868. %@NL@%
  10869. %@CR:MQPb100A@%%@4@%%@AB@%Boolean Evaluation%@AE@%%@EH@%%@NL@%
  10870. %@NL@%
  10871. %@CR:MQPb100B@%%@AB@%{$B+}%@AE@% or %@AB@%{$B-}%@AE@%%@NL@%
  10872. Default: %@AB@%{$B-}%@AE@%%@NL@%
  10873. Type: Local%@NL@%
  10874. %@NL@%
  10875. %@CR:MQPb100C@%%@4@%Determines which type of code will be generated for the Boolean %@AB@%AND%@AE@% and %@AB@%OR%@AE@%%@EH@%
  10876. operators. When the directive is enabled, code is created for the complete
  10877. Boolean expression, even if the result is already known. If the directive is
  10878. disabled (the default), the evaluation stops as soon as the result becomes
  10879. evident, resulting in faster programs. Enable this switch when the second or
  10880. subsequent operands in the Boolean expression include a procedure or
  10881. function call that needs to be executed, regardless of the value of the
  10882. first operand.%@NL@%
  10883. %@NL@%
  10884. %@CR:MQPb100D@%%@4@%%@AB@%Debug Information%@AE@%%@EH@%%@NL@%
  10885. %@NL@%
  10886. %@CR:MQPb100E@%%@AB@%{$D+}%@AE@% or %@AB@%{$D-}%@AE@%%@NL@%
  10887. Default: %@AB@%{$D+}%@AE@%%@NL@%
  10888. Type: Global%@NL@%
  10889. %@NL@%
  10890. %@CR:MQPb100F@%%@4@%Inserts debugging information into your compiled program. When the directive%@EH@%
  10891. is enabled, you can use the QuickPascal debugger to single step through code
  10892. to view VARS, you need %@AB@%{$L+}%@AE@%. Additionally, when a run-time error is
  10893. reported, QuickPascal will move to the line in the source code that caused
  10894. the error.%@NL@%
  10895. %@NL@%
  10896. %@CR:MQPb100G@%%@4@%%@AB@%FAR Calls%@AE@%%@EH@%%@NL@%
  10897. %@NL@%
  10898. %@CR:MQPb100H@%%@AB@%{$F+}%@AE@% or %@AB@%{$F-}%@AE@%%@NL@%
  10899. Default: %@AB@%{$F-}%@AE@%%@NL@%
  10900. Type: Local%@NL@%
  10901. %@NL@%
  10902. %@CR:MQPb100I@%%@4@%Determines which model is used for compiled procedures and functions. When%@EH@%
  10903. the FAR calls directive is enabled, procedures and functions always use the
  10904. FAR call model. If the directive is disabled, QuickPascal determines the
  10905. call model based on location of the routine. If the procedure or function is
  10906. declared in the %@AB@%INTERFACE%@AE@% portion of a unit, the FAR model is used.
  10907. Otherwise, the NEAR model is used.%@NL@%
  10908. %@NL@%
  10909. %@CR:MQPb100J@%%@4@%See Chapter 12%@BO:   517ed@%, "Advanced Topics," for a full discussion of FAR and NEAR%@EH@%
  10910. call models.%@NL@%
  10911. %@NL@%
  10912. %@CR:MQPb100K@%%@4@%%@AB@%I/O Checking%@AE@%%@EH@%%@NL@%
  10913. %@NL@%
  10914. %@CR:MQPb100L@%%@AB@%{$I+}%@AE@% or %@AB@%{$I-}%@AE@%%@NL@%
  10915. Default: %@AB@%{$I+}%@AE@%%@NL@%
  10916. Type: Local%@NL@%
  10917. %@NL@%
  10918. %@CR:MQPb100M@%%@4@%Generates code that examines the result of an input/output procedure. If an%@EH@%
  10919. I/O error occurs while the directive is enabled, the program displays a
  10920. run-time error and terminates. If the I/O checking directive is disabled,
  10921. you should use the %@AB@%IOResult%@AE@% function to check for I/O errors. See Chapter 9%@BO:   3efa5@%,
  10922. "Text Files," for more information on I/O routines.%@NL@%
  10923. %@NL@%
  10924. %@CR:MQPb100N@%%@4@%%@AB@%Local Symbol Data%@AE@%%@EH@%%@NL@%
  10925. %@NL@%
  10926. %@CR:MQPb100O@%%@AB@%{$L+}%@AE@% or %@AB@%{$L-}%@AE@%%@NL@%
  10927. Default: %@AB@%{$L+}%@AE@%%@NL@%
  10928. Type: Global%@NL@%
  10929. %@NL@%
  10930. %@CR:MQPb100P@%%@4@%Generates symbol information in your compiled code. When the directive is%@EH@%
  10931. enabled, you can use the QuickPascal debugger to examine and modify
  10932. variables within your program. The local symbol data directive is used in
  10933. conjunction with the debug information directive. If the debug information
  10934. directive is disabled, the local symbol data directive is automatically
  10935. disabled.%@NL@%
  10936. %@NL@%
  10937. %@CR:MQPb100Q@%%@4@%%@AB@%Method Checking%@AE@%%@EH@%%@NL@%
  10938. %@NL@%
  10939. %@CR:MQPb100R@%%@AB@%{$M+}%@AE@% or %@AB@%{$M-}%@AE@%%@NL@%
  10940. Default: %@AB@%{$M-}%@AE@%%@NL@%
  10941. Type: Global%@NL@%
  10942. %@NL@%
  10943. %@CR:MQPb100S@%%@4@%Determines if memory for an object has been allocated before an object's%@EH@%
  10944. method is called. If the directive is enabled and an object hasn't had
  10945. memory allocated, a run-time error is generated. You should always enable
  10946. the method-checking directive when you are using objects and programming in
  10947. object-oriented Pascal.%@NL@%
  10948. %@NL@%
  10949. %@CR:MQPb100T@%%@4@%%@AB@%Numeric Processing%@AE@%%@EH@%%@NL@%
  10950. %@NL@%
  10951. %@CR:MQPb100U@%%@AB@%{$N+}%@AE@% or %@AB@%{$N-}%@AE@%%@NL@%
  10952. Default: %@AB@%{$N-}%@AE@%%@NL@%
  10953. Type: Global%@NL@%
  10954. %@NL@%
  10955. %@CR:MQPb100V@%%@4@%Specifies which model of floating-point code is generated by the compiler.%@EH@%
  10956. When the directive is enabled, all floating-point calculations are performed
  10957. by the 80x87 math coprocessor. If the directive is disabled, all real type
  10958. calculations are performed in software using the run-time libraries.%@NL@%
  10959. %@NL@%
  10960. %@CR:MQPb100W@%%@4@%When the directive is enabled (%@AB@%$N+%@AE@%), the resulting program will run only on%@EH@%
  10961. machines equipped with 80x87 coprocessors. Attempting to run the program on
  10962. a computer that is not 80x87-equipped generates an error message informing
  10963. the user that a coprocessor is required.%@NL@%
  10964. %@NL@%
  10965. %@CR:MQPb100X@%%@4@%When the directive is disabled (%@AB@%$N-%@AE@%), the resulting program will run on any%@EH@%
  10966. machine, whether or not it has a coprocessor. However, the code will not use
  10967. the coprocessor, even if present. Use of the %@AB@%$N-%@AE@% directive involves some
  10968. differences in the way %@AB@%Extended%@AE@% and %@AB@%Comp%@AE@% data types are handled. See Chapter
  10969. 2%@BO:    bdde@%, "Programming Basics," for more information.%@NL@%
  10970. %@NL@%
  10971. %@CR:MQPb100Y@%%@4@%%@AB@%Range Checking%@AE@%%@EH@%%@NL@%
  10972. %@NL@%
  10973. %@CR:MQPb100Z@%%@AB@%{$R+}%@AE@% or %@AB@%{$R-}%@AE@%%@NL@%
  10974. Default: %@AB@%{$R-}%@AE@%%@NL@%
  10975. Type: Local%@NL@%
  10976. %@NL@%
  10977. %@CR:MQPb100a@%%@4@%Generates code that determines if all array and string indexing expressions%@EH@%
  10978. are within bounds, and all assignments to scalar and subrange variables are
  10979. within range. If range checking fails while the directive is enabled, a
  10980. run-time error is reported. The range checking directive should be used
  10981. only for debugging, as it decreases program performance and increases
  10982. program size.%@NL@%
  10983. %@NL@%
  10984. %@CR:MQPb100b@%%@4@%%@AB@%Stack Checking%@AE@%%@EH@%%@NL@%
  10985. %@NL@%
  10986. %@CR:MQPb100c@%%@AB@%{$S+}%@AE@% or %@AB@%{$S-}%@AE@%
  10987. Default: %@AB@%{$S+}%@AE@%
  10988. Type: Local%@NL@%
  10989. %@NL@%
  10990. %@CR:MQPb100d@%%@4@%Creates code that checks whether enough space remains on the stack for local%@EH@%
  10991. variables before executing a procedure or function. If a stack overflow
  10992. occurs when the directive is enabled, the program displays a run-time error
  10993. message and terminates.%@NL@%
  10994. %@NL@%
  10995. %@CR:MQPb100e@%%@4@%%@AB@%VAR String Checking%@AE@%%@EH@%%@NL@%
  10996. %@NL@%
  10997. %@CR:MQPb100f@%%@AB@%{$V+}%@AE@% or %@AB@%{$V-}%@AE@%
  10998. Default: %@AB@%{$V+}%@AE@%
  10999. Type: Local%@NL@%
  11000. %@NL@%
  11001. %@CR:MQPb100g@%%@4@%Compares the declared type of a %@AB@%VAR%@AE@% type string parameter with the string%@EH@%
  11002. type actually being passed as a parameter when the directive is enabled. The
  11003. types must be identical. If the directive is disabled, no type checking is
  11004. performed.%@NL@%
  11005. %@NL@%
  11006. %@NL@%
  11007. %@CR:MQPb2000@%%@2@%%@AB@%B.2  Parameter Directives%@AE@%%@EH@%%@NL@%
  11008. %@NL@%
  11009. %@CR:MQPb2001@%%@4@%Parameter directives instruct the compiler to take a certain action, based%@EH@%
  11010. on parameters that are passed to the compiler. A space always separates the
  11011. single directive letter and the parameter.%@NL@%
  11012. %@NL@%
  11013. %@CR:MQPb2002@%%@4@%The individual parameter directives are described below.%@EH@%%@NL@%
  11014. %@NL@%
  11015. %@CR:MQPb2003@%%@4@%%@AB@%Include%@AE@%%@EH@%%@NL@%
  11016. %@NL@%
  11017. %@CR:MQPb2004@%%@AB@%{$I%@AE@%%@AI@%Filename%@AE@%%@AB@%}%@AE@%%@NL@%
  11018. Type: Local%@NL@%
  11019. %@NL@%
  11020. %@CR:MQPb2005@%%@4@%Includes a named source file in the compilation immediately after the%@EH@%
  11021. directive. QuickPascal assumes the .INC extension if none is specified. If
  11022. the include file is in a different path from the one defined in the
  11023. QuickPascal Environment command in the Options menu, you must type in the
  11024. entire pathname.%@NL@%
  11025. %@NL@%
  11026. %@CR:MQPb2006@%%@4@%You cannot have an include file within a %@AB@%BEGIN...END%@AE@% block.%@EH@%%@NL@%
  11027. %@NL@%
  11028. %@CR:MQPb2007@%%@4@%%@AB@%Link%@AE@%%@EH@%%@NL@%
  11029. %@NL@%
  11030. %@CR:MQPb2008@%%@AB@%{$L%@AE@%%@AI@%ObjectFile%@AE@%%@AB@%}%@AE@%%@NL@%
  11031. Type: Local%@NL@%
  11032. %@NL@%
  11033. %@CR:MQPb2009@%%@4@%Links a relocatable object file containing external routines written in%@EH@%
  11034. assembly language. If the .OBJ file is in a different path from the one
  11035. defined in the QuickPascal Environment command in the Options menu, you must
  11036. type in the entire pathname. For additional information on linking with
  11037. assembly language, see Chapter 12%@BO:   517ed@%, "Advanced Topics."%@NL@%
  11038. %@NL@%
  11039. %@CR:MQPb200A@%%@4@%%@AB@%Memory%@AE@%%@EH@%%@NL@%
  11040. %@NL@%
  11041. %@CR:MQPb200B@%%@AB@%{$M%@AE@%%@AI@%StackSize%@AE@%%@AB@%,%@AE@%%@AI@%MinHeap%@AE@%%@AB@%,%@AE@%%@AI@%MaxHeap%@AE@%%@AB@%}%@AE@%%@NL@%
  11042. Default: %@AB@%{$M 16384, 0, 655360}%@AE@%%@NL@%
  11043. Type: Global%@NL@%
  11044. %@NL@%
  11045. %@CR:MQPb200C@%%@4@%Sets stack and heap memory allocationy. Three parameters are passed: stack%@EH@%
  11046. size, minimum heap size, and maximum heap size. Each parameter must be an
  11047. integer within a specific range. See the list of ranges in Table B.1 below.%@NL@%
  11048. %@NL@%
  11049. %@CR:MQPbT100@%%@4@%%@AB@%Table B.1  Minimum and Maximum Memory Allocation Parameters%@AE@%%@EH@%%@NL@%
  11050. %@NL@%
  11051. %@AB@%Parameter      Minimum Value       Maximum Value%@AE@%%@NL@%
  11052. %@NL@%
  11053. %@AI@%StackSize%@AE@%      1024                65520%@NL@%
  11054. %@AI@%MinHeap%@AE@%        0                   655360%@NL@%
  11055. %@AI@%MaxHeap%@AE@%        MinHeap             655360%@NL@%
  11056. %@NL@%
  11057. %@NL@%
  11058. %@CR:MQPb3000@%%@2@%%@AB@%B.3  Conditional Directives%@AE@%%@EH@%%@NL@%
  11059. %@NL@%
  11060. %@CR:MQPb3001@%%@4@%Conditional directives produce different code from the same source file if a%@EH@%
  11061. conditional identifier is defined. The conditional directives are, in
  11062. effect, a variation of the %@AB@%IF%@AE@% control statement. If a condition is true,
  11063. code between the %@AB@%{$IF%@AE@%%@AI@%xxx%@AE@%%@AI@%Condition%@AE@%%@AB@%}%@AE@% and %@AB@%{$ENDIF}%@AE@% directives is compiled. If
  11064. the condition is false, the compiler skips the code between the two
  11065. directives. An optional %@AB@%{$ELSE}%@AE@% directive provides further control.%@NL@%
  11066. %@NL@%
  11067. %@AS@%     {$DEFINE DEBUG}%@NL@%
  11068. %@NL@%
  11069. %@AS@%     {$IFDEF DEBUG}%@NL@%
  11070. %@AS@%         Writeln('tax: ', tax, 'total: ', total)%@NL@%
  11071. %@AS@%     {$ELSE}%@NL@%
  11072. %@AS@%         Writeln('amount: ',tax + total);%@NL@%
  11073. %@AS@%     {ENDIF}%@NL@%
  11074. %@NL@%
  11075. %@CR:MQPb3002@%%@4@%You define and undefine identifiers with the %@AB@%{$DEFINE%@AE@% %@AI@%Name%@AE@%%@AB@%}%@AE@% and%@EH@%
  11076. %@AB@%{$UNDEF%@AE@% %@AI@%Name%@AE@%%@AB@%}%@AE@% directives. Conditional identifiers are treated separately
  11077. from similarly named program constants and variables. In addition to
  11078. user-defined control identifiers, QuickPascal incorporates several
  11079. predefined identifiers (listed in Table B.2 below).%@NL@%
  11080. %@NL@%
  11081. %@CR:MQPbT200@%%@4@%%@AB@%Table B.2  QuickPascal Predefined Conditional Identifiers%@AE@%%@EH@%%@NL@%
  11082. %@NL@%
  11083. %@AB@%Conditional%@AE@%%@NL@%
  11084. %@AB@%Identifier     State                      Purpose%@AE@%%@NL@%
  11085. %@NL@%
  11086. %@AB@%VER10%@AE@%          Defined                    Indicates the compiler version%@NL@%
  11087. %@AB@%MSDOS%@AE@%          Defined                    Indicates the operating system%@NL@%
  11088. %@AB@%CPU86%@AE@%          Defined                    Indicates the 80x86 CPU family%@NL@%
  11089. %@AB@%CPU87%@AE@%          Defined if an 80x87 is     Indicates the use of an 80x87 CPU%@NL@%
  11090.                present at compile time%@NL@%
  11091. %@NL@%
  11092. %@CR:MQPb3003@%%@4@%Conditional directives may be placed anywhere in the source file. The%@EH@%
  11093. individual conditional directives are described below.%@NL@%
  11094. %@NL@%
  11095. %@CR:MQPb3004@%%@4@%%@AB@%DEFINE%@AE@%%@EH@%%@NL@%
  11096. %@NL@%
  11097. %@CR:MQPb3005@%%@AB@%{$DEFINE%@AE@% %@AI@%Identifier%@AE@%%@AB@%}%@AE@%%@NL@%
  11098. %@NL@%
  11099. %@CR:MQPb3006@%%@4@%Defines a conditional identifier. The identifier exists through the rest of%@EH@%
  11100. the compilation, or until undefined with the UNDEF directive.%@NL@%
  11101. %@NL@%
  11102. %@CR:MQPb3007@%%@AB@%%@4@%ELSE%@AE@%%@EH@%%@NL@%
  11103. %@NL@%
  11104. %@CR:MQPb3008@%%@AB@%{$ELSE}%@AE@%%@NL@%
  11105. %@NL@%
  11106. %@CR:MQPb3009@%%@4@%Compiles or skips the source based on the identifier in the preceding IF%@EH@%
  11107. directive.%@NL@%
  11108. %@NL@%
  11109. %@CR:MQPb300A@%%@4@%%@AB@%ENDIF%@AE@%%@EH@%%@NL@%
  11110. %@NL@%
  11111. %@CR:MQPb300B@%%@AB@%{$ENDIF}%@AE@%%@NL@%
  11112. %@NL@%
  11113. %@CR:MQPb300C@%%@4@%Ends the conditional compilation associated with the most recent IF%@EH@%
  11114. directive.%@NL@%
  11115. %@NL@%
  11116. %@CR:MQPb300D@%%@4@%%@AB@%IFDEF%@AE@%%@EH@%%@NL@%
  11117. %@NL@%
  11118. %@CR:MQPb300E@%%@AB@%{$IFDEF%@AE@% %@AI@%Identifier%@AE@%%@AB@%}%@AE@%%@NL@%
  11119. %@NL@%
  11120. %@CR:MQPb300F@%%@4@%Compiles the source that follows if the identifier has been defined.%@EH@%%@NL@%
  11121. %@NL@%
  11122. %@CR:MQPb300G@%%@4@%%@AB@%IFNDEF%@AE@%%@EH@%%@NL@%
  11123. %@NL@%
  11124. %@CR:MQPb300H@%%@AB@%{$IFNDEF%@AE@% %@AI@%Identifier%@AE@%%@AB@%}%@AE@%%@NL@%
  11125. %@NL@%
  11126. %@CR:MQPb300I@%%@4@%Compiles the source following the directive if the identifier is undefined.%@EH@%%@NL@%
  11127. %@NL@%
  11128. %@CR:MQPb300J@%%@4@%%@AB@%IFOPT%@AE@%%@EH@%%@NL@%
  11129. %@NL@%
  11130. %@CR:MQPb300K@%%@AB@%{$IFOPT%@AE@% %@AI@%Switch%@AE@%%@AB@%}%@AE@%%@NL@%
  11131. %@NL@%
  11132. %@CR:MQPb300L@%%@4@%Compiles the source that follows if the specified switch has been set as%@EH@%
  11133. described. For example,%@NL@%
  11134. %@NL@%
  11135. %@AS@%     {$IFOPT I-}%@NL@%
  11136. %@AS@%         result := IOResult;%@NL@%
  11137. %@AS@%     {$ENDIF}%@NL@%
  11138. %@NL@%
  11139. %@CR:MQPb300M@%%@4@%%@AB@%UNDEF%@AE@%%@EH@%%@NL@%
  11140. %@NL@%
  11141. %@CR:MQPb300N@%%@AB@%{$UNDEF%@AE@%%@AI@% Identifier%@AE@%%@AB@%}%@AE@%%@NL@%
  11142. %@NL@%
  11143. %@CR:MQPb300O@%%@4@%Undefines a previously declared identifier for the remainder of the%@EH@%
  11144. compilation or until the identifier is once again defined.%@NL@%
  11145. %@NL@%
  11146. %@NL@%
  11147. %@CR:MQPc0000@%%@1@%%@AB@%Appendix C  Summary of Standard Units%@AE@%%@EH@%%@NL@%
  11148. ───────────────────────────────────────────────────────────────────────────%@NL@%
  11149. %@NL@%
  11150. %@CR:MQPc0001@%%@4@%QuickPascal comes with several standard units that expand your programs'%@EH@%
  11151. capabilities. These units──collections of variables, constants, data types,
  11152. procedures, and functions──enhance your control over the screen and text,
  11153. DOS routines, printer use, and graphics. QuickPascal automatically inserts
  11154. the %@AB@%System%@AE@% standard unit whenever you compile a program. %@AB@%System%@AE@% supplies all
  11155. of the QuickPascal standard procedures and functions.%@NL@%
  11156. %@NL@%
  11157. %@CR:MQPc0010@%%@4@%%@AB@%Crt Unit%@AE@%%@EH@%%@NL@%
  11158. %@NL@%
  11159. %@CR:MQPc0011@%%@4@%The %@AB@%Crt%@AE@% unit extends your control of the screen, keyboard input, and sound.%@EH@%
  11160. %@AB@%Crt%@AE@% has procedures and functions that manipulate the screen colors, cursor
  11161. position, text attributes, and windows. It also contains functions for
  11162. checking keyboard activity and lets you turn the internal speaker on and
  11163. off.%@NL@%
  11164. %@NL@%
  11165. %@CR:MQPc0020@%%@4@%%@AB@%Dos Unit%@AE@%%@EH@%%@NL@%
  11166. %@NL@%
  11167. %@CR:MQPc0021@%%@4@%The %@AB@%Dos%@AE@% unit gives you access to file-handling and operating-system%@EH@%
  11168. routines. Programs that need to access DOS procedures and functions in order
  11169. to set or get the time and date, to determine disk sizes and available disk
  11170. space, or to control software interrupts can do so with the %@AB@%Dos%@AE@% unit. Other
  11171. procedures and functions within the %@AB@%Dos%@AE@% unit let you manipulate file names
  11172. and file attributes.%@NL@%
  11173. %@NL@%
  11174. %@CR:MQPc0030@%%@4@%%@AB@%Printer Unit%@AE@%%@EH@%%@NL@%
  11175. %@NL@%
  11176. %@CR:MQPc0031@%%@4@%The %@AB@%Printer%@AE@% unit lets you use a printer. It declares a text file, "Lst," and%@EH@%
  11177. sends the output of %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@% calls that use Lst to the printer port
  11178. rather than to the screen. %@AB@%Printer%@AE@% accepts any type of formatting available
  11179. to %@AB@%Write%@AE@% and %@AB@%Writeln%@AE@%. (Lst directs its output to LPT1. Make sure your
  11180. printer connects to that port.)%@NL@%
  11181. %@NL@%
  11182. %@CR:MQPc0040@%%@4@%%@AB@%MSGraph Unit%@AE@%%@EH@%%@NL@%
  11183. %@NL@%
  11184. %@CR:MQPc0041@%%@4@%The %@AB@%MSGraph%@AE@% unit provides graphics in QuickPascal. It  supports a large%@EH@%
  11185. number of procedures and functions that draw geometric shapes, fill figures
  11186. with colors and patterns, manipulate images, create windows and viewports,
  11187. and display text in various sizes and type styles. You can display graphics
  11188. on a wide variety of video adapters and can choose the best combination of
  11189. screen resolution and colors for your needs.%@NL@%
  11190. %@NL@%
  11191. %@CR:MQPc0050@%%@4@%%@AB@%System Unit%@AE@%%@EH@%%@NL@%
  11192. %@NL@%
  11193. %@CR:MQPc0051@%%@4@%The %@AB@%System%@AE@% unit contains all of the standard procedures and functions%@EH@%
  11194. (%@AB@%Writeln%@AE@%, %@AB@%Pred%@AE@%, %@AB@%Copy%@AE@%, and so on), which you think of as always being
  11195. available. You do not need to include %@AB@%System%@AE@% in the %@AB@%USES%@AE@% list; QuickPascal
  11196. automatically uses the %@AB@%System%@AE@% unit whenever you compile a program.%@NL@%
  11197. %@NL@%
  11198. %@NL@%
  11199. %@CR:MQPd0000@%%@1@%%@AB@%Appendix D  Quick Reference Guide%@AE@%%@EH@%%@NL@%
  11200. ───────────────────────────────────────────────────────────────────────────%@NL@%
  11201. %@NL@%
  11202. %@NL@%
  11203. %@CR:MQPd1000@%%@2@%%@AB@%D.1  Keywords, Procedures, and Functions%@AE@%%@EH@%%@NL@%
  11204. %@NL@%
  11205. %@CR:MQPd1001@%%@4@%Use the QP Advisor for complete descriptions and information.%@EH@%%@NL@%
  11206. %@NL@%
  11207. %@CR:MQPd1002@%%@AB@%Abs(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11208. %@NL@%
  11209.      Returns the absolute value of x.%@NL@%
  11210. %@NL@%
  11211. %@AB@%ABSOLUTE%@AE@%%@NL@%
  11212. %@NL@%
  11213.      Declares a variable to reside at a specific memory location.%@NL@%
  11214. %@NL@%
  11215. %@AB@%Addr(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11216. %@NL@%
  11217.      Returns the address of %@AI@%x%@AE@%, where %@AI@%x%@AE@% is any variable, typed constant,%@NL@%
  11218.      procedure identifier, or function identifier.%@NL@%
  11219. %@NL@%
  11220. %@AB@%AND%@AE@%%@NL@%
  11221. %@NL@%
  11222.      Acts as logical or bitwise %@AB@%AND%@AE@% operator.%@NL@%
  11223. %@NL@%
  11224. %@AB@%Append(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%)%@AE@%%@NL@%
  11225. %@NL@%
  11226.      Opens an existing %@AB@%Text%@AE@% file %@AI@%FileVariable%@AE@% to append additional text.%@NL@%
  11227. %@NL@%
  11228. %@AB@%ArcTan(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11229. %@NL@%
  11230.      Returns the arctangent of x.%@NL@%
  11231. %@NL@%
  11232. %@AB@%ARRAY [%@AE@% %@AI@%Ranges%@AE@%%@AB@% ] OF%@AE@% %@AI@%Type%@AE@%%@NL@%
  11233. %@NL@%
  11234.      Defines %@AI@%Type%@AE@% as the base type, and %@AI@%Ranges%@AE@% as the range of indices, for%@NL@%
  11235.      an array type, variable, or constant.%@NL@%
  11236. %@NL@%
  11237. %@AB@%Assign(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%Name%@AE@% %@AB@%)%@AE@%%@NL@%
  11238. %@NL@%
  11239.      Assigns the file variable %@AI@%FileVariable%@AE@% to the external file named in%@NL@%
  11240.      %@AI@%Name%@AE@%.%@NL@%
  11241. %@NL@%
  11242. %@AB@%BEGIN%@AE@%%@NL@%
  11243. %@NL@%
  11244.      Starts a statement block.%@NL@%
  11245. %@NL@%
  11246. %@AB@%BlockRead(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%Buffer%@AE@%%@AB@%,%@AE@% %@AI@%Count%@AE@% «%@AB@%,%@AE@% %@AI@%RecordsRead%@AE@%» %@AB@%)%@AE@%%@NL@%
  11247. %@NL@%
  11248.      Reads %@AI@%Count%@AE@% number of records into memory from the file specified by%@NL@%
  11249.      %@AI@%FileVariable%@AE@%, beginning with the first byte occupied by %@AI@%Buffer%@AE@%.%@NL@%
  11250.      Optionally %@AB@%BlockRead%@AE@% returns the number of records successfully read in%@NL@%
  11251.      %@AI@%RecordsRead%@AE@%.%@NL@%
  11252. %@NL@%
  11253. %@AB@%BlockWrite(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%Buffer%@AE@%%@AB@%,%@AE@% %@AI@%Count%@AE@% «%@AB@%,%@AE@% %@AI@%RecordsWritten%@AE@%» %@AB@%)%@AE@%%@NL@%
  11254. %@NL@%
  11255.      Writes %@AI@%Count%@AE@% number of records from memory to the file specified by%@NL@%
  11256.      %@AI@%FileVariable%@AE@%, beginning with the first byte occupied by %@AI@%Buffer%@AE@%.%@NL@%
  11257.      Optionally %@AB@%BlockWrite%@AE@% returns the number of records successfully%@NL@%
  11258.      written in %@AI@%RecordsWritten%@AE@%.%@NL@%
  11259. %@NL@%
  11260. %@AB@%CASE%@AE@% %@AI@%Selector%@AE@% %@AB@%OF%@AE@% %@AI@%Constant%@AE@%%@AB@%:%@AE@% %@AI@%StatementBlock%@AE@%%@AB@%;%@AE@% ... %@AB@%END%@AE@%%@NL@%
  11261. %@NL@%
  11262.      Executes the %@AI@%StatementBlock%@AE@% whose %@AI@%Constant%@AE@% matches %@AI@%Selector%@AE@%.%@NL@%
  11263. %@NL@%
  11264. %@AB@%ChDir(%@AE@% %@AI@%NewDir%@AE@% %@AB@%)%@AE@%%@NL@%
  11265. %@NL@%
  11266.      Makes %@AI@%NewDir%@AE@% the current directory.%@NL@%
  11267. %@NL@%
  11268. %@AB@%Chr(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11269. %@NL@%
  11270.      Returns the ASCII character with ordinal value %@AI@%x%@AE@%.%@NL@%
  11271. %@NL@%
  11272. %@AB@%Close(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%%@NL@%
  11273. %@NL@%
  11274.      Closes the open file specified by the file variable %@AI@%FileVariable%@AE@%.%@NL@%
  11275. %@NL@%
  11276. %@AB@%Concat(%@AE@% %@AI@%Str1%@AE@% «%@AB@%,%@AE@% %@AI@%Str2%@AE@% %@AB@%,%@AE@% %@AI@% Str3%@AE@%%@AB@%...%@AE@%» %@AB@%)%@AE@%%@NL@%
  11277. %@NL@%
  11278.      Returns the  argument strings (%@AI@%Str1%@AE@%, %@AI@%Str2%@AE@%, etc.) as a single string.%@NL@%
  11279. %@NL@%
  11280. %@AB@%CONST%@AE@%%@NL@%
  11281. %@NL@%
  11282.      Starts a constant definition section.%@NL@%
  11283. %@NL@%
  11284. %@AB@%Copy(%@AE@% %@AI@%String%@AE@%%@AB@%,%@AE@% %@AI@%Start%@AE@%%@AB@%,%@AE@% %@AI@%Count%@AE@% %@AB@%)%@AE@%%@NL@%
  11285. %@NL@%
  11286.      Returns a substring of %@AI@%String%@AE@%, %@AI@%Count%@AE@% characters long, beginning with%@NL@%
  11287.      character number %@AI@%Start%@AE@%.%@NL@%
  11288. %@NL@%
  11289. %@AB@%Cos(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11290. %@NL@%
  11291.      Returns the cosine of x.%@NL@%
  11292. %@NL@%
  11293. %@AB@%CSeg%@AE@%%@NL@%
  11294. %@NL@%
  11295.      Returns the value of the CS register.%@NL@%
  11296. %@NL@%
  11297. %@AB@%CSTRING%@AE@% «[%@AI@%Length%@AE@%]»%@NL@%
  11298. %@NL@%
  11299.      Defines a variable or constant as a series of up to 255 characters%@NL@%
  11300.      ending in a null byte, as in the C programming language. The integer%@NL@%
  11301.      %@AI@%Length%@AE@% specifies the maximum length of the string.%@NL@%
  11302. %@NL@%
  11303. %@AB@%Dec(%@AE@% %@AI@%x%@AE@% «%@AB@%,%@AE@% %@AI@%Step%@AE@%» %@AB@%)%@AE@%%@NL@%
  11304. %@NL@%
  11305.      Decrements the variable %@AI@%x%@AE@% by 1; if %@AI@%Step%@AE@% is specified, %@AI@%x%@AE@% is decremented%@NL@%
  11306.      by %@AI@%Step%@AE@%.%@NL@%
  11307. %@NL@%
  11308. %@AB@%Delete(%@AE@% %@AI@%String%@AE@%%@AB@%,%@AE@% %@AI@%Start%@AE@%%@AB@%,%@AE@% %@AI@%Count%@AE@% %@AB@%)%@AE@%%@NL@%
  11309. %@NL@%
  11310.      Returns a copy of %@AI@%String%@AE@% with %@AI@%Count%@AE@% characters removed, beginning with%@NL@%
  11311.      character number %@AI@%Start%@AE@%.%@NL@%
  11312. %@NL@%
  11313. %@AB@%Dispose(%@AE@% %@AI@%p%@AE@% %@AB@%)%@AE@%%@NL@%
  11314. %@NL@%
  11315.      Removes the dynamic variable that %@AI@%p%@AE@% points to and returns the memory to%@NL@%
  11316.      the heap.%@NL@%
  11317. %@NL@%
  11318. %@AB@%DIV%@AE@%%@NL@%
  11319. %@NL@%
  11320.      Acts as the integer division operator. %@AI@%i%@AE@% %@AB@%DIV%@AE@% %@AI@%j%@AE@% returns the quotient of%@NL@%
  11321.      %@AI@%i%@AE@% divided by %@AI@%j%@AE@% rounded to the integer nearest zero.%@NL@%
  11322. %@NL@%
  11323. %@AB@%DO%@AE@%%@NL@%
  11324. %@NL@%
  11325.      Introduces the statement block with %@AB@%WHILE%@AE@%, %@AB@%FOR%@AE@%, and %@AB@%WITH%@AE@%.%@NL@%
  11326. %@NL@%
  11327. %@AB@%DOWNTO%@AE@%%@NL@%
  11328. %@NL@%
  11329.      Indicates that a %@AB@%FOR%@AE@% statement's end value is less than its start value%@NL@%
  11330.      and that the control variable is decremented by 1 with each iteration.%@NL@%
  11331. %@NL@%
  11332. %@AB@%DSeg%@AE@%%@NL@%
  11333. %@NL@%
  11334.      Returns the value of the DS register.%@NL@%
  11335. %@NL@%
  11336. %@AB@%ELSE%@AE@%%@NL@%
  11337. %@NL@%
  11338.      Begins the default clause in an %@AB@%IF...THEN...ELSE%@AE@% or %@AB@%CASE%@AE@% statement.%@NL@%
  11339. %@NL@%
  11340. %@AB@%END%@AE@%%@NL@%
  11341. %@NL@%
  11342.      Ends a statement block.%@NL@%
  11343. %@NL@%
  11344. %@AB@%Eof%@AE@% «%@AB@%(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%»%@NL@%
  11345. %@NL@%
  11346.      Returns the end-of-file status for the file %@AI@%FileVariable%@AE@%. %@AB@%Eof%@AE@% returns%@NL@%
  11347.      %@AB@%True%@AE@% if the end of the file has been reached, otherwise it returns%@NL@%
  11348.      %@AB@%False%@AE@%. If you omit %@AI@%FileVariable%@AE@%, %@AB@%Eof%@AE@% checks the status of the standard%@NL@%
  11349.      input file.%@NL@%
  11350. %@NL@%
  11351. %@AB@%Eoln%@AE@% «%@AB@%(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%»%@NL@%
  11352. %@NL@%
  11353.      Returns the end-of-line status. %@AB@%Eoln%@AE@% returns %@AB@%True%@AE@% if the end of the%@NL@%
  11354.      line has been reached, otherwise it returns %@AB@%False%@AE@%. If you omit%@NL@%
  11355.      %@AI@%FileVariable%@AE@%, %@AB@%Eoln%@AE@% checks the status of the standard input file.%@NL@%
  11356. %@NL@%
  11357. %@AB@%Erase(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%%@NL@%
  11358. %@NL@%
  11359.      Erases the file referred to by %@AI@%FileVariable%@AE@%.%@NL@%
  11360. %@NL@%
  11361. %@AB@%Exit%@AE@%%@NL@%
  11362. %@NL@%
  11363.      In a procedure or function, causes control to return to the main%@NL@%
  11364.      program. In the main program, %@AB@%Exit%@AE@% halts program execution.%@NL@%
  11365. %@NL@%
  11366. %@AB@%Exp (%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11367. %@NL@%
  11368.      Returns the exponential of %@AI@%x%@AE@%, that is, the value %@AI@%e%@AE@% raised to the power%@NL@%
  11369.      of %@AI@%x%@AE@%.%@NL@%
  11370. %@NL@%
  11371. %@AB@%EXTERNAL%@AE@%%@NL@%
  11372. %@NL@%
  11373.      Identifies a separately compiled procedure or function written in%@NL@%
  11374.      assembly language.%@NL@%
  11375. %@NL@%
  11376. %@AB@%FILE%@AE@% «%@AB@%OF%@AE@% %@AI@%ComponentType%@AE@%»%@NL@%
  11377. %@NL@%
  11378.      Declares a file type composed of values of type %@AI@%ComponentType%@AE@%.%@NL@%
  11379. %@NL@%
  11380. %@AB@%FilePos(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%%@NL@%
  11381. %@NL@%
  11382.      Returns the current position of an open file referred to by file%@NL@%
  11383.      variable %@AI@%FileVariable%@AE@%.%@NL@%
  11384. %@NL@%
  11385. %@AB@%FileSize(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%%@NL@%
  11386. %@NL@%
  11387.      Returns the size (in bytes) of an open file referred to by file%@NL@%
  11388.      variable %@AI@%FileVariable%@AE@%.%@NL@%
  11389. %@NL@%
  11390. %@AB@%FillChar(%@AE@% %@AI@%Variable%@AE@%%@AB@%,%@AE@% %@AI@%Count%@AE@%%@AB@%,%@AE@% %@AI@%Character%@AE@% %@AB@%)%@AE@%%@NL@%
  11391. %@NL@%
  11392.      Fills %@AI@%Count%@AE@% contiguous bytes of memory with %@AI@%Character%@AE@% (either an ASCII%@NL@%
  11393.      value or a literal character enclosed in single quotes), starting with%@NL@%
  11394.      the first byte occupied by %@AI@%Variable%@AE@%.%@NL@%
  11395. %@NL@%
  11396. %@AB@%Flush(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%%@NL@%
  11397. %@NL@%
  11398.      Writes to disk the buffer of the text file referred to by %@AI@%FileVariable%@AE@%.%@NL@%
  11399. %@NL@%
  11400. %@AB@%FOR%@AE@% %@AI@%ControlVariable%@AE@% %@AB@%:=%@AE@% %@AI@%StartVal%@AE@% {%@AB@%TO%@AE@%|%@AB@%DOWNTO%@AE@%} %@AI@%EndVal%@AE@% %@AB@%DO%@AE@%%@NL@%
  11401.       %@AI@%StatementBlock%@AE@%%@NL@%
  11402. %@NL@%
  11403.      Executes %@AI@%StatementBlock%@AE@% as long as the value of %@AI@%ControlVariable%@AE@% is%@NL@%
  11404.      between its start value %@AI@%StartVal%@AE@% and its end value %@AI@%EndVal%@AE@%, inclusive.%@NL@%
  11405.      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@%
  11406.      than %@AI@%StartVal%@AE@%. %@AB@%FOR%@AE@% increments (with %@AB@%TO%@AE@%) or decrements (with %@AB@%DOWNTO%@AE@%)%@NL@%
  11407.      %@AI@%ControlVariable%@AE@% by 1 each time it executes %@AI@%StatementBlock%@AE@%.%@NL@%
  11408. %@NL@%
  11409. %@AB@%FORWARD%@AE@%%@NL@%
  11410. %@NL@%
  11411.      Declares a procedure but omits its definition until a second%@NL@%
  11412.      declaration. This permits mutually referencing procedures.%@NL@%
  11413. %@NL@%
  11414. %@AB@%Frac(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11415. %@NL@%
  11416.      Returns the fractional portion of the real number %@AI@%x%@AE@%.%@NL@%
  11417. %@NL@%
  11418. %@AB@%FreeMem(%@AE@% %@AI@%Pointer%@AE@%%@AB@%,%@AE@% %@AI@%Size%@AE@% %@AB@%)%@AE@%%@NL@%
  11419. %@NL@%
  11420.      Frees %@AI@%Size%@AE@% bytes of dynamic memory at address %@AI@%Pointer%@AE@%.%@NL@%
  11421. %@NL@%
  11422. %@AB@%FUNCTION%@AE@% %@AI@%Identifier%@AE@%«%@AB@%(%@AE@%  «%@AB@%VAR%@AE@%» %@AI@%Param1%@AE@%«%@AB@%,%@AE@% %@AI@%Param2 ...%@AE@%» %@AB@%:%@AE@%%@AI@%Ptype1%@AE@%
  11423.          «%@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@%
  11424. %@NL@%
  11425.      Defines a function named %@AI@%Identifier%@AE@% that returns a value of type%@NL@%
  11426.      %@AI@%Typename%@AE@%. Any parameters (%@AI@%Param1%@AE@%, %@AI@%Param2%@AE@%, etc.) to the function must be%@NL@%
  11427.      declared along with their type (%@AI@%Ptype1%@AE@%, %@AI@%Ptype2%@AE@%, etc.). Every function%@NL@%
  11428.      must return a value.%@NL@%
  11429. %@NL@%
  11430. %@AB@%GetDir%@AE@%%@AB@%( %@AE@%%@AI@%Drive%@AE@%%@AB@%,%@AE@% %@AI@%Path%@AE@% %@AB@%)%@AE@%%@NL@%
  11431. %@NL@%
  11432.      Returns the current directory in the string %@AI@%Path%@AE@%, given the integer%@NL@%
  11433.      %@AI@%Drive%@AE@%. Setting %@AI@%Drive%@AE@% to  0 uses the current drive, %@AI@%Drive%@AE@% to 1 uses%@NL@%
  11434.      drive A, %@AI@%Drive%@AE@% to 2 uses drive B, and so on.%@NL@%
  11435. %@NL@%
  11436. %@AB@%GetMem(%@AE@% %@AI@%Pointer%@AE@%%@AB@%,%@AE@% %@AI@%Size%@AE@% %@AB@%)%@AE@%%@NL@%
  11437. %@NL@%
  11438.      Creates a new dynamic variable of %@AI@%Size%@AE@% bytes from heap memory, setting%@NL@%
  11439.      location %@AI@%Pointer%@AE@%.%@NL@%
  11440. %@NL@%
  11441. %@AB@%GOTO%@AE@% %@AI@%LabelName%@AE@%%@NL@%
  11442. %@NL@%
  11443.      Unconditionally transfers program control to the statement at label %@NL@%
  11444.      %@AI@%LabelName%@AE@%.%@NL@%
  11445. %@NL@%
  11446. %@AB@%Halt%@AE@%«%@AB@%(%@AE@% %@AI@%Code%@AE@% %@AB@%)%@AE@%»%@NL@%
  11447. %@NL@%
  11448.      Halts program execution and returns to DOS. You can optionally include%@NL@%
  11449.      the program's exit code.%@NL@%
  11450. %@NL@%
  11451. %@AB@%Hi(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11452. %@NL@%
  11453.      Returns the high-order byte of %@AI@%x%@AE@%, a word or integer.%@NL@%
  11454. %@NL@%
  11455. %@AB@%IF%@AE@% %@AI@%BooleanExpression%@AE@% %@AB@%THEN%@AE@% %@AI@%StatementBlock1%@AE@% «%@AB@%ELSE%@AE@% %@AI@%StatementBlock2%@AE@% »%@NL@%
  11456. %@NL@%
  11457.      Executes %@AI@%StatementBlock1%@AE@% if %@AI@%BooleanExpression%@AE@% is %@AB@%True%@AE@%, otherwise%@NL@%
  11458.      executes %@AI@%StatementBlock2%@AE@%.%@NL@%
  11459. %@NL@%
  11460. %@AB@%IMPLEMENTATION%@AE@%%@NL@%
  11461. %@NL@%
  11462.      Indicates the beginning of the unit section that defines the unit's%@NL@%
  11463.      procedures and functions. The identifiers declared in this section are%@NL@%
  11464.      private.%@NL@%
  11465. %@NL@%
  11466. %@AB@%IN%@AE@%%@NL@%
  11467. %@NL@%
  11468.      Acts as the member-of operator for sets. %@AB@%IN%@AE@% is used to test for the%@NL@%
  11469.      presence of an element in a set.%@NL@%
  11470. %@NL@%
  11471. %@AB@%Inc(%@AE@% %@AI@%x%@AE@%  «%@AB@%,%@AE@% Step» %@AB@%)%@AE@%%@NL@%
  11472. %@NL@%
  11473.      Increments the variable %@AI@%x%@AE@% by 1; if %@AI@%Step%@AE@% is specified, %@AI@%x%@AE@% is incremented%@NL@%
  11474.      by %@AI@%Step%@AE@%.%@NL@%
  11475. %@NL@%
  11476. %@AB@%INHERITED%@AE@%%@NL@%
  11477. %@NL@%
  11478.      Modifies a message to refer to the parent method.%@NL@%
  11479. %@NL@%
  11480. %@AB@%INLINE(%@AE@% %@AI@%MachineCode%@AE@% %@AB@%)%@AE@%%@NL@%
  11481. %@NL@%
  11482.      Defines machine code that is inserted into the program.%@NL@%
  11483. %@NL@%
  11484. %@AB@%Insert(%@AE@% %@AI@%String%@AE@%%@AB@%,%@AE@% %@AI@%SubString%@AE@%%@AB@%,%@AE@% %@AI@%Start%@AE@% %@AB@%)%@AE@%%@NL@%
  11485. %@NL@%
  11486.      Inserts the string %@AI@%SubString%@AE@% into the string %@AI@%String%@AE@%, beginning at%@NL@%
  11487.      character number %@AI@%Start%@AE@%. If the resulting string is more than 255%@NL@%
  11488.      characters long, it is truncated to 255 characters.%@NL@%
  11489. %@NL@%
  11490. %@AB@%Int(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11491. %@NL@%
  11492.      Returns the integral portion of the real number %@AI@%x%@AE@%.%@NL@%
  11493. %@NL@%
  11494. %@AB@%INTERFACE%@AE@%%@NL@%
  11495. %@NL@%
  11496.      Indicates the beginning of the unit section that declares the%@NL@%
  11497.      variables, constants, procedures, and functions available to the%@NL@%
  11498.      calling program.%@NL@%
  11499. %@NL@%
  11500. %@AB@%INTERRUPT%@AE@%%@NL@%
  11501. %@NL@%
  11502.      Declares a procedure as an interrupt procedure. Interrupt procedures%@NL@%
  11503.      may handle program interrupts.%@NL@%
  11504. %@NL@%
  11505. %@AB@%IOResult%@AE@%%@NL@%
  11506. %@NL@%
  11507.      Returns the status of the most recent I/O operation. A status of 0%@NL@%
  11508.      indicates the I/O operation was successful.%@NL@%
  11509. %@NL@%
  11510. %@AB@%LABEL%@AE@% {%@AI@%Identifier%@AE@%| 0..9999}%@NL@%
  11511. %@NL@%
  11512.      Declares the label %@AI@%Identifier%@AE@% or a number. Labels are the destination%@NL@%
  11513.      of %@AB@%GOTO%@AE@% statements.%@NL@%
  11514. %@NL@%
  11515. %@AB@%Length(%@AE@% %@AI@%String%@AE@% %@AB@%)%@AE@%%@NL@%
  11516. %@NL@%
  11517.      Returns the length of the string %@AI@%String%@AE@%.%@NL@%
  11518. %@NL@%
  11519. %@AB@%Ln(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11520. %@NL@%
  11521.      Returns the natural logarithm of %@AI@%x%@AE@%.%@NL@%
  11522. %@NL@%
  11523. %@AB@%Lo(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11524. %@NL@%
  11525.      Returns the low-order byte of %@AI@%x%@AE@%, a word or integer.%@NL@%
  11526. %@NL@%
  11527. %@AB@%Mark(%@AE@% %@AI@%Pointer%@AE@% %@AB@%)%@AE@%%@NL@%
  11528. %@NL@%
  11529.      Saves the current top of the heap in %@AI@%Pointer%@AE@%.%@NL@%
  11530. %@NL@%
  11531. %@AB@%MaxAvail%@AE@%%@NL@%
  11532. %@NL@%
  11533.      Returns the size (in bytes) of the largest continuous block of free%@NL@%
  11534.      memory in the heap.%@NL@%
  11535. %@NL@%
  11536. %@AB@%MemAvail%@AE@%%@NL@%
  11537. %@NL@%
  11538.      Returns the total free memory in the heap in bytes.%@NL@%
  11539. %@NL@%
  11540. %@AB@%Member(%@AE@% %@AI@%ObjectVariable%@AE@%%@AB@%,%@AE@% %@AI@%ClassId%@AE@% %@AB@%)%@AE@%%@NL@%
  11541. %@NL@%
  11542.      Returns %@AB@%True%@AE@% if %@AI@%ObjectVariable%@AE@% is a member of the class %@AI@%ClassId%@AE@%, and%@NL@%
  11543.      %@AB@%False%@AE@% otherwise.%@NL@%
  11544. %@NL@%
  11545. %@AB@%MkDir(%@AE@% %@AI@%NewDir%@AE@% %@AB@%)%@AE@%%@NL@%
  11546. %@NL@%
  11547.      Creates a new directory with the path given in the string %@AI@%NewDir%@AE@%.%@NL@%
  11548. %@NL@%
  11549. %@AB@%MOD%@AE@%%@NL@%
  11550. %@NL@%
  11551.      Acts as the modular division operator. The expression %@AI@%i%@AE@% %@AB@%MOD%@AE@% %@AI@%j%@AE@% returns%@NL@%
  11552.      the remainder of %@AI@%i%@AE@% %@AB@%DIV%@AE@% %@AI@%j%@AE@%.%@NL@%
  11553. %@NL@%
  11554. %@AB@%Move(%@AE@% %@AI@%Source%@AE@%%@AB@%,%@AE@% %@AI@%Destination%@AE@%%@AB@%,%@AE@% %@AI@%Count%@AE@% %@AB@%)%@AE@%%@NL@%
  11555. %@NL@%
  11556.      Copies %@AI@%Count%@AE@% bytes of %@AI@%Source%@AE@% to %@AI@%Destination%@AE@%.%@NL@%
  11557. %@NL@%
  11558. %@AB@%New(%@AE@% %@AI@% Pointer%@AE@%%@AB@%)%@AE@%%@NL@%
  11559. %@NL@%
  11560.      Allocates space for a new dynamic variable in the heap and sets %@AI@%Pointer%@AE@%%@NL@%
  11561.      to the address of the new variable. The type of pointer determines how%@NL@%
  11562.      much memory %@AB@%New%@AE@% allocates.%@NL@%
  11563. %@NL@%
  11564. %@AB@%NIL%@AE@%%@NL@%
  11565. %@NL@%
  11566.      Indicates the value of a pointer that does not point to anything.%@NL@%
  11567. %@NL@%
  11568. %@AB@%NOT%@AE@%%@NL@%
  11569. %@NL@%
  11570.      Acts as the logical or bitwise negation operator.%@NL@%
  11571. %@NL@%
  11572. %@AB@%OBJECT%@AE@%«(%@AI@%Parent%@AE@%)»%@NL@%
  11573. %@NL@%
  11574.      Defines an object type or class, descended from the %@AI@%Parent%@AE@% class.%@NL@%
  11575. %@NL@%
  11576. %@AB@%Odd(%@AE@% %@AI@% x%@AE@% %@AB@%)%@AE@%%@NL@%
  11577. %@NL@%
  11578.      Returns %@AB@%True%@AE@% if the integral %@AI@%x%@AE@% is odd, %@AB@%False%@AE@% if %@AI@%x%@AE@% is even.%@NL@%
  11579. %@NL@%
  11580. %@AB@%OF%@AE@%%@NL@%
  11581. %@NL@%
  11582.      Identifies the base type of an %@AB@%ARRAY%@AE@%, %@AB@%FILE%@AE@%, or %@AB@%SET%@AE@%, or introduces the%@NL@%
  11583.      constant list found in a %@AB@%CASE%@AE@% statement.%@NL@%
  11584. %@NL@%
  11585. %@AB@%Ofs(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11586. %@NL@%
  11587.      Returns the offset of %@AI@%x%@AE@%, a variable, typed constant, procedure, or%@NL@%
  11588.      function name.%@NL@%
  11589. %@NL@%
  11590. %@AB@%OR%@AE@%%@NL@%
  11591. %@NL@%
  11592.      Acts as the logical or bitwise %@AB@%OR%@AE@% operator.%@NL@%
  11593. %@NL@%
  11594. %@AB@%Ord(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11595. %@NL@%
  11596.      Returns the ordinal number of %@AI@%x%@AE@% (an ordinal-type variable).%@NL@%
  11597. %@NL@%
  11598. %@AB@%OVERRIDE%@AE@%%@NL@%
  11599. %@NL@%
  11600.      Redefines a parent method to do something new.%@NL@%
  11601. %@NL@%
  11602. %@AB@%PACKED%@AE@%%@NL@%
  11603. %@NL@%
  11604.      Required by standard Pascal. Serves only to distinguish types in%@NL@%
  11605.      QuickPascal.%@NL@%
  11606. %@NL@%
  11607. %@AB@%ParamCount%@AE@%%@NL@%
  11608. %@NL@%
  11609.      Returns the number of command-line parameters.%@NL@%
  11610. %@NL@%
  11611. %@AB@%ParamStr(%@AE@% %@AI@%i%@AE@% %@AB@%)%@AE@%%@NL@%
  11612. %@NL@%
  11613.      Returns a string that is the %@AI@%i%@AE@% th command-line parameter. Parameter%@NL@%
  11614.      number 0 is the program path in DOS versions 3.1 and later.%@NL@%
  11615. %@NL@%
  11616. %@AB@%Pi%@AE@%%@NL@%
  11617. %@NL@%
  11618.      Returns the value Pi (3.1415926535897932385). The precision of the%@NL@%
  11619.      value varies, depending on the floating-point hardware present.%@NL@%
  11620. %@NL@%
  11621. %@AB@%Pointer%@AE@%%@NL@%
  11622. %@NL@%
  11623.      Defines a variable as a generic pointer type. A variable of type%@NL@%
  11624.      %@AB@%POINTER%@AE@% must be assigned to a variable of a specific pointer type%@NL@%
  11625.      before it can be dereferenced.%@NL@%
  11626. %@NL@%
  11627. %@AB@%Pos(%@AE@% %@AI@%SubString%@AE@%%@AB@%,%@AE@% %@AI@%String%@AE@% %@AB@%)%@AE@%%@NL@%
  11628. %@NL@%
  11629.      Returns the starting position of string %@AI@%SubString%@AE@% in string %@AI@%String%@AE@%.%@NL@%
  11630. %@NL@%
  11631. %@AB@%Pred%@AE@%( %@AI@%x%@AE@% )%@NL@%
  11632. %@NL@%
  11633.      Returns the predecessor of %@AI@%x%@AE@% in the list of values of its ordinal type.%@NL@%
  11634. %@NL@%
  11635. %@AB@%PROCEDURE%@AE@% %@AI@%Identifier%@AE@%«%@AB@%( %@AE@%«%@AB@%VAR%@AE@%» %@AI@%Param1%@AE@%«%@AB@%,%@AE@% %@AI@%Param2%@AE@% ...» %@AB@%:%@AE@% %@AI@%Ptype1%@AE@%
  11636.                     «%@AB@%;%@AE@% «%@AB@%VAR%@AE@%» %@AI@%Param3%@AE@%«%@AB@%,%@AE@% %@AI@%Param4%@AE@% ...» %@AB@%:%@AE@% %@AI@%Ptype2%@AE@% %@AB@%...%@AE@%»%@AB@%)%@AE@%»%@NL@%
  11637. %@NL@%
  11638.      Defines a procedure named %@AI@%Identifier%@AE@%. Any parameters (%@AI@%Param1%@AE@%, %@AI@%Param2%@AE@%,%@NL@%
  11639.      etc.) to the procedure must be declared along with their type (%@AI@%Ptype1%@AE@%,%@NL@%
  11640.      %@AI@%Ptype2%@AE@%, etc.).%@NL@%
  11641. %@NL@%
  11642. %@AB@%PROGRAM%@AE@% «%@AI@%ProgName%@AE@%»%@NL@%
  11643. %@NL@%
  11644.      Declares a program with the name %@AI@%ProgName%@AE@%.%@NL@%
  11645. %@NL@%
  11646. %@AB@%Ptr(%@AE@% %@AI@%Seg%@AE@%%@AB@%,%@AE@% %@AI@%Off%@AE@% %@AB@%)%@AE@%%@NL@%
  11647. %@NL@%
  11648.      Converts a segment and offset to a pointer address;%@AI@%Seg%@AE@% and %@AI@%Off%@AE@% are both%@NL@%
  11649.      of type %@AB@%Word%@AE@%.%@NL@%
  11650. %@NL@%
  11651. %@AB@%Random%@AE@%«%@AB@%(%@AE@% %@AI@%Limit%@AE@% %@AB@%)%@AE@%»%@NL@%
  11652. %@NL@%
  11653.      Returns a random real number between 0 and 1, or a random whole number%@NL@%
  11654.      between 0 and %@AI@%Limit%@AE@%.%@NL@%
  11655. %@NL@%
  11656. %@AB@%Randomize%@AE@%%@NL@%
  11657. %@NL@%
  11658.      Initializes the random number generator.%@NL@%
  11659. %@NL@%
  11660. %@AB@%Read(%@AE@%«%@AI@%FileVariable%@AE@%%@AB@%,%@AE@%»%@AI@%Var1%@AE@% «%@AB@%,%@AE@% %@AI@%Var2%@AE@% ...»%@AB@%)%@AE@%%@NL@%
  11661. %@NL@%
  11662.      Reads one or more values from the standard input device or, optionally,%@NL@%
  11663.      from the file specifier %@AI@%FileVariable%@AE@%.%@NL@%
  11664. %@NL@%
  11665. %@AB@%Readln(%@AE@%«%@AI@%FileVariable%@AE@%%@AB@%,%@AE@%»%@AI@%Var1%@AE@% «%@AB@%,%@AE@% %@AI@%Var2%@AE@% ... »%@AB@%)%@AE@%%@NL@%
  11666. %@NL@%
  11667.      Executes the %@AB@%Read%@AE@% procedure, then skips to the beginning of the next%@NL@%
  11668.      line of the text file specified by %@AI@%FileVariable%@AE@%.%@NL@%
  11669. %@NL@%
  11670. %@AB@%RECORD%@AE@% %@AI@%FieldList%@AE@% %@AB@%END%@AE@%%@NL@%
  11671. %@NL@%
  11672.      Creates a compound variable consisting of the items listed in%@NL@%
  11673.      %@AI@%FieldList%@AE@%. The different fields in a record can have different types.%@NL@%
  11674. %@NL@%
  11675. %@AB@%Release(%@AE@% %@AI@%Pointer%@AE@% %@AB@%)%@AE@%%@NL@%
  11676. %@NL@%
  11677.      Returns the value of the heap-top pointer to %@AI@%Pointer%@AE@%, which was%@NL@%
  11678.      previously obtained by %@AB@%Mark%@AE@%.%@NL@%
  11679. %@NL@%
  11680. %@AB@%Rename(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%NewName%@AE@% %@AB@%)%@AE@%%@NL@%
  11681. %@NL@%
  11682.      Renames the external file specified by file variable %@AI@%FileVariable%@AE@% to%@NL@%
  11683.      the name string %@AI@%NewName%@AE@%.%@NL@%
  11684. %@NL@%
  11685. %@AB@%REPEAT%@AE@% %@AI@%StatementBlock%@AE@% %@AB@%UNTIL%@AE@% %@AI@%BooleanExpression%@AE@%%@NL@%
  11686. %@NL@%
  11687.      Executes %@AI@%StatementBlock%@AE@% as long as %@AI@%BooleanExpression%@AE@% remains %@AB@%False%@AE@%.%@NL@%
  11688.      When %@AI@%BooleanExpression%@AE@% becomes %@AB@%True%@AE@%, control passes to the statement%@NL@%
  11689.      following the %@AB@%UNTIL%@AE@% statement.%@NL@%
  11690. %@NL@%
  11691. %@AB@%Reset(%@AE@% %@AI@%FileVariable%@AE@% «%@AB@%,%@AE@% %@AI@%Size%@AE@%» %@AB@%)%@AE@%%@NL@%
  11692. %@NL@%
  11693.      Opens the file specified by %@AI@%FileVariable%@AE@% with a data transfer unit size%@NL@%
  11694.      of %@AI@%Size%@AE@%.%@NL@%
  11695. %@NL@%
  11696. %@AB@%Rewrite(%@AE@% %@AI@%FileVariable%@AE@% «%@AB@%,%@AE@% %@AI@%Size%@AE@%» %@AB@%)%@AE@%%@NL@%
  11697. %@NL@%
  11698.      Creates and opens a new file %@AI@%FileVariable%@AE@%, with a data transfer unit%@NL@%
  11699.      size of %@AI@%Size%@AE@%. If %@AI@%FileVariable%@AE@% already exists, it is truncated to a%@NL@%
  11700.      length of zero.%@NL@%
  11701. %@NL@%
  11702. %@AB@%RmDir(%@AE@% %@AI@%Dir%@AE@% %@AB@%)%@AE@%%@NL@%
  11703. %@NL@%
  11704.      Removes the empty directory named %@AI@%Dir%@AE@%.%@NL@%
  11705. %@NL@%
  11706. %@AB@%Round(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11707. %@NL@%
  11708.      Rounds the real number %@AI@%x%@AE@% to the nearest whole number.%@NL@%
  11709. %@NL@%
  11710. %@AB@%RunError%@AE@%«%@AB@%(%@AE@% %@AI@%ErrorNum%@AE@% %@AB@%)%@AE@%»%@NL@%
  11711. %@NL@%
  11712.      Halts program execution with the run-time error number %@AI@%ErrorNum%@AE@%, or%@NL@%
  11713.      run-time error 0 if %@AI@%ErrorNum%@AE@% is not specified.%@NL@%
  11714. %@NL@%
  11715. %@AB@%Seek(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%Pos%@AE@% %@AB@%)%@AE@%%@NL@%
  11716. %@NL@%
  11717.      Moves the current position of the file specified by %@AI@%FileVariable%@AE@% to the%@NL@%
  11718.      position %@AI@%Pos%@AE@%.%@NL@%
  11719. %@NL@%
  11720. %@AB@%SeekEof%@AE@% «%@AB@%(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%)%@AE@%»%@NL@%
  11721. %@NL@%
  11722.      Returns the end-of-file status for the text file specified%@NL@%
  11723.      by %@AI@%FileVariable%@AE@%, skipping blanks, tabs, and end-of-line markers. The%@NL@%
  11724.      actual file position does not change.%@NL@%
  11725. %@NL@%
  11726. %@AB@%SeekEoln%@AE@%«%@AB@%(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%»%@NL@%
  11727. %@NL@%
  11728.      Returns the end-of-line status for the text file specified by%@NL@%
  11729.      %@AI@%FileVariable%@AE@%, skipping blanks and tabs.%@NL@%
  11730. %@NL@%
  11731. %@AB@%Seg(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11732. %@NL@%
  11733.      Returns the segment containing %@AI@%x%@AE@%, a variable, typed constant,%@NL@%
  11734.      procedure, or function name.%@NL@%
  11735. %@NL@%
  11736. %@AB@%Self%@AE@%%@NL@%
  11737. %@NL@%
  11738.      Refers to the object that received a message, used by methods.%@NL@%
  11739. %@NL@%
  11740. %@AB@%SET OF%@AE@% %@AI@%OrdinalType%@AE@%%@NL@%
  11741. %@NL@%
  11742.      Identifies %@AI@%OrdinalType%@AE@% as the base type for a set type, constant, or%@NL@%
  11743.      variable.%@NL@%
  11744. %@NL@%
  11745. %@AB@%SetTextBuf(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%Buffer%@AE@% «%@AB@%,%@AE@% %@AI@%Size%@AE@%» %@AB@%)%@AE@%%@NL@%
  11746. %@NL@%
  11747.      Assigns the text file %@AI@%FileVariable%@AE@% a buffer of %@AI@%Size%@AE@% bytes in memory%@NL@%
  11748.      starting at %@AI@%Buffer%@AE@%. If %@AI@%Size%@AE@% is omitted, %@AI@%SizeOf%@AE@%%@AB@%(%@AE@% %@AI@%Buffer%@AE@%%@AB@%)%@AE@% is assumed.%@NL@%
  11749. %@NL@%
  11750. %@AB@%SHL%@AE@%%@NL@%
  11751. %@NL@%
  11752.      Acts as the bitwise shift-left operator. The expression %@AI@%i%@AE@% %@AB@%SHL%@AE@% %@AI@%j%@AE@% shifts%@NL@%
  11753.      the value of %@AI@%i%@AE@% to the left by %@AI@%j%@AE@% bits.%@NL@%
  11754. %@NL@%
  11755. %@AB@%SHR%@AE@%%@NL@%
  11756. %@NL@%
  11757.      Acts as the bitwise shift-right operator. The expression %@AI@%i%@AE@% %@AB@%SHR%@AE@% %@AI@%j%@AE@% shifts%@NL@%
  11758.      the value of %@AI@%i%@AE@% to the right by %@AI@%j%@AE@% bits.%@NL@%
  11759. %@NL@%
  11760. %@AB@%Sin(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11761. %@NL@%
  11762.      Returns the sine of %@AI@%x%@AE@%.%@NL@%
  11763. %@NL@%
  11764. %@AB@%SizeOf(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11765. %@NL@%
  11766.      Returns the size of the variable, typed constant, or type %@AI@%x%@AE@% in bytes.%@NL@%
  11767. %@NL@%
  11768. %@AB@%SPtr%@AE@%%@NL@%
  11769. %@NL@%
  11770.      Returns the value of the SP register, the current offset of the stack%@NL@%
  11771.      pointer in the stack segment.%@NL@%
  11772. %@NL@%
  11773. %@AB@%Sqr(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11774. %@NL@%
  11775.      Returns the square of %@AI@%x%@AE@%.%@NL@%
  11776. %@NL@%
  11777. %@AB@%Sqrt(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11778. %@NL@%
  11779.      Returns the square root of %@AI@%x%@AE@%, a positive integer or real number.%@NL@%
  11780. %@NL@%
  11781. %@AB@%SSeg%@AE@%%@NL@%
  11782. %@NL@%
  11783.      Returns the value of the SS register, the stack segment address of the%@NL@%
  11784.      stack pointer.%@NL@%
  11785. %@NL@%
  11786. %@AB@%Str(%@AE@% %@AI@% Number%@AE@%«%@AB@%:%@AE@% %@AI@%Width%@AE@%«%@AB@%:%@AE@% %@AI@%Decimals%@AE@%»»%@AB@%,%@AE@% %@AI@%String%@AE@%%@AB@%)%@AE@%%@NL@%
  11787. %@NL@%
  11788.      Converts the numeric value %@AI@%Number%@AE@% to the string %@AI@%String%@AE@%. The arguments%@NL@%
  11789.      %@AI@%Width%@AE@% and %@AI@%Decimals%@AE@% specify the total width and number of decimal places%@NL@%
  11790.      that will appear in the string.%@NL@%
  11791. %@NL@%
  11792. %@AB@%STRING%@AE@%« %@AB@%[%@AE@% %@AI@%Length%@AE@%%@AB@%]%@AE@% »%@NL@%
  11793. %@NL@%
  11794.      Defines a variable or constant as a series of up to 255 characters. The%@NL@%
  11795.      integer %@AI@%Length%@AE@% specifies the maximum length of the string.%@NL@%
  11796. %@NL@%
  11797. %@AB@%Succ(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11798. %@NL@%
  11799.      Returns the successor to %@AI@%x%@AE@% in the list of values of its ordinal type.%@NL@%
  11800. %@NL@%
  11801. %@AB@%Swap(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11802. %@NL@%
  11803.      Exchanges the high- and low-order bytes of %@AI@%x%@AE@%, an integer or word.%@NL@%
  11804. %@NL@%
  11805. %@AB@%THEN%@AE@% %@AI@%StatementBlock%@AE@%%@NL@%
  11806. %@NL@%
  11807.      Used in the second half of an %@AB@%IF...THEN%@AE@% statement. If the condition in%@NL@%
  11808.      the %@AB@%IF%@AE@% portion of the statement is %@AB@%True%@AE@%, the statements in%@NL@%
  11809.      %@AI@%StatementBlock%@AE@% execute.%@NL@%
  11810. %@NL@%
  11811. %@AB@%TO%@AE@%%@NL@%
  11812. %@NL@%
  11813.      Indicates that a %@AB@%FOR%@AE@% statement's ending value is greater than its%@NL@%
  11814.      starting value and that the control variable will be incremented by%@NL@%
  11815.      one.%@NL@%
  11816. %@NL@%
  11817. %@AB@%Trunc(%@AE@% %@AI@%x%@AE@% %@AB@%)%@AE@%%@NL@%
  11818. %@NL@%
  11819.      Truncates a real value %@AI@%x%@AE@% to an integer.%@NL@%
  11820. %@NL@%
  11821. %@AB@%Truncate(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%%@NL@%
  11822. %@NL@%
  11823.      Truncates the file specified by %@AI@%FileVariable%@AE@% at the current file%@NL@%
  11824.      position.%@NL@%
  11825. %@NL@%
  11826. %@AB@%TYPE%@AE@%%@NL@%
  11827. %@NL@%
  11828.      Begins a type definition section.%@NL@%
  11829. %@NL@%
  11830. %@AB@%UNIT%@AE@% %@AI@%Identifier%@AE@%%@NL@%
  11831. %@NL@%
  11832.      Identifies the code that follows as a unit and gives the unit the name%@NL@%
  11833.      %@AI@%Identifier.%@AE@%%@NL@%
  11834. %@NL@%
  11835. %@AB@%UNTIL%@AE@% %@AI@%BooleanExpression%@AE@%%@NL@%
  11836. %@NL@%
  11837.      Terminates a %@AB@%REPEAT%@AE@% statement when %@AI@%BooleanExpression%@AE@% becomes %@AB@%True%@AE@%.%@NL@%
  11838. %@NL@%
  11839. %@AB@%UpCase(%@AE@% %@AI@%Char%@AE@% %@AB@%)%@AE@%%@NL@%
  11840. %@NL@%
  11841.      Returns character %@AI@%Char%@AE@% in uppercase.%@NL@%
  11842. %@NL@%
  11843. %@AB@%USES%@AE@% %@AI@%Identifier%@AE@%«%@AB@%,%@AE@% %@AI@%Identifier%@AE@%»...%@NL@%
  11844. %@NL@%
  11845.      Identifies units required by the program to resolve references to%@NL@%
  11846.      identifiers defined within the units.%@NL@%
  11847. %@NL@%
  11848. %@AB@%Val(%@AE@% %@AI@%String%@AE@%%@AB@%,%@AE@% %@AI@%Number%@AE@%%@AB@%,%@AE@% %@AI@%ErrorPosition%@AE@% %@AB@%)%@AE@%%@NL@%
  11849. %@NL@%
  11850.      Converts the numeric string %@AI@%String%@AE@% to its numeric representation%@NL@%
  11851.      %@AI@%Number%@AE@%. If %@AI@%String%@AE@% does not represent a number, %@AI@%ErrorPosition%@AE@% returns%@NL@%
  11852.      the position of the first offending character.%@NL@%
  11853. %@NL@%
  11854. %@AB@%VAR%@AE@%%@NL@%
  11855. %@NL@%
  11856.      Begins a variable declaration section or declares a variable parameter.%@NL@%
  11857. %@NL@%
  11858. %@AB@%WHILE%@AE@% %@AI@%BooleanExpression%@AE@% %@AB@%DO%@AE@% %@AI@%StatementBlock%@AE@%%@NL@%
  11859. %@NL@%
  11860.      Executes %@AI@%StatementBlock%@AE@% as long as %@AI@%BooleanExpression%@AE@% remains %@AB@%True%@AE@%. When%@NL@%
  11861.      %@AI@%BooleanExpression%@AE@% becomes %@AB@%False%@AE@%, control passes to the statement%@NL@%
  11862.      following %@AI@%StatementBlock%@AE@%.%@NL@%
  11863. %@NL@%
  11864. %@AB@%WITH%@AE@% %@AI@%RecordName1%@AE@% «%@AB@%,%@AE@% %@AI@%RecordName2%@AE@% %@AB@%...%@AE@%»%@AB@%DO%@AE@% %@AI@%StatementBlock%@AE@%%@NL@%
  11865. %@NL@%
  11866.      Allows statements within %@AI@%StatementBlock%@AE@% to refer to the fields of one%@NL@%
  11867.      or more records without specifying the names of the records%@NL@%
  11868.      (%@AI@%RecordName1%@AE@%, %@AI@%RecordName2%@AE@%...).%@NL@%
  11869. %@NL@%
  11870. %@AB@%Write(%@AE@%«%@AI@%FileVariable%@AE@%%@AB@%,%@AE@%»%@AI@%Var1%@AE@%«%@AB@%,%@AE@% %@AI@%Var2%@AE@%%@AB@%...%@AE@%» %@AB@%)%@AE@%%@NL@%
  11871. %@NL@%
  11872.      Writes one or more values to the standard output device or to the file%@NL@%
  11873.      specified by %@AI@%FileVariable%@AE@%.%@NL@%
  11874. %@NL@%
  11875. %@AB@%Writeln(%@AE@%«%@AI@%FileVariable%@AE@% %@AB@%,%@AE@%»%@AI@%Var1%@AE@%«%@AB@%,%@AE@% %@AI@%Var2%@AE@%%@AB@%...%@AE@%» %@AB@%)%@AE@%%@NL@%
  11876. %@NL@%
  11877.      Executes the %@AB@%Write%@AE@% procedure, then sends an end-of-line marker to the%@NL@%
  11878.      standard output device or the file specified by a %@AI@%FileVariable%@AE@%.%@NL@%
  11879. %@NL@%
  11880. %@AB@%XOR%@AE@%%@NL@%
  11881. %@NL@%
  11882.      Acts as the logical or bitwise exclusive-or operator.%@NL@%
  11883. %@NL@%
  11884. %@NL@%
  11885. %@CR:MQPd2000@%%@2@%%@AB@%D.2  Crt Procedures and Functions%@AE@%%@EH@%%@NL@%
  11886. %@NL@%
  11887. %@CR:MQPd2001@%%@AB@%AssignCrt(%@AE@% %@AI@%FileVariable%@AE@% %@AB@%)%@AE@%%@NL@%
  11888. %@NL@%
  11889.      Associates a %@AB@%Text%@AE@% file variable %@AI@%FileVariable%@AE@% with the CRT device%@NL@%
  11890.      (screen).%@NL@%
  11891. %@NL@%
  11892. %@AB@%ClrEol%@AE@%%@NL@%
  11893. %@NL@%
  11894.      Clears a line from the cursor to the end of the line.%@NL@%
  11895. %@NL@%
  11896. %@AB@%ClrScr%@AE@%%@NL@%
  11897. %@NL@%
  11898.      Clears the window and moves the cursor to the upper left corner.%@NL@%
  11899. %@NL@%
  11900. %@AB@%Delay(%@AE@% %@AI@%Microseconds%@AE@%%@AB@%)%@AE@%%@NL@%
  11901. %@NL@%
  11902.      Pauses program execution for a specified length of time.%@NL@%
  11903. %@NL@%
  11904. %@AB@%DelLine%@AE@%%@NL@%
  11905. %@NL@%
  11906.      Deletes the line at the current cursor location.%@NL@%
  11907. %@NL@%
  11908. %@AB@%GotoXY(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@% y%@AE@% %@AB@%)%@AE@%%@NL@%
  11909. %@NL@%
  11910.      Moves the cursor to designated column and row.%@NL@%
  11911. %@NL@%
  11912. %@AB@%HighVideo%@AE@%%@NL@%
  11913. %@NL@%
  11914.      Turns on high-intensity video for the current foreground color.%@NL@%
  11915. %@NL@%
  11916. %@AB@%InsLine%@AE@%%@NL@%
  11917. %@NL@%
  11918.      Inserts a blank line at the current cursor location.%@NL@%
  11919. %@NL@%
  11920. %@AB@%KeyPressed%@AE@%%@NL@%
  11921. %@NL@%
  11922.      Returns %@AB@%True%@AE@% if the keyboard buffer contains a character.%@NL@%
  11923. %@NL@%
  11924. %@AB@%LowVideo%@AE@%%@NL@%
  11925. %@NL@%
  11926.      Turns off high-intensity video for the current foreground color.%@NL@%
  11927. %@NL@%
  11928. %@AB@%NormVideo%@AE@%%@NL@%
  11929. %@NL@%
  11930.      Restores the text colors and attributes that were in effect at program%@NL@%
  11931.      start-up.%@NL@%
  11932. %@NL@%
  11933. %@AB@%NoSound%@AE@%%@NL@%
  11934. %@NL@%
  11935.      Turns off the computer's speaker.%@NL@%
  11936. %@NL@%
  11937. %@AB@%ReadKey%@AE@%%@NL@%
  11938. %@NL@%
  11939.      Returns one character from the keyboard buffer but does not echo%@NL@%
  11940.      character on the screen.%@NL@%
  11941. %@NL@%
  11942. %@AB@%Sound(%@AE@% %@AI@%Frequency%@AE@% %@AB@%)%@AE@%%@NL@%
  11943. %@NL@%
  11944.      Generates a tone from the computer's speaker at the specified%@NL@%
  11945.      frequency.%@NL@%
  11946. %@NL@%
  11947. %@AB@%TextBackground(%@AE@% %@AI@%Color%@AE@% %@AB@%)%@AE@%%@NL@%
  11948. %@NL@%
  11949.      Sets the background color for character output.%@NL@%
  11950. %@NL@%
  11951. %@AB@%TextColor(%@AE@% %@AI@%Color%@AE@% %@AB@%)%@AE@%%@NL@%
  11952. %@NL@%
  11953.      Sets the foreground color and blinking attribute for character output.%@NL@%
  11954. %@NL@%
  11955. %@AB@%TextMode(%@AE@% %@AI@%Mode%@AE@% %@AB@%)%@AE@%%@NL@%
  11956. %@NL@%
  11957.      Sets the display to the specified text mode.%@NL@%
  11958. %@NL@%
  11959. %@AB@%WhereX%@AE@%%@NL@%
  11960. %@NL@%
  11961.      Returns the current x-coordinate of the text cursor.%@NL@%
  11962. %@NL@%
  11963. %@AB@%WhereY%@AE@%%@NL@%
  11964. %@NL@%
  11965.      Returns the current y-coordinate of the text cursor.%@NL@%
  11966. %@NL@%
  11967. %@AB@%Window(%@AE@% %@AI@%x1%@AE@%%@AB@%,%@AE@% %@AI@%y1%@AE@%%@AB@%,%@AE@% %@AI@%x2%@AE@%%@AB@%,%@AE@% %@AI@%y2%@AE@% %@AB@%)%@AE@%%@NL@%
  11968. %@NL@%
  11969.      Defines a text display window. The coordinates give the upper left and%@NL@%
  11970.      lower right corners of the window.%@NL@%
  11971. %@NL@%
  11972. %@NL@%
  11973. %@CR:MQPd3000@%%@2@%%@AB@%D.3  Dos Procedures and Functions%@AE@%%@EH@%%@NL@%
  11974. %@NL@%
  11975. %@CR:MQPd3001@%%@AB@%DiskFree(%@AE@% %@AI@%DriveNumber%@AE@% %@AB@%)%@AE@%%@NL@%
  11976. %@NL@%
  11977.      Returns the number of bytes of free space on the specified drive.%@NL@%
  11978. %@NL@%
  11979. %@AB@%DiskSize(%@AE@% %@AI@%DriveNumber%@AE@% %@AB@%)%@AE@%%@NL@%
  11980. %@NL@%
  11981.      Returns the total capacity in bytes of the specified drive.%@NL@%
  11982. %@NL@%
  11983. %@AB@%DosExitCode%@AE@%%@NL@%
  11984. %@NL@%
  11985.      Returns the exit code from a child process.%@NL@%
  11986. %@NL@%
  11987. %@AB@%DosVersion%@AE@%%@NL@%
  11988. %@NL@%
  11989.      Returns the version number of the operating system.%@NL@%
  11990. %@NL@%
  11991. %@AB@%EnvCount%@AE@%%@NL@%
  11992. %@NL@%
  11993.      Returns the number of variables defined in the DOS environment.%@NL@%
  11994. %@NL@%
  11995. %@AB@%EnvStr(%@AE@% %@AI@%EnvironmentStringIndex%@AE@% %@AB@%)%@AE@%%@NL@%
  11996. %@NL@%
  11997.      Returns the value of a variable from the DOS environment.%@NL@%
  11998. %@NL@%
  11999. %@AB@%Exec(%@AE@% %@AI@%ProgramPath%@AE@%%@AB@%,%@AE@% %@AI@%CommandLine%@AE@%%@AB@%)%@AE@%%@NL@%
  12000. %@NL@%
  12001.      Loads and runs a child process while suspending parent process.%@NL@%
  12002. %@NL@%
  12003. %@AB@%FExpand(%@AE@% %@AI@%FilePath%@AE@% %@AB@%)%@AE@%%@NL@%
  12004. %@NL@%
  12005.      Expands a name to a fully qualified DOS path name.%@NL@%
  12006. %@NL@%
  12007. %@AB@%FindFirst(%@AE@% %@AI@%SearchPattern%@AE@%%@AB@%,%@AE@% %@AI@% Attributes%@AE@%%@AB@%,%@AE@% %@AI@%Matched%@AE@%%@AB@%)%@AE@%%@NL@%
  12008. %@NL@%
  12009.      Searches the specified directory for the first file matching the given %@NL@%
  12010.      %@AI@%SearchPattern%@AE@% and set of attributes.%@NL@%
  12011. %@NL@%
  12012. %@AB@%FindNext(%@AE@% %@AI@%Matched%@AE@%%@AB@%)%@AE@%%@NL@%
  12013. %@NL@%
  12014.      Searches the specified directory for the next file matching the%@NL@%
  12015.      %@AI@%SearchPattern%@AE@% and attributes specified in a previous call to %@AB@%FindFirst%@AE@%.%@NL@%
  12016. %@NL@%
  12017. %@AB@%FSearch(%@AE@% %@AI@%FilePath%@AE@%%@AB@%,%@AE@% %@AI@%DirectoryList%@AE@% %@AB@%)%@AE@%%@NL@%
  12018. %@NL@%
  12019.      Searches for a file in a list of directories.%@NL@%
  12020. %@NL@%
  12021. %@AB@%FSplit(%@AE@% %@AI@%FilePath%@AE@%%@AB@%,%@AE@% %@AI@%Directory%@AE@%%@AB@%,%@AE@% %@AI@%FileName%@AE@%%@AB@%,%@AE@% %@AI@%Extension%@AE@% %@AB@%)%@AE@%%@NL@%
  12022. %@NL@%
  12023.      Separates a path name into its directory, basename, and extension%@NL@%
  12024.      parts.%@NL@%
  12025. %@NL@%
  12026. %@AB@%GetCBreak(%@AE@% %@AI@%Breaking%@AE@%%@AB@%)%@AE@%%@NL@%
  12027. %@NL@%
  12028.      Gets the current state of DOS CTRL+BREAK checking.%@NL@%
  12029. %@NL@%
  12030. %@AB@%GetDate(%@AE@% %@AI@%Year%@AE@%%@AB@%,%@AE@% %@AI@%Month%@AE@%%@AB@%,%@AE@% %@AI@%Day%@AE@%%@AB@%,%@AE@% %@AI@%DayOfWeek%@AE@%%@AB@%)%@AE@%%@NL@%
  12031. %@NL@%
  12032.      Gets the current system date.%@NL@%
  12033. %@NL@%
  12034. %@AB@%GetEnv(%@AE@% %@AI@%EnvironmentStringLabel%@AE@% %@AB@%)%@AE@%%@NL@%
  12035. %@NL@%
  12036.      Returns the current value of a DOS environment variable.%@NL@%
  12037. %@NL@%
  12038. %@AB@%GetFAttr(%@AE@% %@AI@% FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%Attribute%@AE@%%@AB@%)%@AE@%%@NL@%
  12039. %@NL@%
  12040.      Gets a file's attributes.%@NL@%
  12041. %@NL@%
  12042. %@AB@%GetFTime(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%TimeStamp%@AE@%%@AB@%)%@AE@%%@NL@%
  12043. %@NL@%
  12044.      Gets the %@AB@%LongInt%@AE@% representing a file's date and time of modification.%@NL@%
  12045. %@NL@%
  12046. %@AB@%GetIntVec(%@AE@% %@AI@%InterruptNumber%@AE@%%@AB@%,%@AE@% %@AI@%Vector%@AE@%%@AB@%)%@AE@%%@NL@%
  12047. %@NL@%
  12048.      Gets the vector address for a given interrupt number.%@NL@%
  12049. %@NL@%
  12050. %@AB@%GetTime(%@AE@% %@AI@%Hour%@AE@%%@AB@%,%@AE@% %@AI@%Minute%@AE@%%@AB@%,%@AE@% %@AI@%Second%@AE@%%@AB@%,%@AE@% %@AI@%Sec100%@AE@%%@AB@%)%@AE@%%@NL@%
  12051. %@NL@%
  12052.      Gets the current system time.%@NL@%
  12053. %@NL@%
  12054. %@AB@%GetVerify(%@AE@% %@AI@%Verifying%@AE@%%@AB@%)%@AE@%%@NL@%
  12055. %@NL@%
  12056.      Gets the current state of the DOS verify flag.%@NL@%
  12057. %@NL@%
  12058. %@AB@%Intr(%@AE@% %@AI@%InterruptNumber%@AE@%%@AB@%,%@AE@% %@AI@%RegisterValues%@AE@% %@AB@%)%@AE@%%@NL@%
  12059. %@NL@%
  12060.      Calls a software interrupt, loading and returning register values.%@NL@%
  12061. %@NL@%
  12062. %@AB@%Keep(%@AE@% %@AI@%ExitCode%@AE@%%@AB@%)%@AE@%%@NL@%
  12063. %@NL@%
  12064.      Terminates a program but keeps it resident in memory.%@NL@%
  12065. %@NL@%
  12066. %@AB@%MsDos(%@AE@% %@AI@%RegisterValues%@AE@% %@AB@%)%@AE@%%@NL@%
  12067. %@NL@%
  12068.      Calls DOS interrupt $21.%@NL@%
  12069. %@NL@%
  12070. %@AB@%PackTime(%@AE@% %@AI@%DateTime%@AE@%%@AB@%,%@AE@% %@AI@%TimeStamp%@AE@%%@AB@%)%@AE@%%@NL@%
  12071. %@NL@%
  12072.      Converts an unpacked %@AI@%DateTime%@AE@% record to a packed %@AB@%LongInt%@AE@% %@AI@%TimeStamp%@AE@%%@NL@%
  12073. %@NL@%
  12074. %@AB@%SetCBreak(%@AE@% %@AI@%Breaking%@AE@%%@AB@%)%@AE@%%@NL@%
  12075. %@NL@%
  12076.      Turns DOS CTRL+BREAK checking on or off.%@NL@%
  12077. %@NL@%
  12078. %@AB@%SetDate(%@AE@% %@AI@%Year%@AE@%%@AB@%,%@AE@% %@AI@%Month%@AE@%%@AB@%,%@AE@% %@AI@%Day%@AE@%%@AB@%)%@AE@%%@NL@%
  12079. %@NL@%
  12080.      Sets the current system date.%@NL@%
  12081. %@NL@%
  12082. %@AB@%SetFAttr(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%Attribute%@AE@%%@AB@%)%@AE@%%@NL@%
  12083. %@NL@%
  12084.      Sets a file's attributes.%@NL@%
  12085. %@NL@%
  12086. %@AB@%SetFTime(%@AE@% %@AI@%FileVariable%@AE@%%@AB@%,%@AE@% %@AI@%TimeStamp%@AE@%%@AB@%)%@AE@%%@NL@%
  12087. %@NL@%
  12088.      Sets a file's date and time of file modification record.%@NL@%
  12089. %@NL@%
  12090. %@AB@%SetIntVec(%@AE@% %@AI@%InterruptNumber%@AE@%%@AB@%,%@AE@% %@AI@%Vector%@AE@%%@AB@%)%@AE@%%@NL@%
  12091. %@NL@%
  12092.      Installs a new interrupt handler. If a program changes an interrupt%@NL@%
  12093.      vector, it must restore it before terminating.%@NL@%
  12094. %@NL@%
  12095. %@AB@%SetTime(%@AE@% %@AI@%Hour%@AE@%%@AB@%,%@AE@% %@AI@%Minute%@AE@%%@AB@%,%@AE@% %@AI@%Second%@AE@%%@AB@%,%@AE@% %@AI@%Sec100%@AE@% %@AB@%)%@AE@%%@NL@%
  12096. %@NL@%
  12097.      Sets the system time.%@NL@%
  12098. %@NL@%
  12099. %@AB@%SetVerify(%@AE@% %@AI@%Verifying%@AE@% %@AB@%)%@AE@%%@NL@%
  12100. %@NL@%
  12101.      Sets the state of the DOS verify flag.%@NL@%
  12102. %@NL@%
  12103. %@AB@%SwapVectors%@AE@%%@NL@%
  12104. %@NL@%
  12105.      Swaps interrupt vectors with previously saved values.%@NL@%
  12106. %@NL@%
  12107. %@AB@%UnpackTime(%@AE@% %@AI@%TimeStamp%@AE@%%@AB@%,%@AE@% %@AI@%DateTime%@AE@% %@AB@%)%@AE@%%@NL@%
  12108. %@NL@%
  12109.      Converts the %@AB@%LongInt%@AE@% %@AI@%TimeStamp%@AE@% argument to an unpacked %@AI@%DateTime%@AE@% record.%@NL@%
  12110. %@NL@%
  12111. %@NL@%
  12112. %@CR:MQPd4000@%%@2@%%@AB@%D.4  Printer Unit Interface%@AE@%%@EH@%%@NL@%
  12113. %@NL@%
  12114. %@CR:MQPd4001@%%@4@%The printer unit does not contain any procedures or functions. It connects%@EH@%
  12115. the file variable Lst with the printer port. Using Lst in a %@AB@%Write%@AE@% or %@AB@%Writeln%@AE@%
  12116. statement sends the text to the printer:%@NL@%
  12117. %@NL@%
  12118.      %@AS@%Write( Lst, 'This text goes to the printer.' );%@AE@%%@NL@%
  12119. %@NL@%
  12120. %@CR:MQPd4002@%%@4@%Lst is a text variable assigned to the file variable %@AB@%PRN%@AE@% and preconnected to%@EH@%
  12121. the LPT1 printer port.%@NL@%
  12122. %@NL@%
  12123. %@NL@%
  12124. %@CR:MQPd5000@%%@2@%%@AB@%D.5  MSGraph Procedures and Functions%@AE@%%@EH@%%@NL@%
  12125. %@NL@%
  12126. %@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@%
  12127. %@NL@%
  12128.      Draws an arc given the bounding rectangle and beginning and ending%@NL@%
  12129.      points in viewport coordinates.%@NL@%
  12130. %@NL@%
  12131. %@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@%
  12132. %@NL@%
  12133.      Draws an arc given the bounding rectangle and beginning and ending%@NL@%
  12134.      points in window coordinates in %@AB@%_WXYCoord%@AE@% records.%@NL@%
  12135. %@NL@%
  12136. %@AB@%_ClearScreen(%@AE@% %@AI@%Area%@AE@% %@AB@%)%@AE@%%@NL@%
  12137. %@NL@%
  12138.      Clears the specified area of the screen.%@NL@%
  12139. %@NL@%
  12140. %@AB@%_DisplayCursor(%@AE@% %@AI@%Toggle%@AE@% %@AB@%)%@AE@%%@NL@%
  12141. %@NL@%
  12142.      Specifies whether to turn the cursor back on or leave it off after%@NL@%
  12143.      executing graphics routines.%@NL@%
  12144. %@NL@%
  12145. %@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@%
  12146. %@NL@%
  12147.      Draws an ellipse given the fill control and bounding rectangle in%@NL@%
  12148.      viewport coordinates.%@NL@%
  12149. %@NL@%
  12150. %@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@%
  12151. %@NL@%
  12152.      Draws an ellipse given the fill control and bounding rectangle in%@NL@%
  12153.      window coordinates.%@NL@%
  12154. %@NL@%
  12155. %@AB@%_Ellipse_wxy(%@AE@% %@AI@%Control%@AE@%%@AB@%,%@AE@% %@AI@%wxy1%@AE@%%@AB@%,%@AE@% %@AI@%wxy2%@AE@%%@AB@%)%@AE@%%@NL@%
  12156. %@NL@%
  12157.      Draws an ellipse given the fill control and bounding rectangle in%@NL@%
  12158.      window coordinates in the %@AB@%_WXYCoord%@AE@% records %@AI@%wxy1%@AE@% and %@AI@%wxy2%@AE@%.%@NL@%
  12159. %@NL@%
  12160. %@AB@%_FloodFill(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%,%@AE@% %@AI@%Boundary%@AE@% %@AB@%)%@AE@%%@NL@%
  12161. %@NL@%
  12162.      Fills an area with the current color and fill mask. If the point (%@AI@%x%@AE@%, %@AI@%y%@AE@%)%@NL@%
  12163.      lies inside the figure, it fills the interior; if (%@AI@%x%@AE@%, %@AI@%y%@AE@%) lies outside%@NL@%
  12164.      the figure, it fills the background. %@AI@%x%@AE@% and %@AI@%y%@AE@% are given in viewport%@NL@%
  12165.      coordinates.%@NL@%
  12166. %@NL@%
  12167. %@AB@%_FloodFill_w(%@AE@% %@AI@%wx%@AE@%%@AB@%,%@AE@% %@AI@%wy%@AE@%%@AB@%,%@AE@% %@AI@%Boundary%@AE@%%@AB@%)%@AE@%%@NL@%
  12168. %@NL@%
  12169.      Fills an area with the current color and fill mask. If the point (%@AI@%x%@AE@%, %@AI@%y%@AE@%)%@NL@%
  12170.      lies inside the figure, it fills the interior; if (%@AI@%x%@AE@%, %@AI@%y%@AE@%) lies outside%@NL@%
  12171.      the figure, it fills the background. %@AI@%wx%@AE@% and %@AI@%wy%@AE@% are given in window%@NL@%
  12172.      coordinates.%@NL@%
  12173. %@NL@%
  12174. %@AB@%_GetActivePage%@AE@%%@NL@%
  12175. %@NL@%
  12176.      Returns the current active page number.%@NL@%
  12177. %@NL@%
  12178. %@AB@%_GetArcInfo(%@AE@% %@AI@%Start%@AE@%%@AB@%,%@AE@% %@AI@%End%@AE@%%@AB@%,%@AE@% %@AI@%Paint%@AE@% %@AB@%)%@AE@%%@NL@%
  12179. %@NL@%
  12180.      Returns information about the most recently drawn %@AB@%_Arc%@AE@% or %@AB@%_Pie%@AE@%. The%@NL@%
  12181.      %@AI@%Start%@AE@% point, %@AI@%End%@AE@% point, and %@AI@%Paint%@AE@% point are returned in %@AB@%_XYCoord%@AE@%%@NL@%
  12182.      records.%@NL@%
  12183. %@NL@%
  12184. %@AB@%_GetBkColor%@AE@%%@NL@%
  12185. %@NL@%
  12186.      Returns the current background color.%@NL@%
  12187. %@NL@%
  12188. %@AB@%_GetColor%@AE@%%@NL@%
  12189. %@NL@%
  12190.      Returns the current color index.%@NL@%
  12191. %@NL@%
  12192. %@AB@%_GetCurrentPosition(%@AE@% %@AI@%xy%@AE@%%@AB@%)%@AE@%%@NL@%
  12193. %@NL@%
  12194.      Returns the current graphics cursor position in viewport coordinates in%@NL@%
  12195.      the %@AB@%_XYCoord%@AE@% record %@AI@%xy%@AE@%.%@NL@%
  12196. %@NL@%
  12197. %@AB@%_GetCurrentPosition_wxy(%@AE@% %@AI@%wxy%@AE@%%@AB@%)%@AE@%%@NL@%
  12198. %@NL@%
  12199.      Returns the current graphics cursor position in window coordinates in%@NL@%
  12200.      the %@AB@%_WXYCoord%@AE@% record %@AI@%wxy%@AE@%.%@NL@%
  12201. %@NL@%
  12202. %@AB@%_GetFillMask(%@AE@% %@AI@%Mask%@AE@%%@AB@%)%@AE@%%@NL@%
  12203. %@NL@%
  12204.      Returns the current fill mask in %@AI@%mask%@AE@%, if one is defined.%@NL@%
  12205. %@NL@%
  12206. %@AB@%_GetFontInfo(%@AE@% %@AI@%FInfo%@AE@%%@AB@%)%@AE@%%@NL@%
  12207. %@NL@%
  12208.      Gets the current font characteristics and returns them in the %@AB@%_FontInfo%@AE@%%@NL@%
  12209.      record %@AI@%FInfo%@AE@%.%@NL@%
  12210. %@NL@%
  12211. %@AB@%_GetGTextExtent(%@AE@% %@AI@%TextString%@AE@%%@AB@%)%@AE@%%@NL@%
  12212. %@NL@%
  12213.      Returns the pixel width required to print the string %@AI@%TextString%@AE@% in the%@NL@%
  12214.      current font with the %@AB@%_OutGText%@AE@% function.%@NL@%
  12215. %@NL@%
  12216. %@AB@%_GetGTextVector(%@AE@% %@AI@%Vector%@AE@% %@AB@%)%@AE@%%@NL@%
  12217. %@NL@%
  12218.      Returns the current rotation vector that is applied to font-based text%@NL@%
  12219.      output in the %@AB@%_XYCoord%@AE@% record %@AI@%Vector%@AE@%. The default is (1,0).%@NL@%
  12220. %@NL@%
  12221. %@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@%
  12222. %@NL@%
  12223.      Stores the screen image inside the bounding rectangle specified in%@NL@%
  12224.      viewport coordinates. Stores the image in the buffer %@AI@%Image%@AE@%. The%@NL@%
  12225.      rectangle must be completely within the current clipping region.%@NL@%
  12226. %@NL@%
  12227. %@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@%
  12228. %@NL@%
  12229.      Stores the screen image inside the bounding rectangle specified in%@NL@%
  12230.      window coordinates. Stores the image in the buffer %@AI@%Image%@AE@%. The rectangle%@NL@%
  12231.      must be completely within the current clipping region.%@NL@%
  12232. %@NL@%
  12233. %@AB@%_GetImage_wxy(%@AE@% %@AI@%wxy1%@AE@%%@AB@%,%@AE@% %@AI@%wxy2%@AE@%%@AB@%,%@AE@% %@AI@%Image%@AE@%%@AB@%)%@AE@%%@NL@%
  12234. %@NL@%
  12235.      Stores the screen image inside the bounding rectangle specified in%@NL@%
  12236.      window coordinates in the %@AB@%_WXYCoord%@AE@% records %@AI@%wxy1%@AE@% and %@AI@%wxy2%@AE@%. Stores the%@NL@%
  12237.      image in the buffer %@AI@%Image%@AE@%. The rectangle must be completely within the%@NL@%
  12238.      current clipping region.%@NL@%
  12239. %@NL@%
  12240. %@AB@%_GetLineStyle%@AE@%%@NL@%
  12241. %@NL@%
  12242.      Returns the current line-style mask.%@NL@%
  12243. %@NL@%
  12244. %@AB@%_GetPhysCoord(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%,%@AE@% %@AI@%xy%@AE@%%@AB@%)%@AE@%%@NL@%
  12245. %@NL@%
  12246.      Translates the viewport coordinates (%@AI@%x%@AE@%, %@AI@%y%@AE@%) into physical screen%@NL@%
  12247.      coordinates and returns them in the %@AB@%_XYCoord%@AE@% record %@AI@%xy%@AE@%.%@NL@%
  12248. %@NL@%
  12249. %@AB@%_GetPixel(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%)%@AE@%%@NL@%
  12250. %@NL@%
  12251.      Returns the pixel value (color index) at the location specified in%@NL@%
  12252.      viewport coordinates (%@AI@%x%@AE@%, %@AI@%y%@AE@%).%@NL@%
  12253. %@NL@%
  12254. %@AB@%_GetPixel_w(%@AE@% %@AI@%wx%@AE@%%@AB@%,%@AE@% %@AI@%wy%@AE@%%@AB@%)%@AE@%%@NL@%
  12255. %@NL@%
  12256.      Returns the pixel value (color index) at the location specified in%@NL@%
  12257.      window coordinates (%@AI@%wx%@AE@%, %@AI@%wy%@AE@%).%@NL@%
  12258. %@NL@%
  12259. %@AB@%_GetTextColor%@AE@%%@NL@%
  12260. %@NL@%
  12261.      Returns the color index (attribute) of the current text color.%@NL@%
  12262. %@NL@%
  12263. %@AB@%_GetTextCursor%@AE@%%@NL@%
  12264. %@NL@%
  12265.      Returns the current cursor attribute (shape) in text modes.%@NL@%
  12266. %@NL@%
  12267. %@AB@%_GetTextPosition(%@AE@% %@AI@%r%@AE@%%@AB@%,%@AE@% %@AI@%c%@AE@%%@AB@%)%@AE@%%@NL@%
  12268. %@NL@%
  12269.      Returns the current row and column position of the text cursor.%@NL@%
  12270. %@NL@%
  12271. %@AB@%_GetTextWindow(%@AE@% %@AI@%r1%@AE@%%@AB@%,%@AE@% %@AI@%c1%@AE@%%@AB@%,%@AE@% %@AI@%r2%@AE@%%@AB@%,%@AE@% %@AI@%c2%@AE@%%@AB@%)%@AE@%%@NL@%
  12272. %@NL@%
  12273.      Returns the boundaries of the current text window in row and column%@NL@%
  12274.      coordinates.%@NL@%
  12275. %@NL@%
  12276. %@AB@%_GetVideoConfig(%@AE@% %@AI@%vc%@AE@%%@AB@%)%@AE@%%@NL@%
  12277. %@NL@%
  12278.      Returns the current graphics environment configuration in the%@NL@%
  12279.      %@AB@%_VideoConfig%@AE@% record %@AI@%vc%@AE@%.%@NL@%
  12280. %@NL@%
  12281. %@AB@%_GetViewCoord(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%,%@AE@% %@AI@%xy%@AE@%%@AB@%)%@AE@%%@NL@%
  12282. %@NL@%
  12283.      Translates physical coordinates (%@AI@%x%@AE@%, %@AI@%y%@AE@%) into viewport coordinates,%@NL@%
  12284.      returning the viewport coordinates in the %@AB@%_XYCoord%@AE@% record %@AI@%xy%@AE@%.%@NL@%
  12285. %@NL@%
  12286. %@AB@%_GetViewCoord_w(%@AE@% %@AI@%wx%@AE@%%@AB@%,%@AE@% %@AI@%wy%@AE@%%@AB@%,%@AE@% %@AI@%xy%@AE@%%@AB@%)%@AE@%%@NL@%
  12287. %@NL@%
  12288.      Translates window coordinates (%@AI@%wx%@AE@%, %@AI@%wy%@AE@%) into viewport coordinates,%@NL@%
  12289.      returning the viewport coordinates in the %@AB@%_XYCoord%@AE@% record %@AI@%xy%@AE@%.%@NL@%
  12290. %@NL@%
  12291. %@AB@%_GetViewCoord_wxy(%@AE@% %@AI@%wxy%@AE@%%@AB@%,%@AE@% %@AI@%xy%@AE@%%@AB@%)%@AE@%%@NL@%
  12292. %@NL@%
  12293.      Translates window coordinates given in the %@AB@%_WXYCoord%@AE@% record %@AI@%wxy%@AE@% into%@NL@%
  12294.      viewport coordinates, returning the viewport coordinates in the%@NL@%
  12295.      %@AB@%_XYCoord%@AE@% record %@AI@%xy%@AE@%.%@NL@%
  12296. %@NL@%
  12297. %@AB@%_GetVisualPage%@AE@%%@NL@%
  12298. %@NL@%
  12299.      Returns the current visual page number.%@NL@%
  12300. %@NL@%
  12301. %@AB@%_GetWindowCoord(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%,%@AE@% %@AI@%wxy%@AE@%%@AB@%)%@AE@%%@NL@%
  12302. %@NL@%
  12303.      Translates viewport coordinates (%@AI@%x%@AE@%, %@AI@%y%@AE@%) into window coordinates and%@NL@%
  12304.      returns them in the %@AB@%_WXYCoord%@AE@% record %@AI@%wxy%@AE@%.%@NL@%
  12305. %@NL@%
  12306. %@AB@%_ImageSize(%@AE@% %@AI@%x1%@AE@%%@AB@%,%@AE@% %@AI@%y1%@AE@%%@AB@%,%@AE@% %@AI@%x2%@AE@%%@AB@%,%@AE@% %@AI@%y2%@AE@%%@AB@%)%@AE@%%@NL@%
  12307. %@NL@%
  12308.      Returns the number of bytes needed to store the image inside the%@NL@%
  12309.      bounding rectangle specified by the viewport coordinates (%@AI@%x1%@AE@%, %@AI@%y1%@AE@%), (%@AI@%x2%@AE@%,%@NL@%
  12310.      %@AI@%y2%@AE@%). This function returns a %@AB@%LongInt%@AE@%.%@NL@%
  12311. %@NL@%
  12312. %@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@%
  12313. %@NL@%
  12314.      Returns the number of bytes needed to store the image inside the%@NL@%
  12315.      bounding rectangle specified by the window coordinates (%@AI@%wx1%@AE@%, %@AI@%wy1%@AE@%),%@NL@%
  12316.      (%@AI@%wx2%@AE@%, %@AI@%wy2%@AE@%). This function returns a %@AB@%LongInt%@AE@%.%@NL@%
  12317. %@NL@%
  12318. %@AB@%_ImageSize_wxy(%@AE@% %@AI@%wxy1%@AE@%%@AB@%,%@AE@% %@AI@%wxy2%@AE@% %@AB@%)%@AE@%%@NL@%
  12319. %@NL@%
  12320.      Returns the number of bytes needed to store the image inside the%@NL@%
  12321.      bounding rectangle specified by the window coordinates in the %@AB@%_WXYCoord%@AE@%%@NL@%
  12322.      records %@AI@%wxy1%@AE@% and %@AI@%wxy2%@AE@%. This function returns a %@AB@%LongInt%@AE@%.%@NL@%
  12323. %@NL@%
  12324. %@AB@%_LineTo(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%)%@AE@%%@NL@%
  12325. %@NL@%
  12326.      Draws a line from the current position to the point specified in%@NL@%
  12327.      viewport coordinates, using the current color, line-style mask, and%@NL@%
  12328.      logical write mode.%@NL@%
  12329. %@NL@%
  12330. %@AB@%_LineTo_w(%@AE@% %@AI@%wx%@AE@%%@AB@%,%@AE@% %@AI@%wy%@AE@%%@AB@%)%@AE@%%@NL@%
  12331. %@NL@%
  12332.      Draws a line from the current position to the point specified in window%@NL@%
  12333.      coordinates, using the current color, line-style mask, and logical%@NL@%
  12334.      write mode.%@NL@%
  12335. %@NL@%
  12336. %@AB@%_MoveTo(%@AE@% %@AI@%x, y%@AE@%%@AB@%)%@AE@%%@NL@%
  12337. %@NL@%
  12338.      Moves the graphics cursor to the point specified by the viewport%@NL@%
  12339.      coordinates (%@AI@%x%@AE@%, %@AI@%y%@AE@%).%@NL@%
  12340. %@NL@%
  12341. %@AB@%_MoveTo_w(%@AE@% %@AI@%wx%@AE@%%@AB@%,%@AE@% %@AI@%wy%@AE@%%@AB@%)%@AE@%%@NL@%
  12342. %@NL@%
  12343.      Moves the graphics cursor to the point specified by the window%@NL@%
  12344.      coordinates (%@AI@%wx%@AE@%, %@AI@%wy%@AE@%).%@NL@%
  12345. %@NL@%
  12346. %@AB@%_OutGText(%@AE@% %@AI@%TextString%@AE@%%@AB@%)%@AE@%%@NL@%
  12347. %@NL@%
  12348.      Prints %@AI@%TextString%@AE@% on the screen using the current font and graphics%@NL@%
  12349.      color at the current graphics cursor position.%@NL@%
  12350. %@NL@%
  12351. %@AB@%_OutMem(%@AE@% %@AI@%TextString%@AE@%%@AB@%,%@AE@% %@AI@%Length%@AE@%%@AB@%)%@AE@%%@NL@%
  12352. %@NL@%
  12353.      Prints %@AI@%TextString%@AE@% on the screen at the current text cursor position.%@NL@%
  12354.      This procedure treats ASCII 0, 10, and 13 as graphics characters.%@NL@%
  12355.      Formatting is not supported.%@NL@%
  12356. %@NL@%
  12357. %@AB@%_OutText(%@AE@% %@AI@%TextString%@AE@%%@AB@%)%@AE@%%@NL@%
  12358. %@NL@%
  12359.      Prints %@AI@%TextString%@AE@% on the screen at the current text cursor position.%@NL@%
  12360.      Formatting is not supported, except for carriage return and line feed.%@NL@%
  12361. %@NL@%
  12362. %@AB@%_Pie(%@AE@% %@AI@%Control, x1, y1, x2, y2, x3, y3, x4, y4%@AE@%%@AB@%)%@AE@%%@NL@%
  12363. %@NL@%
  12364. %@NL@%
  12365.      Draws a pie-shaped wedge given the fill control, bounding rectangle,%@NL@%
  12366.      starting point, and ending point. All coordinates are given in viewport%@NL@%
  12367.      coordinates.%@NL@%
  12368. %@NL@%
  12369. %@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@%
  12370. %@NL@%
  12371.      Draws a pie-shaped wedge given the fill control, bounding rectangle,%@NL@%
  12372.      starting point, and ending point. All coordinates are given in%@NL@%
  12373.      %@AB@%_WXYCoord%@AE@% records.%@NL@%
  12374. %@NL@%
  12375. %@AB@%_PutImage(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%,%@AE@% %@AI@%Image%@AE@%%@AB@%,%@AE@% %@AI@%Action%@AE@%%@AB@%)%@AE@%%@NL@%
  12376. %@NL@%
  12377.      Transfers the image stored in the buffer %@AI@%Image%@AE@% to the screen (using the%@NL@%
  12378.      logical operator %@AI@%Action%@AE@%) with the upper left corner at the specified%@NL@%
  12379.      viewport coordinates. If the image does not completely fit in the%@NL@%
  12380.      current clipping region, the image is not transferred.%@NL@%
  12381. %@NL@%
  12382. %@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@%
  12383. %@NL@%
  12384.      Transfers the image stored in the buffer %@AI@%Image%@AE@% to the screen (using the%@NL@%
  12385.      logical operator %@AI@%Action%@AE@%) with the upper left corner at the specified%@NL@%
  12386.      window coordinates. If the image does not completely fit in the current%@NL@%
  12387.      clipping region, the image is not transferred.%@NL@%
  12388. %@NL@%
  12389. %@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@%
  12390. %@NL@%
  12391.      Draws a rectangle given the fill control and bounding rectangle in%@NL@%
  12392.      viewport coordinates, using the current color, line-style mask, and%@NL@%
  12393.      logical write mode.%@NL@%
  12394. %@NL@%
  12395. %@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@%
  12396. %@NL@%
  12397.      Draws a rectangle given the fill control and bounding rectangle in%@NL@%
  12398.      window coordinates, using the current color, line-style mask, and%@NL@%
  12399.      logical write mode.%@NL@%
  12400. %@NL@%
  12401. %@AB@%_Rectangle_wxy(%@AE@% %@AI@%Control%@AE@%%@AB@%,%@AE@% %@AI@%wxy1%@AE@%%@AB@%,%@AE@% %@AI@%wxy2%@AE@%%@AB@%)%@AE@%%@NL@%
  12402. %@NL@%
  12403.      Draws a rectangle given the fill control and bounding rectangle in the%@NL@%
  12404.      window coordinates specified in the %@AB@%_WXYCoord%@AE@% records %@AI@%wxy1%@AE@% and %@AI@%wxy2%@AE@% and%@NL@%
  12405.      using the current color, line-style mask, and logical write mode.%@NL@%
  12406. %@NL@%
  12407. %@AB@%_RegisterFonts(%@AE@% %@AI@%PathName%@AE@%%@AB@%)%@AE@%%@NL@%
  12408. %@NL@%
  12409.      Registers the fonts in the file given in %@AI@%PathName%@AE@%.%@NL@%
  12410. %@NL@%
  12411. %@AB@%_RemapAllPalette(%@AE@% %@AI@%NewPalette%@AE@%%@AB@%)%@AE@%%@NL@%
  12412. %@NL@%
  12413.      Remaps the entire color palette simultaneously, given an array of color%@NL@%
  12414.      values.%@NL@%
  12415. %@NL@%
  12416. %@AB@%_RemapPalette(%@AE@% %@AI@%Index%@AE@%%@AB@%,%@AE@% %@AI@%Value%@AE@%%@AB@%)%@AE@%%@NL@%
  12417. %@NL@%
  12418.      Remaps the color index %@AI@%Index%@AE@% to the color value %@AI@%Value%@AE@%.%@NL@%
  12419. %@NL@%
  12420. %@AB@%_ScrollTextWindow(%@AE@% %@AI@%Count%@AE@%%@AB@%)%@AE@%%@NL@%
  12421. %@NL@%
  12422.      Scrolls the current text window by %@AI@%Count%@AE@% lines. If %@AI@%Count%@AE@% is positive,%@NL@%
  12423.      the text scrolls up; if negative, the text scrolls down.%@NL@%
  12424. %@NL@%
  12425. %@AB@%_SelectPalette(%@AE@% %@AI@%Number%@AE@%%@AB@%)%@AE@%%@NL@%
  12426. %@NL@%
  12427.      Sets the active palette to palette number %@AI@%Number%@AE@% in CGA and Olivetti%@NL@%
  12428.      graphics modes.%@NL@%
  12429. %@NL@%
  12430. %@AB@%_SetActivePage(%@AE@% %@AI@%Page%@AE@%%@AB@%)%@AE@%%@NL@%
  12431. %@NL@%
  12432.      Makes page number %@AI@%Page%@AE@% the active page for graphics output, available%@NL@%
  12433.      only for configurations that support multiple screen pages.%@NL@%
  12434. %@NL@%
  12435. %@AB@%_SetBkColor(%@AE@% %@AI@%Color%@AE@%%@AB@%)%@AE@%%@NL@%
  12436. %@NL@%
  12437.      Sets the current background color to %@AI@%Color%@AE@%.%@NL@%
  12438. %@NL@%
  12439. %@AB@%_SetClipRgn(%@AE@% %@AI@%x1%@AE@%%@AB@%,%@AE@% %@AI@%y1%@AE@%%@AB@%,%@AE@% %@AI@%x2%@AE@%%@AB@%,%@AE@% %@AI@%y2%@AE@%%@AB@%)%@AE@%%@NL@%
  12440. %@NL@%
  12441.      Limits the display of subsequent graphics and font text to the bounding%@NL@%
  12442.      rectangle, given in viewport coordinates.%@NL@%
  12443. %@NL@%
  12444. %@AB@%_SetColor(%@AE@% %@AI@%Color%@AE@%%@AB@%)%@AE@%%@NL@%
  12445. %@NL@%
  12446.      Sets the current graphics color to color index %@AI@%Color%@AE@%.%@NL@%
  12447. %@NL@%
  12448. %@AB@%_SetFillMask(%@AE@% %@AI@%Mask%@AE@%%@AB@%)%@AE@%%@NL@%
  12449. %@NL@%
  12450.      Defines the current fill mask.%@NL@%
  12451. %@NL@%
  12452. %@AB@%_SetFont(%@AE@% %@AI@%Options%@AE@%%@AB@%)%@AE@%%@NL@%
  12453. %@NL@%
  12454.      Selects a new active font from one of the registered fonts. Font%@NL@%
  12455.      selection is based on the characteristics specified by %@AI@%Options%@AE@%.%@NL@%
  12456. %@NL@%
  12457. %@AB@%_SetGTextVector(%@AE@% %@AI@%xvect%@AE@%%@AB@%,%@AE@% %@AI@%yvect%@AE@%%@AB@%)%@AE@%%@NL@%
  12458. %@NL@%
  12459.      Sets the current rotation vector that is applied to font-based text%@NL@%
  12460.      output. The default is horizontal text (1,0).%@NL@%
  12461. %@NL@%
  12462. %@AB@%_SetLineStyle(%@AE@% %@AI@%Style%@AE@%%@AB@%)%@AE@%%@NL@%
  12463. %@NL@%
  12464.      Sets the current line-style mask to %@AI@%Style%@AE@%. The line-style mask affects%@NL@%
  12465.      the output of %@AB@%_LineTo%@AE@% and %@AB@%_Rectangle%@AE@%.%@NL@%
  12466. %@NL@%
  12467. %@AB@%_SetPixel(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%)%@AE@%%@NL@%
  12468. %@NL@%
  12469.      Changes the specified pixel to the current color. The point is%@NL@%
  12470.      specified in viewport coordinates.%@NL@%
  12471. %@NL@%
  12472. %@AB@%_SetPixel_w(%@AE@% %@AI@%wx%@AE@%%@AB@%,%@AE@% %@AI@%wy%@AE@%%@AB@%)%@AE@%%@NL@%
  12473. %@NL@%
  12474.      Sets the specified pixel to the current color. The point is specified%@NL@%
  12475.      in window coordinates.%@NL@%
  12476. %@NL@%
  12477. %@AB@%_SetTextColor(%@AE@% %@AI@%Color%@AE@%%@AB@%)%@AE@%%@NL@%
  12478. %@NL@%
  12479.      Sets the text color to color index %@AI@%Color%@AE@%. Subsequent text output from%@NL@%
  12480.      %@AB@%_OutText%@AE@% and %@AB@%_OutMem%@AE@% appears in the new color.%@NL@%
  12481. %@NL@%
  12482. %@AB@%_SetTextCursor(%@AE@% %@AI@%Attr%@AE@%%@AB@%)%@AE@%%@NL@%
  12483. %@NL@%
  12484.      Sets the cursor shape in text mode.%@NL@%
  12485. %@NL@%
  12486. %@AB@%_SetTextPosition(%@AE@% %@AI@%r%@AE@%%@AB@%,%@AE@% %@AI@%c%@AE@%%@AB@%)%@AE@%%@NL@%
  12487. %@NL@%
  12488.      Moves the text cursor position to the row and column specified,%@NL@%
  12489.      relative to the current text window.%@NL@%
  12490. %@NL@%
  12491. %@AB@%_SetTextRows(%@AE@% %@AI@%Rows%@AE@%%@AB@%)%@AE@%%@NL@%
  12492. %@NL@%
  12493.      Sets the number of rows available for text modes.%@NL@%
  12494. %@NL@%
  12495. %@AB@%_SetTextWindow(%@AE@% %@AI@%r1%@AE@%%@AB@%,%@AE@% %@AI@%c1%@AE@%%@AB@%,%@AE@% %@AI@%r2%@AE@%%@AB@%,%@AE@% %@AI@%c2%@AE@%%@AB@%)%@AE@%%@NL@%
  12496. %@NL@%
  12497.      Defines the upper left and lower right boundaries of the current text%@NL@%
  12498.      window. Output from %@AB@%_OutText%@AE@% and %@AB@%_OutMem%@AE@% is limited to this window.%@NL@%
  12499. %@NL@%
  12500. %@AB@%_SetVideoMode(%@AE@% %@AI@%Mode%@AE@%%@AB@%)%@AE@%%@NL@%
  12501. %@NL@%
  12502.      Selects a screen mode for a particular hardware/display configuration.%@NL@%
  12503. %@NL@%
  12504. %@AB@%_SetVideoModeRows(%@AE@% %@AI@%Mode%@AE@%%@AB@%,%@AE@% %@AI@%Rows%@AE@%%@AB@%)%@AE@%%@NL@%
  12505. %@NL@%
  12506.      Sets the screen mode and number of text rows for a particular hardware/%@NL@%
  12507.      display configuration.%@NL@%
  12508. %@NL@%
  12509. %@AB@%_SetViewOrg(%@AE@% %@AI@%x%@AE@%%@AB@%,%@AE@% %@AI@%y%@AE@%%@AB@%,%@AE@% %@AI@%Org%@AE@%%@AB@%)%@AE@%%@NL@%
  12510. %@NL@%
  12511.      Moves the viewport origin to the physical coordinates (%@AI@%x%@AE@%, %@AI@%y%@AE@%), and%@NL@%
  12512.      returns the previous origin in the %@AB@%_XYCoord%@AE@% record %@AI@%Org%@AE@%.%@NL@%
  12513. %@NL@%
  12514. %@AB@%_SetViewport(%@AE@% %@AI@%x1%@AE@%%@AB@%,%@AE@% %@AI@%y1%@AE@%%@AB@%,%@AE@% %@AI@%x2%@AE@%%@AB@%,%@AE@% %@AI@%y2%@AE@%%@AB@%)%@AE@%%@NL@%
  12515. %@NL@%
  12516.      Defines the graphics viewport (defines the clipping region and sets the%@NL@%
  12517.      viewport origin to the upper left corner of the region) given the%@NL@%
  12518.      bounding rectangle in physical coordinates.%@NL@%
  12519. %@NL@%
  12520. %@AB@%_SetVisualPage(%@AE@% %@AI@%Page%@AE@%%@AB@%)%@AE@%%@NL@%
  12521. %@NL@%
  12522.      Makes %@AI@%Page%@AE@% the current visual page (requires a configuration that%@NL@%
  12523.      supports multiple screen pages).%@NL@%
  12524. %@NL@%
  12525. %@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@%
  12526. %@NL@%
  12527.      Creates a floating-point graphics window given a bounding rectangle in%@NL@%
  12528.      window coordinates. If %@AI@%FInvert%@AE@% is %@AB@%True%@AE@%, the window is inverted%@NL@%
  12529.      vertically.%@NL@%
  12530. %@NL@%
  12531. %@AB@%_SetWriteMode(%@AE@% %@AI@%WMode%@AE@% %@AB@%)%@AE@%%@NL@%
  12532. %@NL@%
  12533.      Sets the logical operation applied to line-drawing output to one of the%@NL@%
  12534.      following: %@AB@%_Gor%@AE@%, %@AB@%_Gand%@AE@%, %@AB@%_GPReset%@AE@%, %@AB@%_GPSet%@AE@%, or %@AB@%_Gxor%@AE@%. Only %@AB@%LineTo%@AE@% and%@NL@%
  12535.      %@AB@%_Rectangle%@AE@% are affected.%@NL@%
  12536. %@NL@%
  12537. %@AB@%_UnRegisterFonts%@AE@%%@NL@%
  12538. %@NL@%
  12539.      Disables fonts and frees memory previously allocated by %@AB@%_RegisterFonts%@AE@%.%@NL@%
  12540. %@NL@%
  12541. %@AB@%_WrapOn(%@AE@% %@AI@%Option%@AE@%%@AB@%)%@AE@%%@NL@%
  12542. %@NL@%
  12543.      Controls text wrapping for %@AB@%_OutText%@AE@% and %@AB@%_OutMem%@AE@% when the output reaches%@NL@%
  12544.      the edge of the text window. By default, text wrapping is enabled.%@NL@%
  12545. %@NL@%
  12546. %@NL@%
  12547.