home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft_Programmers_Library.7z / MPL / fortran / advfrt.txt next >
Encoding:
Text File  |  2013-11-08  |  542.7 KB  |  13,889 lines

  1.  Microsoft(R) FORTRAN ADVANCED TOPICS
  2.  VERSION 5.0
  3.  
  4.  FOR MS(R) OS/2 AND MS-DOS(R) OPERATING SYSTEMS
  5.  
  6.  MICROSOFT CORPORATION
  7.  
  8.  Information in this document is subject to change without notice and does
  9.  not represent a commitment on the part of Microsoft Corporation. The
  10.  software described in this document is furnished under a license agreement
  11.  or nondisclosure agreement. The software may be used or copied only in
  12.  accordance with the terms of the agreement. It is against the law to copy
  13.  the software on any medium except as specifically allowed in the license or
  14.  nondisclosure agreement. No part of this manual may be reproduced or
  15.  transmitted in any form or by any means, electronic or mechanical, including
  16.  photocopying and recording, for any purpose without the express written
  17.  permission of Microsoft.
  18.  
  19.  (c)Copyright Microsoft Corporation, 1989. All rights reserved.
  20.  
  21.  Printed and bound in the United States of America.
  22.  
  23.  Microsoft, MS, MS-DOS, CodeView, and QuickC are registered trademarks of
  24.  Microsoft Corporation.
  25.  
  26.  AT&T is a registered trademark of American Telephone and Telegraph Company.
  27.  
  28.  Hercules is a registered trademark and InColor is a trademark of Hercules
  29.  Computer Technology.
  30.  
  31.  IBM is a registered trademark of International Business Machines
  32.  Corporation.
  33.  
  34.  Intel is a registered trademark of Intel Corporation.
  35.  
  36.  Olivetti is a registered trademark of Ing. C. Olivetti.
  37.  
  38.  Texas Instruments is a registered trademark of Texas Instruments, Inc.
  39.  
  40.  VAX is a registered trademark of Digital Equipment Corporation.
  41.  
  42.  WANG is a registered trademark of Wang Laboratories.
  43.  
  44.  Document No. LN0828-500-R00-0289
  45.  Part No. 06384
  46.  10  9 8 7 6 5 4 3 2 1
  47.  
  48.  
  49.  Table of Contents
  50.  ───────────────────────────────────────────────────────────────────────────
  51.  
  52.  Introduction
  53.       About This Manual
  54.       Document Conventions
  55.  
  56.  Part 1  Working with Microsoft FORTRAN
  57.  
  58.  Chapter 1  Controlling Floating- Point Operations
  59.  1.1  Choosing a Math Package
  60.        1.1.1  The 8087/287/387 Package
  61.        1.1.2  The Emulator Package
  62.        1.1.3  The Alternate Math Package
  63.  1.2  Using the Floating-Point Options (/FP)
  64.        1.2.1  The /FPi87 Option
  65.        1.2.2  The /FPc87 Option
  66.        1.2.3  The /FPi Option
  67.        1.2.4  The /FPc Option
  68.        1.2.5  The /FPa Option
  69.  1.3  Library Considerations in Selecting /FP Options
  70.        1.3.1  Choosing In-Line Instructions or Calls
  71.        1.3.2  Using a Standard Library for Linking
  72.        1.3.3  Ensuring Compatibility between Options
  73.        1.3.4  Special Procedure for MS-DOS 3.2 Users
  74.        1.3.5  Using $FLOATCALLS and $NOFLOATCALLS
  75.  1.4  Using the NO87 Environment Variable
  76.  1.5  Handling 8087/287/387 Floating-Point Exceptions
  77.        1.5.1  Controlling the Processing Environment
  78.        1.5.2  Reading and Setting Status and Control Values
  79.        1.5.3  Floating-Point Exceptions under PC-DOS 3.2
  80.  1.6  Using Non-IBM(R)-Compatible Computers
  81.  
  82.  Chapter 2  Selecting a Memory Model
  83.  2.1  What Is a Memory Model?
  84.  2.2  Understanding Memory Models
  85.        2.2.1  Code and Data Segments
  86.        2.2.2  Near, Far, and Huge Addresses
  87.        2.2.3  The Default Data Segment
  88.  2.3  Working with FORTRAN Memory Models
  89.        2.3.1  Specifying a Memory Model
  90.        2.3.2  Data-Handling Strategies and Limits
  91.        2.3.3  Limits on Code Size
  92.  2.4  Selecting and Adjusting the Memory Model
  93.        2.4.1  Using Standard Memory Models
  94.        2.4.2  The NEAR, FAR, and HUGE Attributes
  95.        2.4.3  The $LARGE and $NOTLARGE Metacommands
  96.        2.4.4  Using Library Routines with Different Memory Models
  97.        2.4.5  Compiler Options Affecting Memory Usage
  98.  
  99.  Chapter 3  FORTRAN Programming under OS/2
  100.  3.1  Compiling and Linking under OS/2
  101.  3.2  Running under Both DOS and OS/2
  102.  3.3  Interfacing FORTRAN with OS/2
  103.  3.4  Understanding Multitasking, Threads, and Dynamic-Link Libraries
  104.        3.4.1  Multitasking and Threads
  105.        3.4.2  Dynamic-Link Libraries
  106.  3.5  Multithread Programs
  107.        3.5.1  Library Support for Multithread Programs
  108.        3.5.2  Thread Control Routines
  109.  3.6  A Multithread FORTRAN Program
  110.        3.6.1  Sample Program Operation
  111.        3.6.2  Compiling and Linking the Sample Multithread Program
  112.        3.6.3  Troubleshooting Multithread Programs
  113.  3.7  Using FORTRAN Dynamic-Link Libraries
  114.        3.7.1  Creating a Dynamic-Link Library
  115.        3.7.2  The LOADDS Attribute
  116.        3.7.3  Multithread Dynamic-Link Libraries: An Overview
  117.        3.7.4  Creating a Multithread Dynamic-Link Library
  118.        3.7.5  Creating a Custom FORTRAN Run-Time Definitions File
  119.        3.7.6  Using a Multithread Dynamic-Link Library
  120.        3.7.7  Compiling for Dynamic-Link and Multithread Capabilities
  121.        3.7.8  FORTRAN OS/2 Libraries
  122.  3.8  Limits on Multithread and Dynamic-Link Programs
  123.        3.8.1  Large and Huge Memory Models (/MT, /MD)
  124.        3.8.2  Math Support (/FPi87)
  125.        3.8.3  Limited CHARACTER*(*) Support
  126.        3.8.4  The C Attribute and REAL Numbers
  127.        3.8.5  Open Files
  128.  3.9  Recommendations
  129.  3.10  Additional Information
  130.  
  131.  Chapter 4  Mixed-Language Programming
  132.  4.1  Making Mixed-Language Calls
  133.        4.1.1  Naming Convention Requirement
  134.        4.1.2  Calling Convention Requirement
  135.        4.1.3  Methods for Passing Parameters
  136.        4.1.4  Compiling and Linking Considerations
  137.  4.2  Calling Other High-Level Languages
  138.        4.2.1  The INTERFACE Statement
  139.        4.2.2  An Alternative Interface to C
  140.        4.2.3  The ALIAS Attribute
  141.        4.2.4  FORTRAN Calls to C and Pascal
  142.        4.2.5  C Functions Available with FORTRAN Run-Time Libraries
  143.        4.2.6  FORTRAN Calls to BASIC
  144.  4.3  Using Assembly-Language Routines
  145.  4.4  Calling FORTRAN from Other Languages
  146.  
  147.  Chapter 5  Transferring Data between Languages
  148.  5.1  Passing by Reference or Value
  149.        5.1.1  BASIC Arguments
  150.        5.1.2  C Arguments
  151.        5.1.3  FORTRAN Arguments
  152.        5.1.4  Pascal Arguments
  153.  5.2  Passing Numeric, Logical, and String Data
  154.        5.2.1  Integer and Real Numbers
  155.        5.2.2  FORTRAN COMPLEX Types
  156.        5.2.3  FORTRAN LOGICAL Type
  157.        5.2.4  Strings
  158.  5.3  Handling Special Data Types
  159.        5.3.1  Arrays
  160.        5.3.2  Structures, Records, and User-Defined Types
  161.        5.3.3  External Data
  162.        5.3.4  Pointers and Address Variables
  163.        5.3.5  Common Blocks
  164.        5.3.6  Using a Varying Number of Parameters
  165.  
  166.  Chapter 6  Record Structures: File Formats and Access
  167.  6.1  Understanding Structures: Forms and Access Modes
  168.  6.2  Using Formatted Records
  169.        6.2.1  Formatted Sequential Records
  170.        6.2.2  Formatted Direct Records
  171.  6.3  Using Unformatted Records
  172.        6.3.1  Unformatted Sequential Records
  173.        6.3.2  Unformatted Direct Records
  174.  6.4  Using Binary Records
  175.        6.4.1  Binary Sequential Records
  176.        6.4.2  Binary Direct Records
  177.  
  178.  Chapter 7  Optimizing Programs
  179.  7.1  Compiling and Linking Strategies
  180.        7.1.1  Using Debugging and Integer-Size Options
  181.        7.1.2  Using 8087/287/387 Math Options
  182.        7.1.3  Using Overlays
  183.  7.2  Coding Strategies
  184.        7.2.1  Removing Error-Message Text during SETUP
  185.        7.2.2  Using Consistent File-Access and Format Types
  186.        7.2.3  Specifying Edit Lists
  187.        7.2.4  Using the BLOCKSIZE Option
  188.        7.2.5  Using Integer and Real Variables
  189.        7.2.6  Using Arrays and EQUIVALENCE Statements
  190.  
  191.  Part 2  The Microsoft FORTRAN Graphics Library
  192.  
  193.  Chapter 8  Graphics Library Routines
  194.  8.1  Using Graphics and Character-Font Functions
  195.  8.2  Defining Graphics Characteristics
  196.        8.2.1  Selecting Display Options
  197.        8.2.2  Setting Graphics Coordinates
  198.        8.2.3  Setting Palettes
  199.        8.2.4  Setting Figure Attributes
  200.  8.3  Displaying Graphics Output
  201.        8.3.1  Creating a Graphics Display
  202.        8.3.2  Displaying Text
  203.        8.3.3  Transferring Images
  204.        8.3.4  Displaying Font-Based Characters
  205.  8.4  Routines Available under OS/2
  206.  
  207.  Chapter 9  Drawing Graphic Elements
  208.  9.1  Working with Graphics Modes
  209.        9.1.1  Checking the Current Video Mode
  210.        9.1.2  Setting the Video Mode
  211.        9.1.3  Writing a Graphics Program (SINE)
  212.  9.2  Adding Color
  213.        9.2.1  Color Graphics Modes
  214.        9.2.2  Using the Color Video Text Modes
  215.  9.3  Understanding Coordinate Systems
  216.        9.3.1  Text Coordinates
  217.        9.3.2  Graphics Coordinates
  218.        9.3.3  Real Coordinates Program (REALG)
  219.        9.3.4  Drawing the Graphs
  220.  
  221.  Chapter 10  Using Fonts from the Graphics Library
  222.  10.1  Available Typefaces
  223.  10.2  Using Microsoft FORTRAN Fonts
  224.         10.2.1  Registering Fonts
  225.         10.2.2  Setting the Font and Displaying Text
  226.  10.3  Example Program (SAMPLER)
  227.  10.4  Using Fonts Effectively
  228.  
  229.  Chapter 11  Graphics Library Reference
  230.       arc, arc_w
  231.       clearscreen
  232.       displaycursor
  233.       ellipse, ellipse_w
  234.       floodfill, floodfill_w
  235.       getactivepage
  236.       getbkcolor
  237.       getcolor
  238.       getcurrentposition, getcurrentposition_w
  239.       getfillmask
  240.       getfontinfo
  241.       getgtextextent
  242.       getimage, getimage_w
  243.       getlinestyle
  244.       getphyscoord
  245.       getpixel, getpixel_w
  246.       gettextcolor
  247.       gettextcursor
  248.       gettextposition
  249.       getviewcoord, getviewcoord_w
  250.       getvideoconfig
  251.       getvisualpage
  252.       getwindowcoord
  253.       imagesize, imagesize_w
  254.       lineto, lineto_w
  255.       moveto, moveto_w
  256.       outgtext
  257.       outtext
  258.       pie, pie_w
  259.       putimage, putimage_w
  260.       rectangle, rectangle_w
  261.       registerfonts
  262.       remapallpalette, remappalette
  263.       selectpalette
  264.       setactivepage
  265.       setbkcolor
  266.       setcliprgn
  267.       setcolor
  268.       setfillmask
  269.       setfont
  270.       setlinestyle
  271.       setpixel, setpixel_w
  272.       settextcolor
  273.       settextcursor
  274.       settextposition
  275.       settextrows
  276.       settextwindow
  277.       setvideomode
  278.       setvideomoderows
  279.       setvieworg
  280.       setviewport
  281.       setvisualpage
  282.       setwindow
  283.       unregisterfonts
  284.       wrapon
  285.  
  286.  Index
  287.  
  288.  Listing of Tables
  289.  
  290.  Table 1.1  Summary of Floating-Point Options
  291.  Table 1.2  Floating-Point Exceptions
  292.  Table 1.3  Mask Settings for Operation Exceptions
  293.  Table 2.1  Data Allocation in Large Memory Models
  294.  Table 2.2  Effects of the NEAR Attribute
  295.  Table 2.3  Effects of the FAR and HUGE Attributes
  296.  Table 3.1  FORTRAN OS/2 Libraries
  297.  Table 4.1  Language Equivalents for Routine Calls
  298.  Table 4.2  Parameter-Passing Defaults
  299.  Table 5.1  Equivalent Numeric Data Types
  300.  Table 5.2  Equivalent Array Declarations
  301.  Table 9.1  Video Modes for Text and Graphics
  302.  Table 9.1  Fill Patterns
  303.  Table 9.2  Available CGA Colors
  304.  Table 9.3  CGA Colors:  $MRESNOCOLOR Mode
  305.  Table 10.1  Typefaces and Type Sizes in the FORTRAN Graphics Library
  306.  Table R.2  $MRES4COLOR Mode Palette Colors
  307.  Table R.3  $MRESNOCOLOR Mode CGA Palette Colors
  308.  Table R.4  $MRESNOCOLOR Mode EGA Palette Colors
  309.  Table R.5  Symbolic Constants for Screen Mode
  310.  Table R.6  Modes Selected by $MAXCOLORMODE and $MAXRESMODE
  311.  
  312.  
  313.  Introduction
  314.  ───────────────────────────────────────────────────────────────────────────
  315.  
  316.  Microsoft(R) FORTRAN Version 5.0 includes many enhancements since its last
  317.  release. The language is now fully compatible with the Systems Application
  318.  Architecture (SAA) FORTRAN extensions and many of the VAX(R) extensions. It
  319.  supports new constructs such as compound data types, SELECT CASE
  320.  decision-making blocks, and other features that extend its utility. This new
  321.  version of Microsoft FORTRAN offers enhanced OS/2 systems support, including
  322.  the use of dynamically linked libraries and multiple threads of execution.
  323.  
  324.  For complete flexibility, programs written with this new version can be
  325.  designed to run under DOS, OS/2, or both operating systems. In addition, an
  326.  extensive graphics library lets data and figures become an integral part of
  327.  any FORTRAN application.
  328.  
  329.  This chapter introduces Microsoft FORTRAN Advanced Topics and describes the
  330.  document conventions used in this manual. If you want to write and run
  331.  FORTRAN programs immediately, the Getting Started with Microsoft FORTRAN and
  332.  the Microsoft FORTRAN Reference man-uals will provide sufficient resources
  333.  to get you up and running quickly.
  334.  
  335.  
  336.  About This Manual
  337.  
  338.  Microsoft FORTRAN Advanced Topics contains two parts. Part 1, "Working with
  339.  Microsoft FORTRAN," discusses how to get the most out of Microsoft FORTRAN
  340.  5.0, and includes such topics as selecting the appropriate memory models,
  341.  using OS/2-specific features, or creating programs with parts written in
  342.  different programming languages.
  343.  
  344.  ───────────────────────────────────────────────────────────────────────────
  345.  NOTE
  346.     Microsoft documentation uses the term "OS/2" to refer to the OS/2
  347.     Systems──Microsoft Operating System/2 (MS(R) OS/2) and IBM(R) OS/2.
  348.     Similarly, the term "DOS" refers to both the MS-DOS(R) and IBM Personal
  349.     Computer DOS operating systems. The name of a specific operating system
  350.     is used when it is necessary to note features that are unique to that
  351.     system.
  352.  ───────────────────────────────────────────────────────────────────────────
  353.  
  354.  The first two chapters discuss memory models and alternatives for handling
  355.  floating-point math. Chapter 3, "FORTRAN Programming under OS/2," covers the
  356.  special features available under OS/2, such as multitasking, dynamic-link
  357.  libraries, virtual memory access, and protected and real modes. Chapter 4,
  358.  "Mixed-Language Programming," describes how to access routines programmed in
  359.  another Microsoft language. And, if you need to exchange data between
  360.  languages, read Chapter 5.
  361.  
  362.  Chapter 6, "Record Structures: File Formats and Access," reviews the
  363.  different file format and access combinations available to Microsoft
  364.  FORTRAN. The last chapter of the Part 1, "Optimizing Programs," covers
  365.  strategies for optimizing both the size and speed of an application, at both
  366.  the compiling/linking and coding levels.
  367.  
  368.  Part 2, "The Microsoft FORTRAN Graphics Library," presents topics and
  369.  considerations in writing graphics applications.
  370.  
  371.  Chapter 8 introduces the routines provided in the graphics library and their
  372.  categories. Chapter 9, "Drawing Graphic Elements," describes graphics
  373.  programming in detail, and steps through several example programs. Chapter
  374.  10, "Using Fonts from the Graphics Library," covers the different fonts
  375.  available and how to use the font manipulating routines. The final chapter,
  376.  "Graphics Library Reference," describes the use of each routine in detail.
  377.  
  378.  The graphics functions in the Microsoft FORTRAN Graphics Library are
  379.  designed to work in the MS-DOS or IBM Personal Computer DOS (PC-DOS)
  380.  environment; the text-based routines are also available under OS/2.
  381.  
  382.  The chapters in this manual can be read either individually or
  383.  consecutively, although the graphics chapters in Part 2 follow a more
  384.  sequential structure. The majority of the chapters in the Part 1 stand by
  385.  themselves and can be read independently.
  386.  
  387.  Microsoft FORTRAN conforms to the American National Standard Programming
  388.  Language FORTRAN 77, as described in the American National Standards
  389.  Institute (ANSI) X3.9-1978 standard.
  390.  
  391.  Microsoft FORTRAN Advanced Topics assumes you have a working knowledge of
  392.  both the computer and ANSI standard FORTRAN, and that you recognize the
  393.  Microsoft extensions to FORTRAN.
  394.  
  395.  
  396.  Document Conventions
  397.  
  398.  This book uses the following typographic conventions:
  399.  
  400.  Examples                                   Description
  401.  
  402.  LLIBFOR7.LIB, LINK, FL,                    Uppercase (capital) letters
  403.  FGRAPH.FI, /4Yb                            indicate file names and DOS-level
  404.                                             commands. Uppercase is also used
  405.                                             for command-line options (unless
  406.                                             the application accepts only
  407.                                             lowercase).
  408.  
  409.  C     Comment line                         This kind of type  is used for
  410.        WRITE (*, *) 'Hello                  program examples, program output,
  411.       + World'                              and error messages within the
  412.                                             text.
  413.  
  414.                                             A capital C marks the beginning
  415.                                             of a comment in sample programs.
  416.                                             Continuation lines are indicated
  417.                                             by a plus (+ ) in column 6.
  418.  
  419.  $TRUNCATE, INTRINSIC,WRITE,                Bold capital letters indicate
  420.  DosSleep                                   language-specific keywords with
  421.                                             special meaning to FORTRAN (or,
  422.                                             in the case of DosSleep, with
  423.                                             special meaning to the OS/2
  424.                                             environment). Keywords are a
  425.                                             required part of statement
  426.                                             syntax, unless enclosed in double
  427.                                             brackets, as explained below.
  428.  
  429.  near, adr                                  Bold lowercase letters are used
  430.                                             for keywords of languages that
  431.                                             use lowercase letters by
  432.                                             convention. For example, in the
  433.                                             sentence, "The BASIC INTEGER and
  434.                                             C short types are equivalent,"
  435.                                             the word INTEGER is a Microsoft
  436.                                             BASIC keyword and short is a
  437.                                             keyword from Microsoft C.
  438.  
  439.  Apostrophes: '' ' '                        In Microsoft FORTRAN, an
  440.                                             apostrophe is entered as a single
  441.                                             right quotation mark ('), not a
  442.                                             single left quotation mark (`).
  443.                                             Note that in the typeface used in
  444.                                             program examples, such as
  445.                                             'string', apostrophes look like
  446.                                             this: '.
  447.  
  448.  expression                                 Words in italics indicate
  449.                                             placeholders for information that
  450.                                             you must supply. A file name is
  451.                                             an example of this kind of
  452.                                             information.
  453.  
  454.  «option»                                  Items inside bold chevrons
  455.                                             are optional.
  456.  
  457.  {choice1 | choice2}                        Braces and a vertical bar
  458.                                             indicate a choice among two or
  459.                                             more items. You must choose one
  460.                                             of the items unless all of the
  461.                                             items are also enclosed in double
  462.                                             square brackets.
  463.  
  464.  Repeating elements...                      Three dots following an item
  465.                                             indicate that more items having
  466.                                             the same form may be entered.
  467.  
  468.  CALL GetNum (i, *10)                       A  column of three dots indicates
  469.  .                                          that part of the example program
  470.  .                                          has intentionally been omitted.
  471.  .
  472.  SUBROUTINE GetNum (i, *)
  473.  
  474.  KEY NAMES                                  Small capital letters are used
  475.                                             for the names of keys and key
  476.                                             sequences, such as ENTER and
  477.                                             CTRL+C.
  478.  
  479.                                             A plus (+) indicates a
  480.                                             combination of keys. For example,
  481.                                             CTRL+E means to hold down the
  482.                                             CTRL key while pressing the E
  483.                                             key.
  484.  
  485.                                             The carriage-return key,
  486.                                             sometimes marked with a bent
  487.                                             arrow, is referred to as ENTER.
  488.  
  489.                                             The cursor movement ("arrow")
  490.                                             keys on the numeric keypad are
  491.                                             called DIRECTION keys. Individual
  492.                                             DIRECTION keys are referred to by
  493.                                             the direction of the arrow on the
  494.                                             top of the key (LEFT, RIGHT, UP,
  495.                                             DOWN) or the name on the top of
  496.                                             the key (PGUP, PGDN).
  497.  
  498.                                             The key names used in this manual
  499.                                             correspond to the names on the
  500.                                             IBM Personal Computer keyboard.
  501.                                             Other machines may use different
  502.                                             names.
  503.  
  504.  "defined term"                             Quotation marks usually indicate
  505.                                             a new term defined in the text.
  506.  
  507.  Video Graphics Array (VGA)                 Acronyms are usually spelled out
  508.                                             the first time they are used.
  509.  
  510.  
  511.  ───────────────────────────────────────────────────────────────────────────
  512.  Part 1  Working with Microsoft FORTRAN
  513.  
  514.  Part 1 covers several topics that let you tailor applications written in
  515.  Microsoft FORTRAN to your specific needs. These topics include options for
  516.  handling floating-point math operations, control over memory models and
  517.  segment usage, and special features available under OS/2, such as multiple
  518.  threads of execution and dynam-ically linked libraries.
  519.  
  520.  Two chapters discuss how to call other-language programs from  Microsoft
  521.  FORTRAN──including C, Pascal, BASIC, and assembly languages, such as
  522.  Microsoft Macro Assembler (MASM). Review these chapters if you plan to port
  523.  programs written in FORTRAN to other computers and you want them to access
  524.  data created by other applications. Since FORTRAN supports several record
  525.  structures, one chapter reviews each of the different structures and its
  526.  particular strengths. The last chapter describes strategies for optimizing
  527.  programs for both size and speed.
  528.  
  529.  
  530.  Chapter 1  Controlling Floating- Point Operations
  531.  ───────────────────────────────────────────────────────────────────────────
  532.  
  533.  Microsoft FORTRAN 5.0 lets you control how your programs handle
  534.  floating-point math operations. In calculation-intensive programs, a well
  535.  chosen floating-point option can speed execution and increase precision.
  536.  This chapter describes the math packages you can install in FORTRAN
  537.  libraries when you run the SETUP program. It also discusses the FL command
  538.  options for choosing the appropriate library for linking and controlling
  539.  floating-point instructions. (For specific information on the FL command,
  540.  see Chapter 7 in the Microsoft FORTRAN Reference.)
  541.  
  542.  This chapter also explains how to override floating-point options by
  543.  changing libraries at link time; how to control an 8087, 80287, or 80387
  544.  coprocessor with the NO87 environment variable; and how to handle the
  545.  8087/80287/80387 floating-point exceptions. Finally, if you run your program
  546.  on a computer that is not IBM compatible, review the last section of the
  547.  chapter for any special considerations for your machine.
  548.  
  549.  
  550.  1.1  Choosing a Math Package
  551.  
  552.  The Microsoft FORTRAN Compiler offers a choice of these floating-point math
  553.  packages:
  554.  
  555.    ■  8087/287/387 (default) package
  556.    ■  Emulator package
  557.    ■  Alternate math package
  558.  
  559.  ───────────────────────────────────────────────────────────────────────────
  560.  NOTE
  561.     The math options support the Intel(R) 8087, 80287, and 80387 math
  562.     coprocessors. For brevity, this book uses the term "8087/287/387" to
  563.     refer to all three coprocessors.
  564.  ───────────────────────────────────────────────────────────────────────────
  565.  
  566.  When you run the SETUP program, you choose one of these math packages. SETUP
  567.  includes the math package you choose in the library it builds. Any programs
  568.  linked to that library use the math package included in the library; you
  569.  must apply the appropriate FL option to make sure that the library you want
  570.  is used at link time.
  571.  
  572.  Use the following descriptions of the math packages to help you choose the
  573.  option that best suits your needs when you run SETUP. (You can run SETUP as
  574.  many times as necessary to build the libraries you want.)
  575.  
  576.  
  577.  1.1.1  The 8087/287/387 Package
  578.  
  579.  The FORTRAN 8087/80287/80387 math package takes full advantage of a math
  580.  coprocessor to perform floating-point operations. Intensive floating-point
  581.  operations tend to slow down computer operations. The 8087/287/387
  582.  coprocessors are math chips dedicated to performing floating-point
  583.  operations rapidly.
  584.  
  585.  This package requires an installed math coprocessor chip; programs compiled
  586.  to use this package fail to run without the coprocessor (an error message
  587.  reading floating point not loaded is issued). This is the default math
  588.  package that SETUP uses if you do not explicitly choose another package.
  589.  
  590.  
  591.  1.1.2  The Emulator Package
  592.  
  593.  The emulator package uses an 8087, 80287, or 80387 coprocessor if one is
  594.  installed. If no coprocessor is available, this package emulates many of the
  595.  8087/287/387 functions with software. The emulator package is the best
  596.  choice if you want to maximize program precision and speed and you want the
  597.  program to run on systems with and without coprocessors.
  598.  
  599.  The emulator package can perform basic operations to the same degree of
  600.  precision as an 8087/287/387 chip. However, the emulator routines used for
  601.  transcendental math functions differ slightly from the corresponding
  602.  8087/287/387 functions. This can cause a slight difference (usually within 2
  603.  bits) in the results of such operations when performed with the emulator
  604.  instead of with an 8087/287/387.
  605.  
  606.  ───────────────────────────────────────────────────────────────────────────
  607.  NOTE
  608.     When you use an 8087, 80287, or 80387 coprocessor or the emulator, the
  609.     interrupt-enable, precision, underflow, and denormalized-operand
  610.     exceptions are masked by default. The remaining exceptions are unmasked.
  611.  ───────────────────────────────────────────────────────────────────────────
  612.  
  613.  
  614.  1.1.3  The Alternate Math Package
  615.  
  616.  The alternate math package gives you the smallest and fastest programs
  617.  possible without a coprocessor. However, the program results are not
  618.  accurate to as many significant digits as results given by the emulator
  619.  package or 8087/287/387 math coprocessors.
  620.  
  621.  The alternate math package uses a subset of the Institute of Electrical and
  622.  Electronics Engineers, Inc. (IEEE) standard format numbers. Infinities,
  623.  NANs, and denormal numbers are not used.
  624.  
  625.  
  626.  1.2  Using the Floating-Point Options (/FP)
  627.  
  628.  The /FP options of the FL command control how a program handles
  629.  floating-point operations. Based on the /FP option and the memory-model
  630.  option you choose, the FL command embeds a library name in the object file
  631.  it creates. (See Table 1.1, "Summary of Floating-Point Options," for a list
  632.  of the library names used for each combination.) Unless the /Lp or /Lr
  633.  option is specified, this library becomes the default library; that is, the
  634.  linker searches in the standard places for a library with that name. If it
  635.  finds such a library, the linker uses that library to resolve external
  636.  references in the object file. Otherwise, the linker displays a message
  637.  indicating that it could not find the library. (The /Lp and /Lr options use
  638.  the OS/2 dual-mode naming conventions. See Chapter 3 for a discussion of
  639.  OS/2 default library names. Unless otherwise indicated, this chapter assumes
  640.  that you use the DOS naming conventions.)
  641.  
  642.  This mechanism allows the linker to link the object file automatically with
  643.  the requested library. However, there are exceptions to the rule; you are
  644.  allowed to link with a different library in some cases (as explained later
  645.  in this section and in Section 1.3, "Library Considerations in Selecting /FP
  646.  Options").
  647.  
  648.  You should use only one of these options on the FL command line. The option
  649.  applies to the entire command line, regardless of its position. (Note that x
  650.  represents a wild card, so that xLIBFORA.LIB refers to either LLIBFORA.LIB
  651.  or MLIBFORA.LIB.) The available options are listed below.
  652.  
  653.       Option                           Effect
  654.  
  655.       /FPa                             Generates floating-point calls;
  656.                                        selects xLIBFORA.LIB
  657.  
  658.       /FPc                             Generates floating-point calls;
  659.                                        selects xLIBFORE.LIB
  660.  
  661.       /FPc87                           Generates floating-point calls;
  662.                                        selects xLIBFOR7.LIB
  663.  
  664.       /FPi                             Generates in-line instructions;
  665.                                        selects xLIBFORE.LIB
  666.  
  667.       /FPi87                           Generates in-line instructions;
  668.                                        selects  xLIBFOR7.LIB (default)
  669.  
  670.  Each /FP option includes two specifications:
  671.  
  672.    1. The floating-point instructions, either in-line 8087/287/387
  673.       instructions or calls to floating-point library functions. The letter
  674.       "i" indicates in-line instructions; the letters "c" or "a" indicate
  675.       floating-point calls.
  676.  
  677.    2. The default floating-point package to use when you link the program.
  678.  
  679.  Table 1.1 summarizes the /FP options and their effects.
  680.  
  681.  Table 1.1  Summary of Floating-Point Options
  682.  
  683.                                                              Use of
  684.  Option         Method            Advantages                 Coprocessor
  685.  
  686.  /FPi87         In line           Smallest memory            Required
  687.                                   requirements and
  688.                                   fastest option
  689.                                   available with a
  690.                                   coprocessor
  691.  
  692.  /FPc87         Calls             Slower than /FPi87,        Required
  693.                                   but allows library
  694.                                   changes at link time
  695.  
  696.  /FPi           In line           Larger than /FPi87,        Used if
  697.                                   but works without a        present
  698.                                   coprocessor; maximizes
  699.                                   precision without a
  700.                                   coprocessor
  701.  
  702.  /FPc           Calls             Slower than /FPi, but      Used if
  703.                                   allows changing            present
  704.                                   library at link time
  705.  
  706.  /FPa           Calls             Fastest and smallest       Ignores
  707.                                   option available           coprocessor
  708.                                   without a coprocessor,
  709.                                   but sacrifices
  710.                                   accuracy to speed
  711.  
  712.  
  713.  The /AL (large) memory-model option is the default. Therefore, if no
  714.  memory-model option is given on the same FL command line, the default
  715.  library for each floating-point option is LLIBFORx.LIB (where x is 7, E, or
  716.  A, depending on the math package the library supports). If the /AM
  717.  memory-model option is given, the default library is MLIBFORx.LIB.
  718.  
  719.  The compiler may evaluate some expressions. Such evaluations always use the
  720.  highest precision possible independent of the floating-point option you
  721.  choose.
  722.  
  723.  Sections 1.2.1-1.2.5 discuss the /FP options and the advantages and
  724.  disadvantages of each option.
  725.  
  726.  
  727.  1.2.1  The /FPi87 Option
  728.  
  729.  The default floating-point option is /FPi87, which includes the name of an
  730.  8087/287/387 library (either LLIBFOR7.LIB or MLIBFOR7.LIB, depending on the
  731.  memory model) in the object file. At link time, you can change your mind and
  732.  link explicitly with an emulator library (either with LLIBFORE.LIB or
  733.  MLIBFORE.LIB, depending on the memory model). If you use this option and
  734.  link with an 8087/287/387 library, an 8087, 80287, 80387 coprocessor must be
  735.  present at run time; otherwise, the program fails and the math package
  736.  displays an error message reading
  737.  
  738.             floating point not loaded
  739.  
  740.  the /FPi87 option.
  741.  
  742.  If you compile with /FPi87 and link with an emulator library, and a
  743.  coprocessor is present at run time, you can use the NO87 environment
  744.  variable if you wish to suppress the use of the coprocessor. (See Section
  745.  1.4 for a description of NO87.) If you link with an 8087/287/387 library,
  746.  the /FPi87 option is the fastest and smallest option available for
  747.  floating-point operations.
  748.  
  749.  The Microsoft FORTRAN Compiler does not generate true in-line 8087/287 code
  750.  when you use the /FPi87 option. Instead, the compiler inserts software
  751.  interrupts to library-code software that direct each interrupt to use either
  752.  the emulator or coprocessor, as appropriate. If you have linked the emulator
  753.  code to your program, these interrupts will call the emulator if a math chip
  754.  is not available.
  755.  
  756.  If your program is designed to run only with a coprocessor, you can speed up
  757.  the program by assembling and linking the following code, which eliminates
  758.  this special processing. In addition, all divide-by-zero errors will be
  759.  masked.
  760.  
  761.       PUBLIC FIARQQ, FICRQQ, FIDRQQ, FIERQQ, FISRQQ, FIWRQQ
  762.       PUBLIC FJARQQ, FJCRQQ, FJSRQQ
  763.  
  764.       FIARQQ EQU O
  765.       FICRQQ EQU O
  766.       FIDRQQ EQU O
  767.       FIERQQ EQU O
  768.       FISRQQ EQU O
  769.       FIWRQQ EQU O
  770.       FJARQQ EQU O
  771.       FJCRQQ EQU O
  772.       FJSRQQ EQU O
  773.  
  774.       extrn __fpmath:for
  775.       extrn __fpsignal:for
  776.       extrn __fptaskdata:for
  777.  
  778.       CDATA segment word common 'DATA'
  779.           dw 0
  780.           dw__fpmath
  781.           dw__fpsignal
  782.           dw__fptaskdata
  783.       CDATA ends
  784.  
  785.       END
  786.  
  787.  
  788.  1.2.2  The /FPc87 Option
  789.  
  790.  The /FPc87 option generates function calls to routines in the 8087/287/387
  791.  library (LLIBFOR7.LIB or MLIBFOR7.LIB, depending on the memory model) that
  792.  perform the corresponding 8087/287/387 instructions. As with the /FPi87
  793.  option, you must have an 8087, 80287, or 80387 coprocessor installed to run
  794.  programs compiled with this option and linked to an 8087/287/387 library.
  795.  How-ever, the /FPc87 option also allows you to change your mind at link time
  796.  and link to an alternate math library instead of emulator or 8087/287/387
  797.  libraries. (See Section 1.3, "Library Considerations in Selecting /FP
  798.  Options," for information about changing libraries at link time.)
  799.  
  800.  ───────────────────────────────────────────────────────────────────────────
  801.  NOTE
  802.     Certain optimizations are not performed when /FPc87 is used, reducing the
  803.     efficiency of your code. Since arithmetic of different precision may
  804.     occur, the results may vary slightly.
  805.  ───────────────────────────────────────────────────────────────────────────
  806.  
  807.  
  808.  1.2.3  The /FPi Option
  809.  
  810.  The /FPi option generates in-line instructions for an 8087, 80287, or 80387
  811.  coprocessor and places the name of the emulator library (LLIBFORE.LIB or
  812.  MLIBFORE.LIB) in the object file. This option is particularly useful when
  813.  you do not know in advance whether or not an 8087/287/387 coprocessor will
  814.  be available at run time. If you distribute your program for use on other
  815.  computers, you should use the /FPi option.
  816.  
  817.  If a coprocessor is present at run time, the program uses the coprocessor.
  818.  If not, the emulator carries out the floating-point operations. If a
  819.  coprocessor is not present at run time, the /FPi option is the most
  820.  efficient way to maximize floating-point precision.
  821.  
  822.  
  823.  1.2.4  The /FPc Option
  824.  
  825.  The /FPc option generates floating-point calls to the emulator library and
  826.  then places the name of the emulator library (LLIBFORE.LIB or MLIBFORE.LIB,
  827.  depending on the memory model) in the object file. The /FPc option gives you
  828.  more flexibility than /FPi, since it allows linking with either an
  829.  8087/287/387 or  alternate math library instead of an emulator library. (See
  830.  Section 1.3 below for information about changing libraries at link time.)
  831.  This option is also recommended if you link to libraries other than the ones
  832.  SETUP builds.
  833.  
  834.  
  835.  1.2.5  The /FPa Option
  836.  
  837.  The /FPa option generates floating-point calls and selects the alternate
  838.  math library (LLIBFORA.LIB or MLIBFORA.LIB, depending on the memory model).
  839.  This library provides the fastest and smallest library if you do not use an
  840.  8087, 80287, or 80387 coprocessor. Like the /FPc option, /FPa lets you
  841.  decide at link time whether to use an emulator or 8087/287/387 library.
  842.  
  843.  
  844.  1.3  Library Considerations in Selecting /FP Options
  845.  
  846.  Sometimes you may want to use other libraries in addition to the default
  847.  library for the floating-point option you chose on the FL command line. For
  848.  example, you may want to create your own libraries or other collections of
  849.  subprograms in object-file form and link these libraries at a later time
  850.  with object files that you have compiled using different FL options. The
  851.  following sections discuss these cases and how to handle them. Although the
  852.  discussion assumes that you put your precompiled object files into
  853.  libraries, the same considerations apply if you use individual object files.
  854.  
  855.  
  856.  1.3.1  Choosing In-Line Instructions or Calls
  857.  
  858.  To choose an appropriate floating-point option, you must first decide
  859.  whether you want to use in-line instructions and compile with the /FPi87 or
  860.  /FPi option, or if you want to use floating-point function calls and compile
  861.  with the /FPc87, /FPc, or /FPa option.
  862.  
  863.  If you choose in-line instructions for your precompiled object files, you
  864.  cannot use the alternate math package (that is, you cannot link with an
  865.  xLIBFORA.LIB library). However, in-line instructions give the best
  866.  performance if you run your program on machines with an 8087, 80287, or
  867.  80387 coprocessor.
  868.  
  869.  If you choose calls, your code executes more slowly, but at link time you
  870.  can use any standard FORTRAN library (that is, any library created by the
  871.  SETUP program) that supports the current memory model.
  872.  
  873.  
  874.  1.3.2  Using a Standard Library for Linking
  875.  
  876.  You must use only one standard FORTRAN library when you link. You can
  877.  control which library is used in one of two ways:
  878.  
  879.    1. At link time, as the first name in the list of object files to be
  880.       linked, give an object file that contains the name of the desired
  881.       library. For example, if you want to use the alternate math library,
  882.       you must give the name of an object file compiled using the /FPa
  883.       option. All floating-point calls in this object file refer to the
  884.       alternate math library.
  885.  
  886.    2. At link time, select the /NOD (no-default library search) option and
  887.       then give the name of the library file containing the floating-point
  888.       package you want to use in the "Libraries" field or in response to the
  889.       "Libraries" prompt. This library overrides the library names in the
  890.       object files; all floating-point calls refer to the named library.
  891.  
  892.  Each library in the object files being linked is added to the "linker search
  893.  list" (that is, the list of libraries that the linker searches to resolve
  894.  calls external to FORTRAN). This searching can complicate the choice of a
  895.  standard library.
  896.  
  897.  Suppose, for example, that you use the /FPa option on a large memory-model
  898.  program to create a set of object files and then use the LIB utility to
  899.  combine these object files into a library. Very possibly, each object file
  900.  would include a default library name (that is, you did not use the /Zl
  901.  option to compile). If you want to link this library with an object file
  902.  created using the /FPc87 option, note that both LLIBFOR7.LIB and
  903.  LLIBFORA.LIB are in the linker search list (assuming you compiled with the
  904.  default memory-model option). The linker searches libraries on the command
  905.  line first, so it searches LLIBFOR7.LIB before it searches LLIBFORA.LIB.
  906.  Since LLIBFOR7.LIB would resolve all external references correctly, this
  907.  mechanism works correctly.
  908.  
  909.  You can ensure that the standard library of your choice is used for linking
  910.  by explicitly giving the library name on the LINK command line. In this
  911.  case, LINK always searches the library you specify before it searches any
  912.  libraries named in the object files. However, make sure you specify this
  913.  library after you have specified any of your own libraries on the LINK
  914.  command line. If you do not specify it, and your library contains a
  915.  different search directive, you may encounter problems.
  916.  
  917.  For example, suppose the object modules in library B were compiled with the
  918.  /FPc87 option, so that each module contains a search directive for the
  919.  library LLIBFOR7.LIB. You want to link with an object file A compiled with
  920.  the /FPa option, so that this object file contains a search directive for
  921.  LLIBFORA.LIB. The following command line links library B with the object
  922.  file A:
  923.  
  924.       LINK A,,,LLIBFOR7+B;
  925.  
  926.  The linker then searches the libraries in the following order:
  927.  
  928.    1. LLIBFOR7.LIB (since it is specified first on the command line)
  929.  
  930.    2. B (since it is specified second on the command line)
  931.  
  932.    3. LLIBFORA.LIB (since the object module A contains a search directive
  933.       for this library)
  934.  
  935.    4. LLIBFOR7.LIB (since the modules in your library B contain search
  936.       directives for this library)
  937.  
  938.  The link procedure would be as follows:
  939.  
  940.    1. The linker searches LLIBFOR7.LIB and resolves all references in object
  941.       file A to standard run-time routines, since you specified this library
  942.       on the command line.
  943.  
  944.    2. The linker closes LLIBFOR7.LIB and searches the next library in the
  945.       list to satisfy references to routines in your library B. These
  946.       routines normally contain references to standard run-time routines.
  947.       Since LLIBFORA.LIB is the next library to be searched, this library
  948.       satisfies the references in B. How-ever, this is not the library you
  949.       intended to use, since you compiled B with the /FPc87 option, which
  950.       uses LLIBFOR7.LIB to resolve references to standard run-time routines.
  951.  
  952.  As indicated in the example above, you cannot mix libraries in this fashion;
  953.  you may get linker errors if you try. Note that if you had specified the
  954.  library B+LLIBFOR7.LIB instead of LLIBFOR7.LIB+B on the LINK command line,
  955.  the linker would have searched LLIBFOR7.LIB instead of the library
  956.  LIBFORA.LIB to resolve standard run-time references in B, and the linking
  957.  operation would have proceeded correctly.
  958.  
  959.  To avoid this kind of ambiguity and to make absolutely sure you are
  960.  specifying the correct standard library for linking, use the /NOD linker
  961.  option. This option causes the linker to search only the libraries that you
  962.  specify on the command line.
  963.  
  964.  Alternately, use the /NOD: libraryname form to suppress the default search
  965.  for a specific library. This is useful if a library specified on the command
  966.  line includes search directives for other libraries that you do not wish to
  967.  specify explicitly on the command line. For example, the OS/2 protected-mode
  968.  libraries contain search directives for the support library, DOSCALLS.LIB.
  969.  
  970.  Perhaps the safest course of all, especially when you are distributing
  971.  libraries to other users, is to compile the object files that make up the
  972.  library with the /Zl option. This option tells the compiler not to include
  973.  search directives in the object files. Later on, when you link the library
  974.  with different object files, the standard library used for linking depends
  975.  only on the floating-point and memory-model options used to compile the
  976.  later object files. The /FPc compiler option is recommended for maximum
  977.  flexibility when linking with such libraries.
  978.  
  979.  In the example below, the source file CALC.FOR is compiled with the default
  980.  floating-point option, /FPi87:
  981.  
  982.       FL /c CALC.FOR
  983.       LINK CALC+ANOTHER+SUM;
  984.  
  985.  /FPi87 generates in-line instructions and selects the 8087/287/387 library
  986.  (that is, LLIBFOR7.LIB, since no floating-point option is given and the
  987.  large-model library is the default).
  988.  
  989.  In the following example, CALC.FOR  is compiled with the alternate math
  990.  option (/FPa):
  991.  
  992.       FL /c /FPa CALC.FOR
  993.       FL CALC ANOTHER SUM /link LLIBFORE.LIB /NOD
  994.  
  995.  When the FL command is used to link, the /link field (options appearing
  996.  after /link) specifies the /NOD option so that the LLIBFORA.LIB library
  997.  (whose name is embedded in the object fileCALC.OBJ ) is not searched. This
  998.  field gives the name LLIBFORE.LIB, which causes all floating-point calls to
  999.  refer to the emulator library instead of the alternate math library.
  1000.  
  1001.  In the example below, SAMPLE.FOR  is compiled with the /FPc87 option, which
  1002.  selects the 8087/287/387 library LLIBFOR7.LIB, as the default library:
  1003.  
  1004.       FL /FPc87 SAMPLE.FOR /link /NOD:LLIBFOR7.LIB LLIBFAP.LIB
  1005.  
  1006.  However, the command line uses the /NOD: option to suppress the selection of
  1007.  LLIBFOR7.LIB, and tells the linker to use LLIBFAP.LIB instead (the
  1008.  OS/2-protected mode of the alternate math library). The /NOD: option
  1009.  instructs the linker to ignore the next library specified on the command
  1010.  line, but to include any subsequent libraries (and any references they
  1011.  contain to other libraries). Thus, DOSCALLS.LIB (referenced in LLIBFAP.LIB)
  1012.  is still searched.
  1013.  
  1014.  
  1015.  1.3.3  Ensuring Compatibility between Options
  1016.  
  1017.  Each time you compile a source file, you can specify a floating-point
  1018.  option. When you link more than one object file to produce an executable
  1019.  program file, you must ensure that floating-point operations are handled in
  1020.  a consistent way and that the current environment allows the linker to find
  1021.  the required library. Left to itself, the linker may or may not pick the
  1022.  library you intended. (See the Microsoft FORTRAN Getting Started manual for
  1023.  information about choosing floating-point options for the libraries you
  1024.  build with the SETUP program.)
  1025.  
  1026.  ───────────────────────────────────────────────────────────────────────────
  1027.  NOTE
  1028.     If you are building your own libraries of routines that contain
  1029.     floating-point operations, the /FPc floating-point option is recommended
  1030.     for all compilations, as it offers the greatest flexibility.
  1031.  ───────────────────────────────────────────────────────────────────────────
  1032.  
  1033.  
  1034.  1.3.4  Special Procedure for MS-DOS 3.2 Users
  1035.  
  1036.  This section is important only if your system has all of the following:
  1037.  
  1038.    ■  You use MS-DOS Version 3.2.
  1039.    ■  You boot from a hard disk drive.
  1040.    ■  Your computer uses a math coprocessor (such as the 80387).
  1041.    ■  You run programs that use floating-point math.
  1042.  
  1043.  For systems that satisfy all of the preceding conditions, you may be able to
  1044.  eliminate floating-point math problems by installing a small patch in DOS.
  1045.  
  1046.  ───────────────────────────────────────────────────────────────────────────
  1047.  NOTE
  1048.     The floating-point problem has been eliminated in versions of DOS higher
  1049.     than 3.2. This includes DOS 3.21 and 3.3.
  1050.  ───────────────────────────────────────────────────────────────────────────
  1051.  
  1052.  If you are not sure whether you need the patch, take these steps:
  1053.  
  1054.    1. Copy the program PATCH87.EXE (included in this release) to the root
  1055.       directory of your hard drive.
  1056.  
  1057.    2. Reboot your system from the hard disk. Do not perform any floppy-disk
  1058.       operations after rebooting. It is very important to avoid floppy-disk
  1059.       I/O after rebooting because it will affect the reliability of the
  1060.       diagnostic test you are about to perform.
  1061.  
  1062.    3. If necessary, use the CD command from DOS to move to the root directory
  1063.       of your hard disk.
  1064.  
  1065.    4. Run the PATCH87.EXE program by entering this command at the DOS prompt:
  1066.  
  1067.            PATCH87
  1068.  
  1069.  The program then performs a diagnostic test on your system to determine
  1070.  whether it needs the DOS patch and, if so, whether it can be performed
  1071.  successfully.
  1072.  
  1073.  If the test indicates that you should install the DOS patch, take these
  1074.  steps:
  1075.  
  1076.    1. Format a blank floppy disk. (Do not use the /S formatting option to
  1077.       transfer system files to the disk. See Chapter 3 of the Microsoft
  1078.       FORTRAN Reference, "Nonrepeatable Edit Descriptors," for more
  1079.       information on /S.)
  1080.  
  1081.    2. Use the SYS command to copy IO.SYS and MSDOS.SYS (or PCDOS.SYS) from
  1082.       the root directory of your hard disk to the new floppy disk. For
  1083.       instance, if you boot from drive C:, you would enter the following
  1084.       commands:
  1085.  
  1086.          C:
  1087.          SYS A:
  1088.  
  1089.    3. Use the COPY command to copy COMMAND.COM and SYS.COM to the same floppy
  1090.       disk.
  1091.  
  1092.    4. Use the COPY command to copy the program PATCH87.EXE (included in this
  1093.       release) to the same floppy disk.
  1094.  
  1095.    5. Change the current drive and directory to the floppy disk, by entering
  1096.  
  1097.          A:
  1098.  
  1099.    6. Install the DOS patch by entering
  1100.  
  1101.          PATCH87 /F
  1102.  
  1103.  ───────────────────────────────────────────────────────────────────────────
  1104.  WARNING
  1105.     If you experience any disk errors during steps 2 through 6, do not
  1106.     proceed with step 7. Reboot from your hard disk and repeat the entire
  1107.     process.
  1108.  ───────────────────────────────────────────────────────────────────────────
  1109.  
  1110.    1. If you do not experience any errors, use the SYS command to transfer
  1111.       the files IO.SYS and MSDOS.SYS (or PCDOS.SYS) from the floppy disk back
  1112.       to your hard disk. For instance, if your system boots from the root
  1113.       directory of drive C:, you would enter the following command at the DOS
  1114.       prompt:
  1115.  
  1116.           A:
  1117.           SYS C:
  1118.  
  1119.    2. The DOS patch has been installed. Reboot the system.
  1120.  
  1121.  
  1122.  1.3.5  Using $FLOATCALLS and $NOFLOATCALLS
  1123.  
  1124.  The $FLOATCALLS and $NOFLOATCALLS metacommands control whether
  1125.  floating-point operations are processed through calls to library subroutines
  1126.  or by in-line instructions. These metacommands are no longer recommended.
  1127.  The /FP options offer similar control and are more flexible because they
  1128.  select the library to be used as well as the processing method.
  1129.  
  1130.  However, if you have existing code that contains these metacommands, keep in
  1131.  mind that $FLOATCALLS and $NOFLOATCALLS control only the processing method
  1132.  for floating-point operations. They do not affect the library name that the
  1133.  compiler places in the object file; this is still determined by the /FP and
  1134.  /A options that you choose on the FL command line.
  1135.  
  1136.  Also note that these metacommands take precedence over the floating-point
  1137.  options you give on the FL command line. This may mean, for example, that a
  1138.  source file containing $NOFLOATCALLS may result in an object file that
  1139.  contains in-line instructions, even if it were compiled with the /FPa
  1140.  option. Such an object file would not link correctly with an alternate math
  1141.  library.
  1142.  
  1143.  
  1144.  1.4  Using the NO87 Environment Variable
  1145.  
  1146.  Programs compiled with the /FPc or /FPi option use an 8087/287/387
  1147.  coprocessor at run time if one is installed. You can override this and force
  1148.  the use of the emulator instead by setting the NO87 environment variable.
  1149.  (See Section 2.5.1 or your DOS documentation for a discussion of environment
  1150.  variables.)
  1151.  
  1152.  If NO87 is set to any value when the program executes, the program ignores
  1153.  an 8087/287/387 coprocessor. The value of the NO87 setting appears on the
  1154.  standard output as a message. The message displays only if an 8087/287/387
  1155.  is present and suppressed; if no coprocessor is present, no message appears.
  1156.  If you don't want a message printed out, set NO87 equal to one or more
  1157.  spaces.
  1158.  
  1159.  Note that only the presence or absence of the NO87 definition is important
  1160.  in suppressing use of the coprocessor. The actual value of the NO87 setting
  1161.  only affects whether a message prints on the screen.
  1162.  
  1163.  The NO87 variable takes effect with any program linked with the emulator
  1164.  library (LLIBFORE.LIB or MLIBFORE.LIB). It has no effect on programs linked
  1165.  with LLIBFOR7.LIB, MLIBFOR7.LIB, MLIBFORA.LIB, or LLIBFORA.LIB.
  1166.  
  1167.  The following is an example of how NO87 can be used:
  1168.  
  1169.       SET NO87=Use of coprocessor suppressed
  1170.  
  1171.  This statement causes the message Use of coprocessor suppressed to appear
  1172.  on the screen when running a program that can use an installed 8087, 80287,
  1173.  or 80387 coprocessor. Note that if the equal sign is followed by a blank
  1174.  space, the coprocessor is suppressed but no message is displayed.
  1175.  
  1176.  The example below assigns no variable to NO87; the statement does not affect
  1177.  the coprocessor Note that no characters or spaces can follow the equal sign.
  1178.  
  1179.       SET NO87=
  1180.  
  1181.  Programs that can use an 8087/287/387 coprocessor do use it, if one is
  1182.  present.
  1183.  
  1184.  
  1185.  1.5  Handling 8087/287/387 Floating-Point Exceptions
  1186.  
  1187.  The five exceptions to floating-point arithmetic required by the IEEE
  1188.  standard are supported by the 8087/287/387 coprocessor and the real-math
  1189.  support routines. Exceptions that would result in a NAN ("Not a Number")
  1190.  error message are enabled by default. The others are disabled.
  1191.  
  1192.  These exceptions are not affected by the $DEBUG metacommand; instead, they
  1193.  are controlled by a "status" word and a "control" word, as explained below.
  1194.  
  1195.  Table 1.2 explains the six exceptions and their default and alternative
  1196.  actions.
  1197.  
  1198.  Table 1.2  Floating-Point Exceptions
  1199.  
  1200.  Floating-Point                                     Default
  1201.  Exception               Explanation                Action
  1202.  
  1203.  Invalid operation       Results in a NAN, such     Enabled; gives
  1204.                          as the square root of      run-time error message
  1205.                          -1 or 0*INF                M6101
  1206.  
  1207.  Divide by zero          Evaluates to a real        Enabled; gives
  1208.                          number divided by          run-time error message
  1209.                          zero: r/0.0                M6103
  1210.  
  1211.  
  1212.  
  1213.  Overflow                Results in a number        Enabled; gives
  1214.                          greater than maximum       run-time error message
  1215.                          representable number       M6104
  1216.  
  1217.  Underflow               Results in a number        Disabled; returns zero
  1218.                          smaller than the
  1219.                          smallest valid
  1220.                          representable number
  1221.  
  1222.  Denormalized            Results in a number
  1223.  operand                 so small that it can
  1224.                          only be approximately
  1225.                          represented
  1226.  
  1227.  Precision (or           Occurs whenever a          Disabled; returns
  1228.  inexact)                result is subject to       properly rounded
  1229.                          rounding error             result
  1230.  
  1231.  
  1232.  If any of these six exceptions are disabled, you can get NAN, Infinite, or
  1233.  Indefinite values in your variables. If you print such a value, the output
  1234.  field will contain NAN, INF, or IND, padded with periods to the field width.
  1235.  If the output field has fewer than three spaces, only periods are printed.
  1236.  
  1237.  
  1238.  1.5.1  Controlling the Processing Environment
  1239.  
  1240.  The 8086/286/386 and 8087/287/387 processors are controlled by the status
  1241.  word and the control word, respectively. This section describes the uses of
  1242.  these memory locations.
  1243.  
  1244.  When one of the floating-point-exception conditions given in Table 1.2 above
  1245.  occurs, the appropriate bit in the status word is set. This flag remains set
  1246.  until you clear it.
  1247.  
  1248.  Figure 1.1 shows the format of the status word.
  1249.  
  1250.  When the bit corresponding to one of these exceptions is set (equals 1) in
  1251.  the control word, that exception is masked, and the operation that caused
  1252.  the exception proceeds with its default action. Alternately, if a bit is
  1253.  reset (equals 0), the corresponding exception generates an error message,
  1254.  halts the operation, and terminates the program. In either case, the
  1255.  exception is logically connected (with OR) into the status word. See Chapter
  1256.  1 in the Microsoft FORTRAN Reference for more information on logical
  1257.  operators.
  1258.  
  1259.  Figure 1.2 shows the format of the control word.
  1260.  
  1261.  Besides masking-exception conditions, the control word is used to set the
  1262.  following modes for the internal arithmetic required by the IEEE standard:
  1263.  
  1264.       Mode                        Description
  1265.  
  1266.       Infinity control            Chooses affine mode (the mode
  1267.                                   where the familiar +INF and -INF
  1268.                                   style of arithmetic is used) or
  1269.                                   projective mode (the mode where
  1270.                                   +INF and -INF are considered to
  1271.                                   be the same number). The
  1272.                                   principal effect of projective
  1273.                                   mode is to change the nature of
  1274.                                   comparisons; projective INF does
  1275.                                   not compare with anything but
  1276.                                   itself.
  1277.  
  1278.       Round control               Rounds to nearest (or even), up,
  1279.                                   down, or truncates.
  1280.  
  1281.       Precision control           Determines the bit of the
  1282.                                   mantissa (24, 53, or 64) at which
  1283.                                   rounding takes place. All results
  1284.                                   are stored to 64 bits regardless
  1285.                                   of precision control which
  1286.                                   affects only the rounding in the
  1287.                                   internal form. When stored, any
  1288.                                   result is rounded to the storage
  1289.                                   precision again.
  1290.  
  1291.  The current defaults for the control word are shown in the following list:
  1292.  
  1293.       Mode or Mask                Default
  1294.  
  1295.       Infinity control            Affine
  1296.       Round control               Nearest
  1297.       Precision control           64 bits
  1298.       Interrupt-enable mask       Unmasked
  1299.       Precision mask              Masked
  1300.       Underflow mask              Masked
  1301.       Overflow mask               Unmasked
  1302.       Zero-divide mask            Unmasked
  1303.       Denormalized-operand mask   Masked (cannot be changed)
  1304.       Invalid-operation mask      Unmasked
  1305.  
  1306.  Table 1.3 below defines the mask settings for the overflow, zero-divide, and
  1307.  invalid-operation exceptions associated with several optional control words.
  1308.  A control-word value of decimal 4914 specifies the default-mask settings
  1309.  that are customary during 8087/287/387 operations.
  1310.  
  1311.  Table 1.3  Mask Settings for Operation Exceptions
  1312.  
  1313.       Control Word       Overflow     Zero Divide
  1314.  
  1315.       4914 = 16#1332     Unmasked     Unmasked
  1316.       4915 = 16#1333     Unmasked     Unmasked
  1317.       4918 = 16#1336     Unmasked     Masked
  1318.       4919 = 16#1337     Unmasked     Masked
  1319.       4922 = 16#133A     Masked       Unmasked
  1320.       4923 = 16#133B     Masked       Unmasked
  1321.       4926 = 16#133E     Masked       Masked
  1322.       4927 = 16#133F     Masked       Masked
  1323.  
  1324.  
  1325.  1.5.2  Reading and Setting Status and Control Values
  1326.  
  1327.  You can use the following procedures and functions to read or set the values
  1328.  of the status and control words──the INTEGER*2 arguments passed to the
  1329.  appropriate routines as described below. Their values determine the behavior
  1330.  of the 8086/286/386 (status-word) and 8087/287/387 (control-word)
  1331.  processors.
  1332.  
  1333.  The store-status-word (SSWRQQ) function returns the value of the status
  1334.  word. Use the following declaration for this procedure:
  1335.  
  1336.             INTERFACE TO INTEGER*2 FUNCTION SSWRQQ()
  1337.             END
  1338.  
  1339.  The store-control-word (SCWRQQ) function returns the value of the control
  1340.  word. Use the following declaration for this procedure:
  1341.  
  1342.             INTERFACE TO INTEGER*2 FUNCTION SCWRQQ()
  1343.             END
  1344.  
  1345.  The load-control-word (LCWRQQ) procedure sets the control word to a given
  1346.  value. LCWRQQ has the following declaration:
  1347.  
  1348.             INTERFACE TO SUBROUTINE LCWRQQ(CW)
  1349.             INTEGER*2 CW
  1350.             END
  1351.  
  1352.  Always use LCWRQQ to change the control word. To ensure that special
  1353.  routines handling stack-exceptions and denormal propagation will work
  1354.  correctly, the control-word and auxiliary variables must be set up in the
  1355.  same way that LCWRQQ organizes them. (Denormals are numbers very close to
  1356.  zero──on the order of 10^(-38) or smaller──that allow gradual underflow. The
  1357.  Microsoft FORTRAN numeric inquiry functions such as NEAREST and PRECISION do
  1358.  not apply to denormalized numbers. See IEEE math or Intel chip
  1359.  specifications for detailed information on denormals.)
  1360.  
  1361.  ───────────────────────────────────────────────────────────────────────────
  1362.  NOTE
  1363.     Altering the 8087/287/387 control word with a macro assembler FLDCW
  1364.     (floating-point load-control word) instruction is not recommended if you
  1365.     use an 8087/287/387 coprocessor with a Microsoft language.
  1366.  ───────────────────────────────────────────────────────────────────────────
  1367.  
  1368.  Since the denormal exception is not a part of the IEEE standard, the
  1369.  Microsoft FORTRAN exception handler intercepts denormal exceptions to give
  1370.  the effect of being masked. The 8087/287/387 chips themselves do not mask
  1371.  denormals. You cannot alter this handling of denormals regardless of the
  1372.  denormal bit value in the LCWRQQ control word.
  1373.  
  1374.  The Microsoft FORTRAN exception handler allows for software masking of
  1375.  invalid operations, but does not allow the math chip to mask them. If you
  1376.  choose to use the software masking, be aware that this can affect program
  1377.  performance if you run software on other computers or compile code written
  1378.  for Microsoft FORTRAN with another compiler.
  1379.  
  1380.  
  1381.  1.5.3  Floating-Point Exceptions under PC-DOS 3.2
  1382.  
  1383.  Programs running under IBM Personal Computer DOS (PC-DOS) 3.2 that
  1384.  explicitly trap for floating-point exceptions may not operate when
  1385.  floating-point exceptions occur.
  1386.  
  1387.  Use the following procedure to patch IBM PC-DOS 3.2:
  1388.  
  1389.    1. Use the SYS command from PC-DOS to transfer IBMDOS.COM and IBMBIO.COM
  1390.       to a writable disk.
  1391.  
  1392.    2. Copy COMMAND.COM, SYS.COM, and DEBUG.COM from your PC-DOS 3.2 floppy
  1393.       disk to the new disk.
  1394.  
  1395.    3. Copy STKPAT.BAT, STKPAT.SCR, RMRHS.EXE, and SETRHS.EXE from the \PATCH
  1396.       directory (included in this release) to the new disk.
  1397.  
  1398.    4. Reboot the system from the new disk.
  1399.  
  1400.    5. Run STKPAT.BAT. This patches the IBMBIO.COM on the new disk.
  1401.  
  1402.    6. Use the SYS command from PC-DOS to transfer the patch to any other IBM
  1403.       PC-DOS 3.2 disk.
  1404.  
  1405.  If you are running any version of DOS 3.2 other than IBM PC-DOS 3.2, contact
  1406.  your hardware manufacturer to see if the problem exists in your DOS 3.2
  1407.  version.
  1408.  
  1409.  
  1410.  1.6  Using Non-IBM(R)-Compatible Computers
  1411.  
  1412.  If your computer is not an IBM or a closely compatible computer and you want
  1413.  to use an 8087/287/387 coprocessor, make sure that the computer handles
  1414.  exceptions correctly. All Microsoft languages that support the 8087/287/387
  1415.  coprocessors must intercept exceptions for accurate results and to detect
  1416.  error conditions properly. Most other language vendors do not detect or
  1417.  correct these errors.
  1418.  
  1419.  The exception handler in the emulator and the 8087/287/387 libraries (that
  1420.  is, LLIBFORE.LIB or MLIBFORE.LIB, and LLIBFOR7.LIB or MLIBFOR7.LIB,
  1421.  respectively) works without modification on the following computers:
  1422.  
  1423.    1. The IBM PC family
  1424.  
  1425.    2. Computers that are closely compatible with the IBM PC, such as the
  1426.       WANG(R) PC and the AT&T(R) 6300
  1427.  
  1428.    3. The Texas Instruments(R) Professional Computer
  1429.  
  1430.    4. Any machine that uses nonmaskable interrupts (NMI) for 8087/287/387
  1431.       exceptions
  1432.  
  1433.  If your computer is listed above, or if you are sure that it is completely
  1434.  IBM compatible, you can immediately begin linking your programs. If it is
  1435.  not listed, you may need to modify the 8087/287/387 libraries.
  1436.  
  1437.  The distribution disk contains an assembly-language source file, EMOEM.ASM,
  1438.  to help make any necessary modifications. Any machine that sends the
  1439.  8087/287/387 exception to an 8259 Priority Interrupt Controller (master or
  1440.  master/slave) can be supported easily by a simple table change to the
  1441.  EMOEM.ASM module. The source file contains further instructions on how to
  1442.  modify EMOEM.ASM and patch executable files.
  1443.  
  1444.  
  1445.  Chapter 2  Selecting a Memory Model
  1446.  ───────────────────────────────────────────────────────────────────────────
  1447.  
  1448.  You can gain greater control over how your program uses memory by specifying
  1449.  the program's memory model. This chapter explains the concept of memory
  1450.  models and discusses in detail each of the different models provided with
  1451.  the Microsoft FORTRAN Compiler: medium, large, and huge models. Later
  1452.  sections advise you on how to select an appropriate model for your program
  1453.  and how to make any necessary adjustments to that model.
  1454.  
  1455.  Adjusting a memory model to meet your program's requirements can produce
  1456.  more efficient code than using the default model. Understand the default
  1457.  models first, then learn to modify them to fit specific needs.
  1458.  
  1459.  
  1460.  2.1  What Is a Memory Model?
  1461.  
  1462.  A "memory model" is a set of predefined rules the compiler follows to
  1463.  transfer the program code and data into "segments" of 64K (kilobyte) blocks
  1464.  in memory. The memory model defines how the compiler organizes code and data
  1465.  into segments and what kind of addresses (near, far, or huge) will access
  1466.  the information in each segment. A near address is a 16-bit "offset"
  1467.  (location relative to the beginning of the current segment) that can access
  1468.  a maximum of 64K of mem-ory; a far address or a huge address is a 32-bit
  1469.  address that can access all avail-able memory. (See Section 2.2.2 for a
  1470.  discussion of the segmented memory and addresses of the 8086/80286
  1471.  microprocessor families.)
  1472.  
  1473.  When you select a memory model, you are telling the compiler that it can
  1474.  make certain assumptions about the program's characteristics and generate
  1475.  machine code accordingly. For example, when you select the large memory
  1476.  model (the default model for FORTRAN), the compiler allows for programs with
  1477.  more than 64K of code and 64K of data. The compiler must generate far
  1478.  addresses to access both code and data. In the medium model, the compiler
  1479.  expects only 64K or less of data, allowing it to generate near addresses to
  1480.  access data items.
  1481.  
  1482.  
  1483.  2.2  Understanding Memory Models
  1484.  
  1485.  To understand how memory models work, you need a basic understanding of the
  1486.  segmented architecture of the 8086 family of processors. The remainder of
  1487.  this section gives an overview of the addressing conventions used on the
  1488.  8086 processors and how they relate to memory models. Consult such
  1489.  references as the Programmer's Guide to the IBM PC for a detailed
  1490.  description of segments and their use.
  1491.  
  1492.  
  1493.  2.2.1  Code and Data Segments
  1494.  
  1495.  When you load a program into memory, its code (compiled executable
  1496.  statements) and data (information the program uses) are placed in separate
  1497.  storage areas. The processor treats the stored code as a sequence of
  1498.  operations to be carried out. A program refers to other code locations by
  1499.  making calls to subroutines or functions. Stored data are any values needed
  1500.  by the program, for which an area of memory is reserved, including variable
  1501.  names, arrays, or common blocks.
  1502.  
  1503.  All processors make this fundamental distinction between code and data.
  1504.  However, the way in which a program's code and data are stored and accessed
  1505.  depends on the architecture and addressing schemes of the particular
  1506.  processor being used.
  1507.  
  1508.  On the 8086, 80286, and 80386, code and data occupy separate segments and
  1509.  are accessed through separate segment registers. (See Section 2.2.2 for an
  1510.  explanation of the different types of addresses and the use of segment
  1511.  registers on the 8086/286/386.)
  1512.  
  1513.  
  1514.  2.2.2  Near, Far, and Huge Addresses
  1515.  
  1516.  The 8086 processor and its relatives are 16-bit machines. Normally, a
  1517.  machine using 16-bit addresses can access only 64K of memory. The 8086
  1518.  family of processors uses a special addressing scheme to overcome this
  1519.  limitation.
  1520.  
  1521.  To extend the amount of memory that can be addressed by a program, physical
  1522.  memory on the 8086 is divided into segments, each up to 64K long. The
  1523.  starting point of each segment in memory is represented by a 16-bit address.
  1524.  
  1525.  
  1526.  2.2.2.1  Near Addresses
  1527.  
  1528.  The 8086 reserves four registers to hold segment base addresses: CS (code
  1529.  segment), DS (data segment), SS (stack segment), and ES (extra segment). A
  1530.  segment address, however, points only to the "base" (beginning) of the
  1531.  segment. To refer to a particular item within a segment, you must also give
  1532.  the location of the item within the segment. This requires a 16-bit offset
  1533.  address, which gives the address of an item relative to the base of a
  1534.  particular segment. A 16-bit offset is called a "near" address.
  1535.  
  1536.  Wherever possible, it is preferable for the compiler to generate near
  1537.  addresses, to access code and data items. Near addresses are much more
  1538.  efficient than far addresses, because they require less space and take less
  1539.  time to calculate.
  1540.  
  1541.  Although a complete 8086/286/386 address is 32 bits long, the 8086/286/386
  1542.  uses reserved segment registers in a way that makes it possible to access
  1543.  some items with just near addresses. To see how this works, take the
  1544.  simplest case, where a program has one code segment and one data segment.
  1545.  The 8086 family has two machine registers that are dedicated to accessing
  1546.  the code and data segments: the CS and DS registers. When a program loads,
  1547.  the CS register is set to the address of the code segment, and the DS
  1548.  register is set to the address of the data segment. Since these registers
  1549.  are reserved for this purpose, the built-in 8086 instructions assume that
  1550.  the appropriate segment addresses can be found there. So the instructions
  1551.  require only the 16-bit offset of an item within a segment.
  1552.  
  1553.  
  1554.  2.2.2.2  Far Addresses
  1555.  
  1556.  Many programs, however, contain more than 64K of code or more than 64K of
  1557.  data. The addressing scheme becomes more complicated for larger programs.
  1558.  
  1559.  A complete address on the 8086/286/386, then, requires 32 bits: 16 bits for
  1560.  the segment address and 16 bits for the offset. A full 32-bit address is
  1561.  known as a "far" address.
  1562.  
  1563.  When program code exceeds 64K, it occupies more than one code segment. The
  1564.  Microsoft FORTRAN Compiler places the code from each "module" (compiled
  1565.  source file) in its own segment. Each module is therefore restricted to 64K
  1566.  or less, since it must fit in a segment. All calls to subroutines and
  1567.  functions require the compiler to use far addresses, since the address of
  1568.  the code must include both the segment (the location of the module) and the
  1569.  offset (the location of the subroutine or function within the module). This
  1570.  increases the size of the program and makes it less efficient, but allows it
  1571.  to grow beyond 64K.
  1572.  
  1573.  Similarly, programs with more than 64K of data occupy more than one data
  1574.  segment. The compiler divides data into different classes (for example,
  1575.  global uninitialized data, constants, and global initialized data) and
  1576.  assigns different classes to different segments.
  1577.  
  1578.  With multiple data segments, some data items are placed in the "default data
  1579.  segment," the data segment addressed by the DS register. (See Section
  1580.  2.2.3 for more information about this data segment.) The compiler only
  1581.  needs to generate a 16-bit offset address to access these items, since it
  1582.  uses the DS register to "point" to this segment. However, it must generate
  1583.  full 32-bit (far) addresses to access any data items outside the default
  1584.  data segment. This increases the size and makes programs less efficient,
  1585.  but it allows the program to access large amounts of data, a common
  1586.  requirement for FORTRAN programs.
  1587.  
  1588.  
  1589.  2.2.2.3  Huge Addresses
  1590.  
  1591.  One further complication can arise when a program has very large data items.
  1592.  A program may contain a single data item (array or common block) that
  1593.  exceeds 64K. Normally, the compiler calculates addresses of elements within
  1594.  a single data item using 16-bit (near) arithmetic. To do this, it assumes
  1595.  that all elements of the data item lie within the same segment, so the same
  1596.  base address can be used for the address of all elements. When a single data
  1597.  item exceeds 64K, this assumption no longer holds true.
  1598.  
  1599.  To access elements within a data item that exceeds 64K, the compiler must
  1600.  calculate addresses using 32-bit (far) arithmetic. In Microsoft FORTRAN, a
  1601.  single data item larger than 64K is known as a "huge" data item, and the
  1602.  address of the item is a "huge" address. A huge address, like a far address,
  1603.  is a full 32-bit address, but the huge address has the additional
  1604.  implication that 32-bit offsets are required to access all individual
  1605.  elements of the data item.
  1606.  
  1607.  Only data items can have huge addresses. The code for each module is
  1608.  restricted to 64K or less, so that it never exceeds one segment. Huge
  1609.  addresses are even less efficient than far addresses, but they resolve
  1610.  data-handling difficulties in programs that require very large data items.
  1611.  
  1612.  
  1613.  2.2.3  The Default Data Segment
  1614.  
  1615.  Even in programs with multiple data segments, the address of a single data
  1616.  segment can remain in DS throughout program execution. This segment is known
  1617.  as the "default data segment." Items in this segment can be addressed with
  1618.  near addresses.
  1619.  
  1620.  Local data items (but not formal arguments) smaller than the "data
  1621.  threshold" (that is, the maximum allowable size for a single piece of data)
  1622.  are placed in this segment, unless a FAR or HUGE attribute is used to move
  1623.  the item outside the segment. (The data threshold is set with the /Gt
  1624.  option, described briefly in Section 2.4.5.1.) In addition, the default
  1625.  data segment always contains certain internal data, regardless of the data
  1626.  threshold value.
  1627.  
  1628.  Every program has a default data segment. In a program with only one data
  1629.  segment, the default data segment is the only data segment. See Section
  1630.  2.3.2.1 for more information about the contents and use of the default
  1631.  data segment.
  1632.  
  1633.  
  1634.  2.3  Working with FORTRAN Memory Models
  1635.  
  1636.  This section introduces the characteristics of the FORTRAN memory models
  1637.  (medium, large, and huge) and discusses strategies for working within the
  1638.  size limits for code and data. (Section 2.4 below gives additional
  1639.  information on selecting a memory model and adjusting it to program-specific
  1640.  needs.)
  1641.  
  1642.  Briefly, the standard memory models have the following characteristics:
  1643.  
  1644.       Model                                      Characteristics
  1645.  
  1646.       Large (default)                Total program code and data can
  1647.                                      each exceed 64K. Each module is
  1648.                                      given its own code segment;
  1649.                                      therefore, each module is limited
  1650.                                      to 64K. The compiler creates
  1651.                                      multiple code and data segments
  1652.                                      as needed. However, formal array
  1653.                                      arguments are restricted to 64K,
  1654.                                      unless the argument is explicitly
  1655.                                      declared with the HUGE attribute.
  1656.  
  1657.       Medium                         Total program data are restricted
  1658.                                      to 64K. Total program code can
  1659.                                      exceed 64K. Each module is given
  1660.                                      its own code segment and
  1661.                                      therefore limited to 64K.
  1662.  
  1663.       Huge                           This model has the same
  1664.                                      characteristics as the large
  1665.                                      model, but all formal array
  1666.                                      arguments are assumed to exceed
  1667.                                      64K.
  1668.  
  1669.  Many of the code and data size limits apply to all three models. In fact,
  1670.  the only difference between the large and huge memory models is that the
  1671.  large model assumes arrays are smaller than 64K (both adjustable- and
  1672.  assumed-size arrays), while huge model assumes they are larger than 64K. The
  1673.  medium model differs from the large model only in its handling of common
  1674.  blocks, and use of near addresses rather than far addresses to pass
  1675.  subroutine arguments. See Section 2.3.2.4 for more information.
  1676.  
  1677.  Since the three memory models are similar in most respects, the following
  1678.  discussion of memory-model characteristics applies to all three models,
  1679.  except where noted.
  1680.  
  1681.  
  1682.  2.3.1  Specifying a Memory Model
  1683.  
  1684.  Specify a memory model for your programs by taking the following steps:
  1685.  
  1686.    1. When you run the SETUP program, you can either tell SETUP to build a
  1687.       library that supports the default (large) memory model or choose a
  1688.       different memory model. Based on your response, SETUP builds support
  1689.       for the preferred memory model into the run-time library it creates. If
  1690.       you want to use different memory models for different programs, create
  1691.       a separate library for each memory model.
  1692.  
  1693.    2. When you compile a program with the FL command, you can give a
  1694.       memory-model option on the command line. This option allows FL to link
  1695.       the program to a library that supports that memory model. If you do not
  1696.       specify a memory model, FL links to a large-model library by default.
  1697.  
  1698.       Note that if you use the OS/2 dual-mode names (described in Section
  1699.       3.1, "Compiling and Linking Under OS/2," in Chapter 3 of this manual),
  1700.       you may also need to specify the appropriate FL option /Lr, /Lp, or /Lc
  1701.       to select the correct library.
  1702.  
  1703.  The Microsoft FORTRAN Compiler defaults to the large memory model. The large
  1704.  model can accommodate programs that use more than 64K of total code and
  1705.  data. If the program uses multiple modules, each module can have up to 64K
  1706.  of code in a unique segment. For programs that require more than 64K of
  1707.  data, the compiler creates multiple data segments as needed by the program.
  1708.  See Sections 2.3.2.5 and 2.3.2.6 for specific restrictions of the large
  1709.  memory model.
  1710.  
  1711.  The large memory model can accommodate most of the programs compiled with
  1712.  the Microsoft FORTRAN Compiler. However, if a program does not fit in the
  1713.  large memory model, you must either shift to the huge memory model or use
  1714.  some of the techniques described in Chapter 7, "Optimizing Programs."
  1715.  Conversely, if a program runs under the large model, you may be able to
  1716.  improve its performance and decrease its size by changing to the medium
  1717.  memory model.
  1718.  
  1719.  Any large-model library (such as either LLIBFORE.LIB, LLIBFOR7.LIB, or
  1720.  LLIBFORA.LIB) works with the large or huge model. The medium model requires
  1721.  the library MLIBFORE.LIB, MLIBFOR7.LIB, or MLIBFORA.LIB.
  1722.  
  1723.  ───────────────────────────────────────────────────────────────────────────
  1724.  NOTE
  1725.     See Chapter 7,  for a description of other ways you can improve program
  1726.     efficiency by choosing libraries during installation, choosing compiler
  1727.     command-line options, and using I/O options within the program.
  1728.  ───────────────────────────────────────────────────────────────────────────
  1729.  
  1730.  
  1731.  2.3.2  Data-Handling Strategies and Limits
  1732.  
  1733.  The ways in which the three FORTRAN memory models allocate data result in
  1734.  different limits on data size. The sections below describe these
  1735.  data-allocation methods and the resulting limits. They also suggest
  1736.  strategies for working within these limits.
  1737.  
  1738.  See Table 2.1, "Data Allocation in Large Memory Models," in Section 2.3.2.6
  1739.  for a summary of data allocation.
  1740.  
  1741.  
  1742.  2.3.2.1  Limits on the Default Data Segment
  1743.  
  1744.  Keeping data in the default data segment increases a program's efficiency.
  1745.  Items in the default data segment are usually accessed with near (16-bit)
  1746.  addresses, since the program only requires an offset from the address in the
  1747.  DS register. In the large and huge models, however, 32-bit addresses are
  1748.  used to pass arguments to other routines, unless the formal arguments are
  1749.  declared with the NEAR attri-bute (see Section 2.4.2 for more information).
  1750.  
  1751.  The default data segment contains the following:
  1752.  
  1753.    ■  The program stack, which holds arguments passed to subprograms and
  1754.       local data declared in an AUTOMATIC statement. Normally the stack is
  1755.       2K, although you can change its size. In a multithread and/or
  1756.       dynamic-link library application running under OS/2, the program stack
  1757.       receives its own segment.
  1758.  
  1759.    ■  Floating-point and character constants, including constants generated
  1760.       by the compiler and I/O routines. These constants may differ in number
  1761.       or value from constants specified in the source program.
  1762.  
  1763.    ■  Data allocated or used by the run-time library, including run-time data
  1764.       and internal forms of formats for formatted I/O in medium-model
  1765.       programs.
  1766.  
  1767.    ■  Space for file I/O buffers for medium-model programs and space for
  1768.       dynamic allocation of file-control blocks (FCBs). Whenever an I/O
  1769.       package links with a program, FCBs are allocated for the terminal
  1770.       (console), for internal files, and for any additional files the program
  1771.       opens.
  1772.  
  1773.       For every FCB allocated, an associated I/O buffer is allocated as well;
  1774.       for medium-model programs, these buffers are allocated in the default
  1775.       data segment. In large-model programs, I/O buffers are allocated
  1776.       outside the default data segment. If you specify redirection on the FL
  1777.       command line, the compiler allocates an additional FCB and I/O buffer.
  1778.  
  1779.    ■  Arrays smaller than the data-threshold value in the large and huge
  1780.       models. The data threshold is a cutoff value set by the /Gt option
  1781.       which the compiler uses in allocating data. Any arrays larger than or
  1782.       the same size as the data threshold are stored in separate segments
  1783.       outside the default data segment and accessed with far addresses.
  1784.  
  1785.    ■  Subprogram entry and exit information, if the /4Yb option (or the
  1786.       $DEBUG metacommand) is in effect.
  1787.  
  1788.    ■  Allocatable arrays, if no far heap space is available.
  1789.  
  1790.  In the medium memory model, the default data segment also contains all
  1791.  common blocks not explicitly declared with the HUGE or FAR attribute.
  1792.  
  1793.  The total space required by the items listed above, including all local
  1794.  variables and arrays allocated in the default data segment, cannot exceed
  1795.  64K and still remain in the default data segment. If the program violates
  1796.  this restriction, you have the following options:
  1797.  
  1798.    ■  Move some data items out of the default data segment by using the FAR
  1799.       or HUGE attribute. See Section 2.4.2 for more information on these
  1800.       attributes.
  1801.  
  1802.    ■  Use the /Gt option, described in Section 2.4.5.1, to move all data
  1803.       items larger than a given size out of the default data segment. Note
  1804.       that this option does not work with medium-model programs.
  1805.  
  1806.    ■  Use the BLOCKSIZE option in OPEN statements in the source program to
  1807.       change the size of the I/O buffers allocated to the units you open. By
  1808.       default, each unit is allocated a 1,024-byte I/O buffer; however, the
  1809.       BLOCKSIZE option allows you to specify a different buffer size. Note
  1810.       that this solution is effective only in medium-model programs, since
  1811.       these buffers are not stored in the default data segment in large and
  1812.       huge models.
  1813.  
  1814.    ■  Remove the /4Yb option (or the $DEBUG metacommand) from all debugged
  1815.       programs.
  1816.  
  1817.  Any of the above strategies help reduce the amount of information stored in
  1818.  the default data segment. As your program approaches 64K, heeding one or
  1819.  more of these suggestions may keep the entire program within the default
  1820.  segment.
  1821.  
  1822.  
  1823.  2.3.2.2  Limits on Fixed-Size Arrays Exceeding 64K
  1824.  
  1825.  Fixed-size arrays larger than 64K are automatically allocated as many
  1826.  segments as necessary outside the default data segment. The compiler
  1827.  generates huge ad-dresses for these arrays since they cross segment
  1828.  boundaries. The only limit on the number of these huge arrays in the program
  1829.  is available memory.
  1830.  
  1831.  No individual scalar object, including an array element, can, however, span
  1832.  a segment boundary. If possible, the compiler offsets the start of an array
  1833.  in the segment so that this spanning does not occur. This cannot be done for
  1834.  character and structure arrays whose element size is not a power of two and
  1835.  whose length is greater than 128K. Common blocks cannot be adjusted either,
  1836.  since Microsoft FORTRAN does not require different program units to use the
  1837.  same declarations or ordering of variables. An error results if your array
  1838.  or common block declaration tries to allocate a scalar item across a segment
  1839.  boundary.
  1840.  
  1841.  ───────────────────────────────────────────────────────────────────────────
  1842.  NOTE
  1843.     Arrays smaller than 64K (65,536 bytes) but larger than 65,521 bytes
  1844.     should be considered larger than 64K and declared with the HUGE attribute
  1845.     (see Section 2.4.2 for more information). Even though such arrays do
  1846.     not exceed the 64K limit, they may be too large for a segment if the
  1847.     segment does not start on a paragraph boundary.
  1848.  ───────────────────────────────────────────────────────────────────────────
  1849.  
  1850.  
  1851.  2.3.2.3  Limits on Adjustable- and Assumed-Size Arrays
  1852.  
  1853.  Adjustable-size and assumed-size arrays can appear in a FORTRAN program as
  1854.  formal arguments to subprograms. The size of an adjustable- or assumed-size
  1855.  array is determined at execution time by the size of the array passed as the
  1856.  cor-responding actual argument to the subprogram. (See the DIMENSION
  1857.  statement entry in Chapter 4 of the Microsoft FORTRAN Reference for more
  1858.  information on these types of arrays.)
  1859.  
  1860.  Although the size of such an array is actually determined at execution time,
  1861.  the compiler must decide on an addressing convention at compile time to
  1862.  generate references to the array. To do so, the compiler assumes either that
  1863.  the array is 64K or smaller, in which case it can generate near or far
  1864.  addresses, depending on where the array is stored──or, that the array is
  1865.  larger than 64K, in which case huge addressing is required.
  1866.  
  1867.  In the large and medium models, the compiler assumes that adjustable- and
  1868.  assumed-size arrays are 64K or smaller, and therefore generates near or far
  1869.  addresses to access them. If the actual size of an adjustable-size or
  1870.  assumed-size array exceeds 64K at execution time, the program's results are
  1871.  unpredictable.
  1872.  
  1873.  To arrange the program so that it will correctly handle adjustable-size and
  1874.  assumed-size arrays larger than 64K, you have the following choices:
  1875.  
  1876.    ■  You can specify the HUGE attribute when you declare a particular array
  1877.       as a formal argument. This attribute tells the compiler that the actual
  1878.       argument may be (but is not required to be) larger than 64K, causing
  1879.       the compiler to generate a huge address for that particular array.
  1880.  
  1881.    ■  You can use the huge memory model (described in Section 2.4.1.2). In
  1882.       the huge model, the compiler assumes that all adjustable-size and
  1883.       assumed-size arrays are larger than 64K and generates huge addresses to
  1884.       access them. To improve program efficiency in the huge model, you can
  1885.       use either the NEAR or FAR attribute with any adjustable-size or
  1886.       assumed-size array whose actual size will always be smaller than 64K.
  1887.  
  1888.  Note that both of the methods mentioned above work in all cases, whether or
  1889.  not the actual size of the adjustable-size or assumed-size array is larger
  1890.  than 64K.
  1891.  
  1892.  Fixed-size formal array arguments are treated as if they were assumed-size,
  1893.  except that a fixed-size formal array argument larger than 64K is implicitly
  1894.  treated as huge. All of the preceding comments about assumed-size arrays
  1895.  apply to fixed-size arrays, too. (This treatment of arrays promotes
  1896.  compatibility with earlier versions of FORTRAN that did not support assumed-
  1897.  or adjustable-size arrays, but did support their functionality by ignoring
  1898.  the last dimension of an array.)
  1899.  
  1900.  
  1901.  2.3.2.4  Limits on Common Blocks
  1902.  
  1903.  In the large and huge memory models, each common block in the program is
  1904.  allocated as many segments as it needs outside the default data segment. If
  1905.  the common block is larger than 64K, the compiler generates huge addresses.
  1906.  If the common block is 64K or smaller, the compiler generates far addresses.
  1907.  
  1908.  Some restrictions apply to the variables of a common block larger than 64K.
  1909.  No individual array element or variable in a common block can span a segment
  1910.  boundary. The compiler allocates common blocks so that they always start at
  1911.  the beginning of a segment. This restriction means that the boundary between
  1912.  bytes 65,536 and 65,537 of the common block must fall between two variables
  1913.  or between two elements of an array.
  1914.  
  1915.  If an array in a common block spans a segment boundary and is passed as an
  1916.  actual argument, the corresponding formal argument must be declared with the
  1917.  HUGE attribute.
  1918.  
  1919.  If you have small, frequently accessed common blocks in your program, you
  1920.  may benefit from declaring such blocks with the NEAR attribute. This
  1921.  attribute causes the compiler to place the common block in the default data
  1922.  segment, where it can be accessed with more efficient near addresses.
  1923.  However, this is an option only if you have room in the default data
  1924.  segment. (See Section 2.3.2.1, "Limits on the Default Data Segment," for
  1925.  more information.)
  1926.  
  1927.  As an alternative, if you have room in the default data segment, you may be
  1928.  able to use the medium memory model. The medium memory model places all
  1929.  common blocks in the default data segment except the following:
  1930.  
  1931.    ■  Blank common blocks explicitly declared with the FAR attribute
  1932.    ■  Named common blocks larger than 64K
  1933.  
  1934.  
  1935.  2.3.2.5  Limits on Arguments Passed to Subprograms
  1936.  
  1937.  Normally, FORTRAN arguments are passed by reference. When a subroutine is
  1938.  called, the compiler places the addresses of the arguments on the program
  1939.  stack. Such a method of passing arguments places some restrictions on the
  1940.  different memory models:
  1941.  
  1942.    ■  In the large and huge models, the compiler uses far (32-bit) addresses
  1943.       in order to pass arguments to subprograms, even if the arguments are in
  1944.       the default data segment.
  1945.  
  1946.    ■  In the medium memory model, the compiler uses near addresses to pass
  1947.       arguments to subprograms, with the assumption that all program data
  1948.       resides in the default data segment.
  1949.  
  1950.  The following strategies can help you bypass these stack restrictions:
  1951.  
  1952.    ■  In large and huge models, if a formal argument is declared with the
  1953.       NEAR attribute in the INTERFACE statement, the compiler uses a near
  1954.       (16-bit) address to pass the actual argument to the subprogram. Since
  1955.       near addresses are more efficient than far addresses, this will improve
  1956.       program efficiency. However, any actual arguments passed to NEAR formal
  1957.       arguments must reside in the default data segment, or unpredictable
  1958.       behavior may result.
  1959.  
  1960.    ■  In the medium memory model, if you want to pass an argument that is
  1961.       outside the default data segment (for example, an array declared with
  1962.       the FAR attribute, or any fixed-size array larger than 64K), you must
  1963.       declare the corresponding formal argument with the FAR or HUGE
  1964.       attribute.
  1965.  
  1966.    ■  In Microsoft FORTRAN, you can also pass arguments by value. When you
  1967.       use the VALUE attribute with an argument, you specify that the argument
  1968.       is to be passed by value instead of by reference. Instead of placing
  1969.       the address of the argument on the stack, the compiler places a copy of
  1970.       the argument's value on the stack.
  1971.  
  1972.    ■  The stack is normally part of the default data segment. The default
  1973.       stack size is 2K; you can change the size by using the /F option with
  1974.       FL, the /STACK option with LINK, or the EXEMOD utility. When passing
  1975.       arguments by value to a subprogram, be sure the total size required by
  1976.       the arguments does not exceed available stack space. Passing entire
  1977.       arrays by value can cause problems. Since arrays can exceed the stack
  1978.       size all by themselves, passing an array by value can cause a stack
  1979.       overflow with unpredictable results.
  1980.  
  1981.  
  1982.  2.3.2.6  Summary of Data Allocation
  1983.  
  1984.  Table 2.1 summarizes data allocation in the large memory model. Differences
  1985.  between the large, huge, and medium models appear in footnotes to the table.
  1986.  
  1987.  Table 2.1  Data Allocation in Large Memory Models
  1988.  
  1989.  Type of Data            Storage                    Address Type      Restrict
  1990.  
  1991.  Local variables         Default data segment       Near             Combined
  1992.  and fixed-size                                                       all such
  1993.  arrays smaller than                                                  variable
  1994.  the data threshold                                                  arrays,
  1995.                                                                       stack an
  1996.                                                                       data sto
  1997.                                                                       default
  1998.                                                                       segment,
  1999.                                                                       exceed 6
  2000.  
  2001.  Arrays smaller than     Separate segments          Far               Availabl
  2002.  64K but larger than     outside default data
  2003.  the data threshhold     segment
  2004.  
  2005.  Arrays larger than      As many segments as        Huge              Availabl
  2006.  64K                     needed outside default
  2007.                          data segment
  2008.  
  2009.  Common blocks          As many segments as        Far if  the       Availabl
  2010.                          needed outside default     common block
  2011.                          data segment               is 64K or
  2012.                                                     smaller; huge
  2013.                                                     otherwise
  2014.  
  2015.  
  2016.  Also, for the large memory model the compiler assumes that all formal array
  2017.  arguments are 64K or smaller, unless specifically declared with the HUGE
  2018.  attribute. This is also true of the medium model. In the huge model, the
  2019.  compiler assumes that the adjustable-size and assumed-size arrays are larger
  2020.  than 64K, unless specifically declared with the NEAR or FAR attribute.
  2021.  
  2022.  
  2023.  2.3.3  Limits on Code Size
  2024.  
  2025.  The Microsoft FORTRAN Compiler places the code from each module in its own
  2026.  segment. Since the maximum size of a segment is 64K, the compiled code in
  2027.  each module cannot exceed 64K. You can determine how much code each program
  2028.  module contains by looking at a source-file or map-file listing.
  2029.  
  2030.  The following sections describe some strategies you can use to minimize the
  2031.  size of your program code and make it more efficient. (See Chapter 7,
  2032.  "Optimizing Programs," for descriptions of other strategies.)
  2033.  
  2034.  
  2035.  2.3.3.1  Creating Programs Larger than 64K
  2036.  
  2037.  If a module exceeds the 64K code-size limit, you must reduce its size by
  2038.  breaking it into two or more source files. An effective way is to break the
  2039.  source program into sections based on functionality and compile them
  2040.  separately. Working with the sections separately does not affect the final
  2041.  program size (although it may increase the total size of the object files),
  2042.  but it does alter the number of memory segments used. Keeping each piece
  2043.  focused on a particular aspect of the program also makes the source code
  2044.  easier to understand and maintain.
  2045.  
  2046.  Conversely, you can combine the code from two or more modules into one
  2047.  segment by using the /NT option (described in Section 2.4.5.2). Modules with
  2048.  identical text-segment names are loaded into the same segment, provided
  2049.  their combined length does not exceed the 64K segment limit.
  2050.  
  2051.  
  2052.  2.3.3.2  Improving Efficiency with the NEAR Attribute
  2053.  
  2054.  FORTRAN uses far (32-bit) addresses to reference progam code because the
  2055.  reference must provide both the segment address and the offset of the code
  2056.  item within the segment. If the program uses some subprograms very heavily,
  2057.  you may increase program efficiency by using the NEAR attribute.
  2058.  
  2059.  When applied to a subprogram, the NEAR attribute specifies that the
  2060.  subprogram code resides in the same segment as the calling routine. Since
  2061.  the segment ad-dress remains constant, the compiler can generate a near
  2062.  (16-bit) address to call the subprogram.
  2063.  
  2064.  To use the NEAR attribute on a subprogram, you must make sure that the
  2065.  subprogram actually appears in the correct segment. You can do this by
  2066.  placing the subprogram in the same source file as the calling routine, thus
  2067.  ensuring that they compile into a single module.
  2068.  
  2069.  If you want to keep the routines in separate source files, you can use the
  2070.  /NT option to set the text-segment names for both modules. If you give both
  2071.  modules the same text-segment name, they will be loaded into the same
  2072.  segment.
  2073.  
  2074.  See Section 2.4.2 of this manual and Chapter 1 of the Microsoft FORTRAN
  2075.  Reference for more information on the NEAR attribute.
  2076.  
  2077.  
  2078.  2.4  Selecting and Adjusting the Memory Model
  2079.  
  2080.  This section describes the methods you can use to select and adjust memory
  2081.  models. You can choose one of the three standard FORTRAN memory models by
  2082.  giving one of the /A options on the FL command line; these options are
  2083.  described in Section 2.4.1 below.
  2084.  
  2085.  When you use the standard memory models, the FL command handles library
  2086.  support for you. FL automatically links with a library corresponding to the
  2087.  memory model you specify on the command line, provided that you had already
  2088.  created this library at the time you ran the SETUP program. Unless you
  2089.  specify otherwise, FL uses a large-model library for linking; this is also
  2090.  the default for the library created by the SETUP program if you do not
  2091.  choose a memory model during installation. The large and huge models use the
  2092.  same library; the medium model has its own library.
  2093.  
  2094.  The advantage of using standard models for your program is simplicity. For
  2095.  the standard models, memory management is specified by compiler options and
  2096.  does not require the use of extended keywords. This is an important
  2097.  consideration if you expect to transfer your program to other systems,
  2098.  particularly systems that do not use segmented architecture. Note that
  2099.  the threshold option (/Gt), the text-segment-naming option (/NT), and the
  2100.  data-segment-naming option (/ND) are also portable ways to control
  2101.  allocation.
  2102.  
  2103.  The disadvantage of using standard memory models exclusively is that they
  2104.  may not produce the most efficient code. For example, if you have an
  2105.  otherwise large-model program with one assumed-size array that may exceed
  2106.  64K, it is to your advantage to declare the single large array with the HUGE
  2107.  attribute. Switching to the huge model forces the compiler to consider all
  2108.  assumed- and adjustable-size arrays to be huge.
  2109.  
  2110.  Sections 2.4.1-2.4.3 describe ways to adjust allocation for one or more
  2111.  items without changing the entire memory model. The methods described in
  2112.  these sections give you greater control over the program's structure and
  2113.  performance. However, to understand the effects of using the options and
  2114.  attributes described in these sections and to use them safely, you need a
  2115.  thorough understanding of FORTRAN memory models and the 8086 architecture.
  2116.  
  2117.  
  2118.  2.4.1  Using Standard Memory Models
  2119.  
  2120.  The /AL, /AH, or /AM option selects a memory model. You can use only one
  2121.  memory-model option on the FL command line. The option applies to all source
  2122.  files on the command line and has no effect on object files given on the
  2123.  command line.
  2124.  
  2125.       Options                Model Selected
  2126.  
  2127.       /AL                    Large model (default; corresponds
  2128.                              to the default library generated
  2129.                              by SETUP)
  2130.  
  2131.       /AH                    Huge model
  2132.  
  2133.       /AM                    Medium model
  2134.  
  2135.  If you compile separate source files of a program at different times, you
  2136.  must specify the same memory model for all of them.
  2137.  
  2138.  The following discussion assumes the standard DOS library naming
  2139.  conventions. If you use the OS/2 dual-mode command-line options /Lp, /Lr, or
  2140.  /Lc, then the naming conventions appropriate to OS/2 dual-modes apply. (See
  2141.  Section 3.4, "Understanding Multitasking, Threads, and Dynamic-Link
  2142.  Libraries," for more information on OS/2 library names.)
  2143.  
  2144.  
  2145.  2.4.1.1  Large Model (/AL)
  2146.  
  2147.  The /AL option tells the compiler to use the large memory model. The large
  2148.  memory model is the default, so you do not have to give this option
  2149.  explicitly. The large-model option allows the compiler to create multiple
  2150.  segments as needed for both code and data.
  2151.  
  2152.  The default for large-model programs is that both code and data items are
  2153.  accessed with far addresses. You override the default with the NEAR or HUGE
  2154.  attribute for data and the NEAR attribute for code.
  2155.  
  2156.  The /AL option causes the name of the large-model, standard FORTRAN
  2157.  library──LLIBFORE.LIB, LLIBFOR7.LIB, or LLIBFORA.LIB, depending on the /FP
  2158.  option you specified on the FL command line──to be placed in each object
  2159.  file created. This allows the linker to use the required library
  2160.  automatically, provided that the library exists (that is, you built it using
  2161.  SETUP).
  2162.  
  2163.  
  2164.  2.4.1.2  Huge Model (/AH)
  2165.  
  2166.  The /AH option tells the compiler to use the huge memory model.
  2167.  
  2168.  The huge model differs from the large model only in the treatment of
  2169.  adjustable- and assumed-size arrays. With the huge model, the compiler
  2170.  assumes that such arrays are larger than 64K and generates huge addresses to
  2171.  access them; in the large models, the compiler assumes that such arrays are
  2172.  smaller than 64K unless they are explicitly declared with the HUGE
  2173.  attribute.
  2174.  
  2175.  These huge addresses make huge models less efficient than large models.
  2176.  How-ever, the huge model is useful when you want most or all adjustable-size
  2177.  and assumed-size arrays in the program to handle arrays larger than 64K
  2178.  correctly.
  2179.  
  2180.  When using the huge model, you can use the NEAR or FAR attribute with any
  2181.  formal array argument whose actual size is always smaller than 64K. This
  2182.  attribute tells the compiler to generate near or far addresses for the
  2183.  array; these addresses are more efficient than huge addresses. (See Section
  2184.  2.4.2 of this manual and Chapter 1 of the Microsoft FORTRAN Reference for
  2185.  more information about the FAR and NEAR attributes, respectively.)
  2186.  
  2187.  As an alternative to using the huge model, you can use the large model,
  2188.  specifying the HUGE attribute for any adjustable-size or assumed-size array
  2189.  whose actual size may exceed 64K. (See Section 2.4.2 of this manual and
  2190.  Chapter 1 of the Microsoft FORTRAN Reference for more information on the
  2191.  HUGE attribute.)
  2192.  
  2193.  The same libraries are used for huge model as for large model, so the /AH
  2194.  option places the name of the appropriate large-model FORTRAN library (that
  2195.  is, LLIBFORE.LIB, LLIBFOR7.LIB, or LLIBFORA.LIB) in each object file.
  2196.  
  2197.  
  2198.  2.4.1.3  Medium Model (/AM)
  2199.  
  2200.  The /AM option tells the compiler to use the medium memory model.
  2201.  
  2202.  The medium model differs from the large model in two respects: common blocks
  2203.  are allocated differently, and arguments to subprograms are passed
  2204.  differently.
  2205.  
  2206.  In medium models, blank common blocks not explicitly declared with the FAR
  2207.  or HUGE attribute──and named common blocks that are 64K or smaller──are
  2208.  placed in the default data segment. This allocation method allows the
  2209.  compiler to generate near addresses to access these common blocks. As a
  2210.  result, medium-model programs are usually more efficient in terms of speed
  2211.  and space than large- and huge-model programs. Common blocks larger than 64K
  2212.  are placed outside the default data segment and must be accessed with huge
  2213.  addresses.
  2214.  
  2215.  The argument-passing convention used by the medium model is also smaller and
  2216.  faster than in the large and huge models. In the medium model, the compiler
  2217.  passes actual arguments to subprograms using near addresses (instead of the
  2218.  far addresses used in large and huge models). This is possible because the
  2219.  compiler assumes that all data reside in the default data segment. If you
  2220.  want to pass data from outside the default data segment to a subprogram in
  2221.  the medium model, you must declare the corresponding formal argument in the
  2222.  subprogram with the FAR or HUGE attribute.
  2223.  
  2224.  Even if you cannot use the medium model for the program, you can force the
  2225.  compiler to use more efficient near addresses for passing arguments by
  2226.  declaring formal arguments with the NEAR attribute. You must be sure,
  2227.  however, that the actual arguments to be passed to the near formal arguments
  2228.  are located in the default data segment.
  2229.  
  2230.  ───────────────────────────────────────────────────────────────────────────
  2231.  NOTE
  2232.     Input and output (I/O) on far and huge items are not allowed in the
  2233.     medium model. How-ever, you can copy these items to a temporary location
  2234.     in the default data segment to perform I/O on them.
  2235.  ───────────────────────────────────────────────────────────────────────────
  2236.  
  2237.  The size of the default data segment cannot exceed 64K, and contains the
  2238.  stack and variables, in addition to common blocks. This restricts the
  2239.  practical size of the common blocks to less than 64K in order to remain
  2240.  within the segment boundaries. (See Section 2.3.2.1 for a description of
  2241.  the contents of the default data segment.)
  2242.  
  2243.  In practice, few FORTRAN programs can meet this restriction. You may still
  2244.  be able to use the medium model, however, by specifying the FAR and HUGE
  2245.  attributes in the program. For example, if the program contains large,
  2246.  infrequently accessed common blocks, you can use the FAR or HUGE attribute
  2247.  to move these blocks out of the default data segment. Smaller common blocks
  2248.  that are accessed more frequently can remain in the default data segment.
  2249.  
  2250.  You can also use the FAR and HUGE attributes to move other large data items,
  2251.  such as arrays, out of the default data segment. This creates more room in
  2252.  the segment for common blocks.
  2253.  
  2254.  As an alternative to using the medium memory model, you can use the NEAR
  2255.  attribute with specific common blocks to cause them to be placed in the
  2256.  default data segment. This improves program efficiency when you have one or
  2257.  more small, heavily used common blocks.
  2258.  
  2259.  See Section 2.4.2 of this manual and Chapter 1 of the Microsoft FORTRAN
  2260.  Reference for more information about the FAR, HUGE, and NEAR attributes.
  2261.  
  2262.  The name of the appropriate medium-model library──MLIBFORE.LIB,
  2263.  MLIBFOR7.LIB, or MLIBFORA.LIB, depending on the /FP option you specified on
  2264.  the FL command line──is placed in each object file created, provided the
  2265.  library exists (that is, you built it using SETUP).
  2266.  
  2267.  
  2268.  2.4.2  The NEAR, FAR, and HUGE Attributes
  2269.  
  2270.  The NEAR, FAR, and HUGE attributes are keywords used in a FORTRAN program to
  2271.  override default-addressing conventions. Section 1.6 of the Microsoft
  2272.  FORTRAN  Reference describes the syntax of these attributes and outlines
  2273.  restrictions on their use. This section describes the effects of these
  2274.  attributes on code and data items in the three FORTRAN memory models.
  2275.  
  2276.  The NEAR, FAR, and HUGE attributes give you more flexibility than selecting
  2277.  one of the standard memory models. For example, you may be able to avoid
  2278.  switching from the large to the huge memory model if you use the HUGE
  2279.  attribute on any adjustable- or assumed-size arrays that may exceed 64K. On
  2280.  the other hand, even if the program requires the huge model, you can improve
  2281.  program efficiency by identifying small, frequently accessed items that
  2282.  could benefit from being placed in the default data segment.
  2283.  
  2284.  The FAR attribute is also useful for programs that have more data than can
  2285.  fit in the default data segment. You can declare less frequently accessed
  2286.  items with the FAR attribute in order to move them out of the default data
  2287.  segment, which leaves room for the more heavily used items. You can also use
  2288.  the /Gt option, described in Section 2.4.5.1, to move some data items out
  2289.  of the default data segment.
  2290.  
  2291.  Keep in mind, however, that the NEAR, FAR, and HUGE attributes are
  2292.  extensions to the FORTRAN language. They are meaningful only on processors,
  2293.  such as the 8086, which have a segmented architecture. If portable code is a
  2294.  high priority, do not use these attributes. The standard memory-model
  2295.  options, along with the /Gt option, allow you to alter the memory model in a
  2296.  portable way; since these options are given at compile time, they do not
  2297.  affect the source code.
  2298.  
  2299.  The discussion of each memory model in the preceding sections suggests
  2300.  strategies for using the NEAR, FAR, and HUGE attributes with each model.
  2301.  Tables 2.2 and 2.3 summarize the effects of each attribute on items in each
  2302.  of the three standard memory models.
  2303.  
  2304.  Table 2.2  Effects of the NEAR Attribute
  2305.  
  2306.                          Large                      Huge
  2307.  Item                    Memory Model               Memory Model
  2308.  
  2309.  Variables and           No effect for items        Same as large model
  2310.  fixed-size arrays       smaller than data
  2311.                          threshold value.
  2312.                          Arrays larger than
  2313.                          threshold value but
  2314.                          smaller than 64K are
  2315.                          placed in default data
  2316.                          segment.
  2317.  
  2318.  Formal arguments        Actual arguments are       Same as large model
  2319.                          passed with near
  2320.                          addresses and must be
  2321.                          in default data
  2322.                          segment.
  2323.  
  2324.  Common blocks           Placed in default data     Same as large model
  2325.                          segment; near
  2326.                          addresses
  2327.  
  2328.  Subprograms             Near calls                 Near calls
  2329.  
  2330.  Assumed-size and        Actual arguments are       Same as large model
  2331.  adjustable-size         passed with near
  2332.  arrays                  addresses and must be
  2333.                          in default data
  2334.                          segment.
  2335.  ───────────────────────────────────────────────────────────────────────────
  2336.  
  2337.  
  2338.  Table 2.3  Effects of the FAR and HUGE Attributes
  2339.  
  2340.                          Large                      Huge
  2341.  Item                    Memory Model               Memory Model
  2342.  
  2343.  Variables and           If variable or array       Same as large model
  2344.  fixed-size arrays       is smaller than 64K,
  2345.                          it is moved out of the
  2346.                          default data segment
  2347.                          and accessed with far
  2348.                          addresses. If array is
  2349.                          larger than 64K, the
  2350.                          FAR or HUGE attribute
  2351.                          has no effect and huge
  2352.                          addresses are
  2353.                          generated.
  2354.  
  2355.  Formal arguments        FAR has no effect. If      If FAR is used, far
  2356.                          HUGE is applied to an      addresses are gen-
  2357.                          array, huge addresses      erated instead of huge
  2358.                          are generated.             addresses. HUGE has
  2359.                                                     no effect.
  2360.  
  2361.  Common blocks           No effect                  No effect
  2362.  
  2363.  
  2364.  
  2365.  
  2366.  
  2367.  
  2368.  
  2369.  
  2370.  
  2371.  
  2372.  Subprograms            No effect                  No effect
  2373.  
  2374.  Assumed-size,           FAR has no effect.         If FAR is used, far
  2375.  allocatable, and        Huge addresses are         addresses are gen-
  2376.  adjustable-size         generated with HUGE        erated instead of huge
  2377.  arrays                  attribute.                 addresses. HUGE has
  2378.                                                     no effect.
  2379.  ───────────────────────────────────────────────────────────────────────────
  2380.  
  2381.  
  2382.  2.4.3  The $LARGE and $NOTLARGE Metacommands
  2383.  
  2384.  The $LARGE and $NOTLARGE metacommands are related to the NEAR, FAR, and HUGE
  2385.  attributes, although their meanings are slightly different. Use of the
  2386.  $LARGE and $NOTLARGE metacommands is no longer recommended; the attributes
  2387.  are preferred.
  2388.  
  2389.  ───────────────────────────────────────────────────────────────────────────
  2390.  NOTE
  2391.     The term "large" can be confusing since it is used both for the $LARGE
  2392.     metacommand and for the large memory model. The $LARGE metacommand is not
  2393.     related to the large memory model; instead, the size defined by the
  2394.     $LARGE metacommand corresponds to the huge memory model (for formal
  2395.     arguments to subprograms) or the HUGE attribute (for fixed-size arrays).
  2396.     The $LARGE and $NOTLARGE metacommands are retained for compatibility with
  2397.     previous versions of FORTRAN.
  2398.  ───────────────────────────────────────────────────────────────────────────
  2399.  
  2400.  Fixed-size arrays declared under the $LARGE metacommand are treated the same
  2401.  as arrays declared with the HUGE attribute: arrays are placed outside the
  2402.  default data segment and must be accessed with far addresses for arrays 64K
  2403.  or smaller or with huge addresses for arrays larger than 64K. In the huge
  2404.  memory model, fixed-size arrays can be accessed with near addresses if they
  2405.  are smaller than a segment and smaller than the specified threshold value.
  2406.  In the medium and large memory models, declaring an array with the $NOTLARGE
  2407.  metacommand (either explicitly or by default) has no effect on the array's
  2408.  allocation. This is also true for fixed-size arrays in the huge model.
  2409.  
  2410.  
  2411.  2.4.4  Using Library Routines with Different Memory Models
  2412.  
  2413.  The standard libraries built by SETUP are designed to correspond to the
  2414.  three memory models. The libraries impose these restrictions on FORTRAN
  2415.  programs:
  2416.  
  2417.    ■  Arrays containing format specifiers cannot be declared with a HUGE
  2418.       attribute, specified in a $LARGE metacommand, or span more than one
  2419.       segment, in any memory model.
  2420.  
  2421.    ■  Huge arrays cannot be used as internal files in any memory model.
  2422.  
  2423.    ■  In medium-model programs, all items involved in I/O operations must be
  2424.       near, including items in I/O lists, format specifications, and internal
  2425.       files.
  2426.  
  2427.    ■  In medium-model programs, far format specifiers are illegal.
  2428.  
  2429.  
  2430.  2.4.5  Compiler Options Affecting Memory Usage
  2431.  
  2432.  Some FL command-line options──/Gt, /NT, and /ND──tell the compiler to change
  2433.  the manner in which it allocates memory. These are discussed briefly below.
  2434.  (Chapter 7 of the Microsoft FORTRAN Reference, "The FL Command,"describes
  2435.  these compiler options in detail.)
  2436.  
  2437.  
  2438.  2.4.5.1  Data Threshold Option (/Gt)
  2439.  
  2440.  The /Gt option sets the data threshold. The "data threshold" is a cutoff
  2441.  value the compiler uses in allocating data. In the large and huge models,
  2442.  each array or variable larger than or the same size as the assigned
  2443.  threshold value──but smaller than 64K──is stored in a new data segment
  2444.  outside the default data segment and accessed with a far address.
  2445.  
  2446.  Decreasing the threshold value is useful when you want to move data out of
  2447.  the default data segment without declaring them with the FAR attribute.
  2448.  Increasing the threshold value allows you to store arrays larger than 32,767
  2449.  bytes (the default value) in the default data segment, provided you have
  2450.  room for them. You can also accomplish this by declaring such arrays with
  2451.  the NEAR attribute.
  2452.  
  2453.  
  2454.  2.4.5.2  Naming Segments Option (/NT)
  2455.  
  2456.  The /NT option lets you override the default-naming conventions used by the
  2457.  FORTRAN compiler and supply your own name for text segments.
  2458.  
  2459.  "Text" is simply another term for "code"; therefore, a text segment is a
  2460.  code segment. Segments with the same name are loaded into the same physical
  2461.  segment in memory. For example, you can use the /NT option to give two
  2462.  different modules the same text-segment name, thus ensuring that they will
  2463.  be loaded into the same segment in memory. This is useful when you want to
  2464.  use the NEAR attribute with a subprogram.
  2465.  
  2466.  In all three of the FORTRAN memory models, the compiler places the code from
  2467.  each module in a separate segment with a distinct name, which is formed by
  2468.  using the module base name along with the suffix "_TEXT." See Section
  2469.  2.3.3, "Limits on Code Size," for more information on code size
  2470.  restrictions.
  2471.  
  2472.  
  2473.  2.4.5.3  Naming Data Option (/ND)
  2474.  
  2475.  The /ND option lets you override the default-naming conventions used by the
  2476.  Microsoft FORTRAN Compiler and supply your own name for data segments. The
  2477.  default data segment is named "_DATA." The compiler places data stored
  2478.  outside the default data segment in private segments with unique names.
  2479.  These items are: huge arrays; arrays larger than the threshold value; items
  2480.  declared with the FAR or HUGE attribute; and common blocks in large and huge
  2481.  models. (See Section 2.2.1, "Code and Data Segments," for more information
  2482.  on the names.)
  2483.  
  2484.  The /ND option places data from the module in a uniquely named data segment.
  2485.  When execution transfers to that module, the compiler loads the DS register
  2486.  with the base address of the named data segment; when execution leaves the
  2487.  module, the compiler restores DS to its previous value (usually DGROUP). As
  2488.  a result, during execution in that module, the compiler can use near
  2489.  addresses for calls to data residing in the named segment. This technique
  2490.  particularly improves the performance of routines that repeatedly access
  2491.  data.
  2492.  
  2493.  
  2494.  Chapter 3  FORTRAN Programming under OS/2
  2495.  ───────────────────────────────────────────────────────────────────────────
  2496.  
  2497.  This chapter presents an overview of the steps required to compile and link
  2498.  FORTRAN programs within the OS/2 environment and discusses some important
  2499.  programming strategies for use with OS/2. The chapter assumes you are
  2500.  already familiar with OS/2 programming. Microsoft FORTRAN now supports
  2501.  multithread and dynamic-link-library programming under OS/2, as described in
  2502.  this chapter. The Microsoft CodeView and Utilities User's Guide, included
  2503.  with this release, contains a guide to using the Microsoft CodeView(R)
  2504.  debugger in a multithread or dynamic-link-library environment.
  2505.  
  2506.  Section 3.10, "Additional Information," refers you to other publications
  2507.  that can deepen your understanding of OS/2. These publications address
  2508.  concerns particular to multithread programming and provide more com-plete
  2509.  discussions of dynamic-link libraries.
  2510.  
  2511.  
  2512.  3.1  Compiling and Linking under OS/2
  2513.  
  2514.  If you have set up FORTRAN for programming only under OS/2, you do not need
  2515.  to use any additional options to compile and link with the FL command. Use
  2516.  FL just as you would under DOS. If you wish to alter your current library
  2517.  and directory arrangement, you can rerun the SETUP program and create any
  2518.  new arrangement you want.
  2519.  
  2520.  In discussions throughout this chapter, the run-time libraries are referred
  2521.  to with the general single-mode naming convention, xLIBFORy.LIB (where x
  2522.  equals L or M and refers to a large or medium memory model, and y equals 7,
  2523.  E, or A and refers to the math coprocessor, emulator, or alternate math
  2524.  library). However, when the discussion calls for dual-mode development (that
  2525.  is, when you want to build libraries for both OS/2 protected-mode and
  2526.  real-mode development), then a new naming convention is used. It will
  2527.  distinguish between versions of the libraries that use the same memory model
  2528.  and floating-point options, but operate under real mode or protected mode.
  2529.  Those libraries follow the naming convention xLIBFy«R|P».LIB, with R used
  2530.  for real mode and P indicating protected mode.
  2531.  
  2532.  When you set up FORTRAN to compile under both real and protected modes, you
  2533.  must use one of the library options when compiling and linking with FL.
  2534.  Specifying the /Lr option selects the real-mode libraries so your program
  2535.  runs under DOS or in the OS/2 compatibility box. The /Lp option selects the
  2536.  OS/2 protected mode versions of the libraries and creates a program that
  2537.  runs only under OS/2 in protected mode. For example, to compile BESSEL.FOR
  2538.  for OS/2 protected mode, you would use the following command:
  2539.  
  2540.       FL /Lp BESSEL.FOR
  2541.  
  2542.  ───────────────────────────────────────────────────────────────────────────
  2543.  NOTE
  2544.     You must use the OS/2 (protected-mode) version of the CodeView debugger,
  2545.     CVP.EXE, to debug protected-mode programs.
  2546.  ───────────────────────────────────────────────────────────────────────────
  2547.  
  2548.  
  2549.  3.2  Running under Both DOS and OS/2
  2550.  
  2551.  You can create programs that run under DOS or in real and protected modes
  2552.  under OS/2 by linking your program for protected mode and "binding" it.
  2553.  Binding resolves references to OS/2 dynamic-link libraries so the program
  2554.  runs in both modes and under either operating system.
  2555.  
  2556.  To bind a program, link it with the protected-mode library. Then, use the
  2557.  BIND utility. For example, the following commands compile, link, and bind
  2558.  the file BESSEL.FOR:
  2559.  
  2560.       FL /Lp BESSEL.FOR
  2561.       BIND BESSEL APILMR.OBJ C:\LIB\DOSCALLS.LIB C:\LIB\API.LIB
  2562.  
  2563.  You must include the full path to the DOSCALLS.LIB  and  API.LIB  files in
  2564.  the command line. Alternately, you can compile, link, and bind the program
  2565.  automatically by specifying the /Fb option with the FL command. For example,
  2566.  
  2567.       FL /Lp /Fb BESSEL.FOR
  2568.  
  2569.  will automatically invoke the BIND utility for you.
  2570.  
  2571.  The AMPILMR.OBJ file is always required if you are using the large memory
  2572.  model. It also is required in the medium model if you use the ALLOCATE
  2573.  statement or the near and far heap in mixed-language programs. Although it
  2574.  is not explicitly required in other situtations, it is recommended that you
  2575.  link with AMPILMR.OBJ.
  2576.  
  2577.  If you write your own routines that use OS/2 system functions and you want
  2578.  to bind the resulting program, you must use only a subset of the Application
  2579.  Program Interface (API) functions, known as "Family API functions." See the
  2580.  Microsoft OS/2 Programmer's Reference for a list of Family API functions.
  2581.  
  2582.  See the Microsoft CodeView and Utilities User's Guide for complete
  2583.  information about the BIND command.
  2584.  
  2585.  ───────────────────────────────────────────────────────────────────────────
  2586.  NOTE
  2587.     Bound programs cannot be debugged using the CodeView debugger. However,
  2588.     you can use the OS/2 version of CodeView, CVP.EXE, to debug a
  2589.     protected-mode version of the program.
  2590.  ───────────────────────────────────────────────────────────────────────────
  2591.  
  2592.  
  2593.  3.3  Interfacing FORTRAN with OS/2
  2594.  
  2595.  To facilitate access to OS/2 routines, this release of Microsoft FORTRAN
  2596.  provides include files that contain the FORTRAN interfaces and declarations
  2597.  of all the standard OS/2 system routines. The interface files (the file
  2598.  names ending with .FI) must be included as the first executable statement in
  2599.  a source file that references OS/2 routines. However, the declaration files
  2600.  (files ending with .FD) must appear at the beginning of each subprogram that
  2601.  calls OS/2 routines; they declare the structures and symbolic constants
  2602.  needed by the same OS/2 routines.
  2603.  
  2604.  To reduce compilation time and memory requirements, include only those
  2605.  particular parts of the file that you want. To do so, you need to set
  2606.  conditional-compilation flags when referencing the include files. See
  2607.  BSE.FI, BSE.FD, OS2.FI, OS2.FD, PM.FI, and PM.FD on the distribution disks
  2608.  for specific details. For information on the base OS/2 routines (BSE files),
  2609.  see the Microsoft Operating System/2 Programmer's Toolkit, Programmer's
  2610.  Reference. For information on the Presentation Manager routines (PM files),
  2611.  see the Microsoft Operating System/2 Programmer's Toolkit, Presentation
  2612.  Manager Reference, Volume 1.
  2613.  
  2614.  
  2615.  3.4  Understanding Multitasking, Threads, and Dynamic-Link Libraries
  2616.  
  2617.  Special library support for OS/2 programming is provided with Microsoft
  2618.  FORTRAN Version 5.0. This version provides libraries for creating types of
  2619.  programs not previously supported, including multiple-thread programs and
  2620.  dynamically linked libraries.
  2621.  
  2622.  Sections 3.4.1-3.4.2 briefly describe multitasking and dynamic-link
  2623.  libraries; they are aspects of programming that OS/2 supports but MS-DOS
  2624.  does not.
  2625.  
  2626.  
  2627.  3.4.1  Multitasking and Threads
  2628.  
  2629.  "Multitasking" occurs when multiple, mutually independent programs share the
  2630.  same central processing unit (CPU) simultaneously. This term does not imply,
  2631.  however, that more than one person is interacting with the processor.
  2632.  
  2633.  OS/2 performs the scheduling and allocation of real hardware resources to
  2634.  "threads," which are paths of execution belonging to one or more "processes"
  2635.  (pieces of program code).
  2636.  
  2637.  A thread can share the code and data segments of a process with other
  2638.  threads in the same process, but it has its own stack, unique register
  2639.  values, and current instruction address. The system grants processor time to
  2640.  each thread, so that all threads of a process execute simultaneously. A
  2641.  thread is also the smallest unit of execution that OS/2 can schedule.
  2642.  
  2643.  The OS/2 environment offers the following types of multitasking:
  2644.  
  2645.       Type of
  2646.       Multitasking                     Description
  2647.  
  2648.       Screen group                     One or more processes that share
  2649.                                        a logical screen and keyboard;
  2650.                                        highest-level multitasking
  2651.                                        element. A word processor and a
  2652.                                        data base operating
  2653.                                        simultaneously under OS/2 will
  2654.                                        normally run in two different
  2655.                                        screen groups.
  2656.  
  2657.       Process                          Part of an executing program that
  2658.                                        is the unit of ownership for
  2659.                                        resources such as memory, open
  2660.                                        files, semaphores (see Section
  2661.                                        3.6.1 below), and one or more
  2662.                                        threads.
  2663.  
  2664.       Thread                           Execution path within a process;
  2665.                                        smallest multitasking unit
  2666.                                        managed by OS/2.
  2667.  
  2668.  A sample program supplied with this release highlights the use of threads.
  2669.  The program, FMHELLO.FOR, is a multithread version of the classic "Hello
  2670.  world" program.
  2671.  
  2672.  A pictorial representation of screen groups, processes, and threads is shown
  2673.  in Figure 3.1.
  2674.  
  2675.  In the figure above, each screen group consists of two processes. Each
  2676.  process can be composed of several threads.
  2677.  
  2678.  In any process, Thread 1 is the main thread. All threads in a process act
  2679.  independently. Unless you take steps to make one visible to another, each
  2680.  thread executes completely independently of another thread. They do,
  2681.  however, share the same variables and resources.
  2682.  
  2683.  ───────────────────────────────────────────────────────────────────────────
  2684.  NOTE
  2685.     It is not recommended that you use mixed-language programming in
  2686.     conjunction with multithread programs or dynamic-link libraries.
  2687.  ───────────────────────────────────────────────────────────────────────────
  2688.  
  2689.  
  2690.  3.4.2  Dynamic-Link Libraries
  2691.  
  2692.  A "dynamic-link library" is a set of routines linked to a program either at
  2693.  load time or at run time, rather than at the time of compilation. OS/2
  2694.  supports dynamic-link libraries; MS-DOS does not. The easiest way to
  2695.  understand dynamic linking is to contrast it with the more familiar method
  2696.  of static linking.
  2697.  
  2698.  Static linking involves the following steps:
  2699.  
  2700.    1. Write and compile a program that uses a standard FORTRAN I/O statement,
  2701.       such as WRITE. This produces an object file that contains a reference
  2702.       to the external function in the standard FORTRAN library that supports
  2703.       this high-level statement.
  2704.  
  2705.    2. Link the object file with the library file containing the external
  2706.       function. This linking step combines the two files by including the
  2707.       code for the referenced function into the final executable file. In
  2708.       other words, the external reference is resolved at link time.
  2709.  
  2710.    3. Run the executable file produced in step 2. This executable file is
  2711.       totally self- contained because it contains the code for the external
  2712.       function.
  2713.  
  2714.  Static linking is useful, but it has some disadvantages. For example, the
  2715.  final exe-cutable code cannot be upgraded or changed without relinking with
  2716.  the main program's object files. When there is a new release of a commercial
  2717.  program, the entire executable file must be replaced with a new version.
  2718.  
  2719.  Another disadvantage of static linking is that common sets of code cannot be
  2720.  shared. Any and all executable files that use the WRITE statement must
  2721.  explicitly link with the necessary routine. Thus, the code needed to
  2722.  support WRITE may be duplicated in many different executable files on a disk
  2723.  or in memory.
  2724.  
  2725.  Executable files that take advantage of dynamic-link libraries are smaller
  2726.  than statically linked files because they do not contain the code for
  2727.  external functions. They can also be upgraded by supplying new versions of
  2728.  the dynamic-link libraries. No relinking of the executable file is required.
  2729.  
  2730.  A less obvious but very important advantage of using dynamic-link libraries
  2731.  is that executable files may share code. A common set of routines can be
  2732.  placed in a dynamic-link library and accessed by any number of executable
  2733.  files.
  2734.  
  2735.  ───────────────────────────────────────────────────────────────────────────
  2736.  NOTE
  2737.     The OS/2 operating system uses dynamic-link libraries extensively. All of
  2738.     the OS/2 system functions are presented as external procedures that a
  2739.     user program can call.
  2740.  ───────────────────────────────────────────────────────────────────────────
  2741.  
  2742.  Dynamic linking involves the following basic steps:
  2743.  
  2744.    1. Write and compile a program that references an external function, just
  2745.       as you would for static linking.
  2746.  
  2747.    2. Create a special .DEF (definitions) file that specifies which functions
  2748.       the main program will import from the dynamic-link library.
  2749.  
  2750.    3. Link the main program with the appropriate "imports library." An
  2751.       imports library is a file that contains a reference to the external
  2752.       function in the dynamic-link library. This file does not contain code
  2753.       from the external function.
  2754.  
  2755.    4. DOSCALLS.LIB is an example of an imports library; if you did not link
  2756.       with DOSCALLS.LIB, the .DEF file would have to specify each OS/2 API
  2757.       function used in your program.
  2758.  
  2759.       You must describe the functions your program imports from dynamic-link
  2760.       libraries either in the .DEF file or in an imports library. The
  2761.       resulting file, after linking, does not contain any code from the
  2762.       external dynamic-link library.
  2763.  
  2764.    5. Create a dynamic-link library that contains the code referenced in the
  2765.       main program.
  2766.  
  2767.    6. Execute the program created in step 3. When this executable file is
  2768.       run, OS/2 loads the code and discovers the special reference to the
  2769.       dynamic-link library. For each external dynamic-link-library reference,
  2770.       OS/2 searches the dynamic-link-library directory and resolves the
  2771.       external reference at load time.
  2772.  
  2773.  
  2774.  3.5  Multithread Programs
  2775.  
  2776.  The simplest multithread program is an independent self-contained program
  2777.  created by the static linking method. The following sections describe the
  2778.  support needed by multithread processes and the special software routines
  2779.  used in han-dling them.
  2780.  
  2781.  
  2782.  3.5.1  Library Support for Multithread Programs
  2783.  
  2784.  This section discusses the multithread library LLIBFMT.LIB. See Section
  2785.  3.7.4, "Creating a Multithread Dynamic-Link Library," for a discussion of
  2786.  FDLLOBJS.LIB.
  2787.  
  2788.  LLIBFMT.LIB is a statically linked, multithread, large-model FORTRAN
  2789.  li-brary. Use this library to construct statically linked executable files
  2790.  that support multiple threads of execution. A multithread program created
  2791.  with this library is a large model program by default, but can be adjusted
  2792.  to use the huge model. Note that LLIBFMT.LIB does not support the medium
  2793.  memory model.
  2794.  
  2795.  LLIBFMT.LIB is used to create a program that is entirely self-contained and
  2796.  that does not share FORTRAN run-time code or data with any other programs or
  2797.  dynamic-link libraries. Note also that LLIBFMT.LIB uses the emulator math
  2798.  package.
  2799.  
  2800.  A multithread program that uses this library must be linked only with the
  2801.  files LLIBFMT.LIB and DOSCALLS.LIB. No other FORTRAN run-time libraries
  2802.  should be used in linking. When you build object files with LLIBFMT.LIB, use
  2803.  the /MT command-line option to ensure that the code links with the correct
  2804.  library. For a complete description of the /MT option, see Chapter 7 of the
  2805.  Microsoft FORTRAN Reference.
  2806.  
  2807.  
  2808.  3.5.2  Thread Control Routines
  2809.  
  2810.  The FORTRAN run-time library allows thread creation through the BEGINTHREAD
  2811.  function. Thread termination should be performed by calling the FORTRAN
  2812.  run-time thread-termination function ENDTHREAD. Threads terminate
  2813.  automatically when they complete execution.  The function THREADID is used
  2814.  in the multithread environment; it returns an INTEGER*2 representing the
  2815.  identification number used by OS/2 to manage that thread within a process.
  2816.  
  2817.  ───────────────────────────────────────────────────────────────────────────
  2818.  WARNING
  2819.     The OS/2 Application Program Interface (API) call DosCreateThread
  2820.     should not be used with FORTRAN. If the low-level API calls
  2821.     DosCreateThread and DosExit are used, the results are unpredictable.
  2822.  ───────────────────────────────────────────────────────────────────────────
  2823.  
  2824.  The next three sections provide the specifications for the FORTRAN run-time
  2825.  thread-management functions. In each of these sections, you will find:
  2826.  
  2827.    ■  A description of the routine, including any return values
  2828.  
  2829.    ■  An example showing the INTERFACE statement for the function and the
  2830.       order and type of any arguments
  2831.  
  2832.    ■  A discussion of any arguments
  2833.  
  2834.    ■  Notes or comments on the use of the routine
  2835.  
  2836.  
  2837.  3.5.2.1  The BEGINTHREAD Function
  2838.  
  2839.  The BEGINTHREAD function creates a new thread. Multithread programs must
  2840.  call BEGINTHREAD repeatedly, once for every thread created.
  2841.  
  2842.  If BEGINTHREAD successfully creates a new thread, it returns an
  2843.  identification number for the new thread. If BEGINTHREAD fails, a run-time
  2844.  error results. Such an error can occur if you specify an odd address stack;
  2845.  specify an odd or zero-length stack; attempt to create more threads than the
  2846.  run-time library can support (32); or experience a low-level system error.
  2847.  The example below shows the required interface to BEGINTHREAD and
  2848.  demonstrates how it can be used.
  2849.  
  2850.  Example
  2851.  
  2852.             INTERFACE TO INTEGER*2 FUNCTION
  2853.            + BEGINTHREAD(RTN,STK,SIZE,ARG)
  2854.             INTEGER*4 RTN [VALUE]       ! pass LOCFAR(thread_routine)
  2855.             INTEGER*1 STK(*)
  2856.             INTEGER*4 SIZE
  2857.             INTEGER*4 ARG
  2858.             END
  2859.  
  2860.       C  Example call to BEGINTHREAD
  2861.             EXTERNAL CHILD
  2862.             INTEGER*1 STACK(2048)
  2863.             INTEGER*2 TID
  2864.             TID = BEGINTHREAD (LOCFAR(CHILD), STACK(1), 2048, 0)
  2865.             .
  2866.             .
  2867.             .
  2868.             END
  2869.  
  2870.  The arguments used in the BEGINTHREAD function are discussed below:
  2871.  
  2872.       Argument                    Description
  2873.  
  2874.       RTN                         The far address of the routine
  2875.                                   you want the new thread to
  2876.                                   execute. For BEGINTHREAD to work
  2877.                                   properly, you must pass it the
  2878.                                   number returned by the LOC or
  2879.                                   LOCFAR function by value. The
  2880.                                   thread terminates automatically
  2881.                                   when it returns from the routine
  2882.                                   supplied by the RTN  argument.
  2883.                                   You also can terminate the thread
  2884.                                   by calling ENDTHREAD within the
  2885.                                   far routine.
  2886.  
  2887.       STK                         The memory address of an area to
  2888.                                   be used as the new thread's
  2889.                                   stack. The address must be on a
  2890.                                   word boundary (an even number)
  2891.                                   and must specify an area at least
  2892.                                   as long as the SIZE  argument.
  2893.                                   Usually the address refers to
  2894.                                   either a static array or an area
  2895.                                   created by the ALLOCATE
  2896.                                   statement.
  2897.  
  2898.       SIZE                        The size of the thread's stack,
  2899.                                   in bytes. The SIZE argument must
  2900.                                   be even, positive, and non-zero.
  2901.  
  2902.       ARG                         A parameter to pass to the newly
  2903.                                   created thread, passed by far
  2904.                                   reference. Typically, ARG  is the
  2905.                                   address of a data item, which may
  2906.                                   be a structure containing
  2907.                                   multiple data fields. If you do
  2908.                                   not need to pass an argument to
  2909.                                   the child thread, set ARG  equal
  2910.                                   to zero.
  2911.  
  2912.                                   Note that in the sample interface
  2913.                                   above, ARG  is declared as
  2914.                                   INTEGER*4. In general, you can
  2915.                                   modify the INTERFACE statement to
  2916.                                   reflect the type of the actual
  2917.                                   argument you pass. This
  2918.                                   modification avoids type mismatch
  2919.                                   warnings from the compiler.
  2920.  
  2921.                                   If you pass different types of
  2922.                                   arguments to more than one
  2923.                                   thread──which all use the same
  2924.                                   interface──the compiler will warn
  2925.                                   you with a recoverable error
  2926.                                   message.
  2927.  
  2928.                                   See Appendix D in the Microsoft
  2929.                                   FORTRAN Reference for more
  2930.                                   information on these types of
  2931.                                   errors. You can either ignore the
  2932.                                   messages or move each BEGINTHREAD
  2933.                                   call to a separate module with a
  2934.                                   custom interface.
  2935.  
  2936.  When a thread is created, the system calls the function supplied by the
  2937.  argument RTN. The new thread can access all files and resources owned by the
  2938.  parent process.
  2939.  
  2940.  If you write multiple-thread programs that make FORTRAN run-time calls from
  2941.  child threads, take care to allocate adequate stack space. To be safe,
  2942.  allocate at least 2K bytes for each thread's stack. In general, you should
  2943.  have 2K of stack space free when calling any API routine.
  2944.  
  2945.  
  2946.  3.5.2.2  The ENDTHREAD Subroutine
  2947.  
  2948.  The subroutine ENDTHREAD terminates a thread created by the BEGINTHREAD
  2949.  function. ENDTHREAD does not require any arguments. The example below shows
  2950.  the interface and a typical call to ENDTHREAD.
  2951.  
  2952.  
  2953.  Example
  2954.  
  2955.             INTERFACE TO SUBROUTINE ENDTHREAD()
  2956.             END
  2957.  
  2958.             C  SAMPLE USAGE OF ENDTHREAD
  2959.                    IF (i.EQ.0)
  2960.                      CALL ENDTHREAD()
  2961.             .
  2962.             .
  2963.             .
  2964.  
  2965.  Threads terminate automatically when they finish executing. However, the
  2966.  subroutine ENDTHREAD lets a thread conditionally terminate itself before it
  2967.  com-pletes its normal execution path.
  2968.  
  2969.  
  2970.  3.5.2.3  The THREADID Function
  2971.  
  2972.  The function THREADID returns to a thread its own unique identification
  2973.  number within a process. THREADID does not take any arguments. The example
  2974.  below shows the required interface to THREADID and demonstrates how it can
  2975.  be used.
  2976.  
  2977.  Example
  2978.  
  2979.             INTERFACE TO INTEGER*2 FUNCTION THREADID()
  2980.             END
  2981.             .
  2982.             .
  2983.             .
  2984.             RESULT(THREADID())=.TRUE.
  2985.             RETURN
  2986.             END
  2987.  
  2988.  Use THREADID when a thread needs to know its own identification number. For
  2989.  example, it could serve as an index to a global array that manages thread
  2990.  status.
  2991.  
  2992.  
  2993.  3.6  A Multithread FORTRAN Program
  2994.  
  2995.  The sections below describe the steps to compile, link, and run a
  2996.  multithread version of the classic "Hello world" program. The source code
  2997.  for this program is included on the distribution diskettes as FMHELLO.FOR.
  2998.  
  2999.  The FORTRAN multithread "Hello world" program FMHELLO brings up one thread
  3000.  for each command-line argument. Each thread will print "Hello world from
  3001.  thread n!" the number of times specified in the corresponding argument. The
  3002.  multithread library supports a maximum of 32 threads. For FMHELLO, since the
  3003.  main body is itself a thread, the maximum number of child threads is 31.
  3004.  
  3005.  
  3006.  3.6.1  Sample Program Operation
  3007.  
  3008.  To try the multithread implementation of "Hello world," type
  3009.  
  3010.       FMHELLO arg1 «arg2...»
  3011.  
  3012.  For example,
  3013.  
  3014.       FMHELLO 2 4 6
  3015.  
  3016.  brings up 3 threads; the first thread says "hello" two times, the second
  3017.  thread says "hello" four times, and the third thread says "hello" six times.
  3018.  
  3019.  In operation, FMHELLO follows these steps:
  3020.  
  3021.    1. Brings up the requested number of threads with BEGINTHREAD
  3022.    2. Waits until all threads have been brought up
  3023.    3. Begins multithread execution and waits for completion
  3024.  
  3025.  The synchronization in step 2 keeps the threads from all starting as the
  3026.  same thread (with the same thread ID number). Multiple threads with the same
  3027.  ID number can occur if the first spawned thread completes execution before
  3028.  the next request to create a thread is acted upon. The amount of time
  3029.  allotted to any individual thread is actually much larger than the execution
  3030.  time spent in each thread.
  3031.  
  3032.  An alternative method of thread synchronization is to use semaphores. A
  3033.  "semaphore" is a software flag used by OS/2 to precisely coordinate the
  3034.  activities of two or more threads. Microsoft FORTRAN does not directly
  3035.  support semaphores. If you wish, you can access semaphores through the OS/2
  3036.  API calls. See the OS/2 documentation (such as Microsoft Operating System /2
  3037.  Programmer's Reference) for a complete discussion of the required functions.
  3038.  
  3039.  In order to synchronize its threads, FMHELLO uses the DosSleep function,
  3040.  which causes a thread to periodically "wake up." During these wake-ups, the
  3041.  thread can check for a software flag. Polling a flag using DosSleep has some
  3042.  drawbacks, however, because
  3043.  
  3044.    ■  The thread wakes up unnecessarily and performs some processing only to
  3045.       find it has to go to sleep again.
  3046.  
  3047.    ■  The thread oversleeps (that is, the event it is waiting for has already
  3048.       occurred, but the thread sleeps until the sleep request expires).
  3049.  
  3050.  Often, your program will have to wait for a process to complete. If you do
  3051.  not know exactly how long that process will take, it is better to make the
  3052.  thread wait for a semaphore rather than use DosSleep.
  3053.  
  3054.  In the case of FMHELLO, however, the use of DosSleep is more appropriate
  3055.  because
  3056.  
  3057.    ■  DosSleep is easily understood and clearly functional.
  3058.  
  3059.    ■  The program is not particularly time dependent, so the above
  3060.       disadvantages will not adversely affect it. Also, we know that this is
  3061.       a one-time event and that the main code "quickly" wakes up the
  3062.       child-code portion of the program. That is, the DosSleep code path
  3063.       occurs once at child start-up time and is never entered again during
  3064.       child execution.
  3065.  
  3066.  Also, the sleep time is short and predetermined. The parent code sets the
  3067.  flag as soon as all of the threads have been started. In other words, there
  3068.  is no chance for the parent code to do other things and leave the thread
  3069.  waiting for DosSleep for long periods of time.
  3070.  
  3071.  
  3072.  3.6.2  Compiling and Linking the Sample Multithread Program
  3073.  
  3074.  The program FMHELLO.FOR is a statically linked multithread program. The
  3075.  steps in compiling and linking this program are as follows:
  3076.  
  3077.    1. Ensure that the files LLIBFMT.LIB and DOSCALLS.LIB are available.
  3078.  
  3079.       Either place them in the current working directory or in a directory
  3080.       specified in the LIB environment variable.
  3081.  
  3082.       The file LLIBFMT.LIB takes the place of the regular run-time-library
  3083.       file used in linking. See Section 3.5.1 for more information on
  3084.       LLIBFMT.LIB.
  3085.  
  3086.       The file DOSCALLS.LIB provides support for any OS/2 calls made in the
  3087.       multithread program. In this example, the OS/2 call DosSleep is used.
  3088.       In addition, the LLIBFMT.LIB file refers to DOSCALLS.LIB in the form of
  3089.       OS/2 calls.
  3090.  
  3091.    2. Compile and link the program with the following conditions set:
  3092.  
  3093.         ■  Large code address size
  3094.         ■  Far or huge data address size
  3095.         ■  Segment setup of SS not equal to DS; DS fixed
  3096.  
  3097.       The first two conditions are specified by either the large (the
  3098.       default) or huge memory models. The last condition is specified by
  3099.       using the /MT option with the FL command. (See Section 3.8.1 for a
  3100.       complete description of the /MT option.)  The complete FL invocation is
  3101.       shown below:
  3102.  
  3103.              FL /MT FMHELLO.FOR
  3104.  
  3105.       When compiling multithread programs, you can specify any of the
  3106.       floating-point options except /FPa (the alternate math package). To
  3107.       maximize efficiency, however, use the default floating-point option
  3108.       (/FPi87). The library LLIBFMT.LIB includes the emulator math package,
  3109.       but will use a math coprocessor if one is present. The other
  3110.       floating-point options (except /FPa) will also work, but cause their
  3111.       respective versions of the default library name to be placed in the
  3112.       object files. These differences are only a concern if you link as a
  3113.       separate step and use the /NOD: option to suppress default library
  3114.       searches.
  3115.  
  3116.    3. Link the resulting object file with LLIBFMT.LIB and DOSCALLS.LIB only.
  3117.       (The FL driver automatically takes care of this step.)
  3118.  
  3119.       Note that the default memory model (large) implies a far data address
  3120.       size. You can also specify huge data address with the /AH command-line
  3121.       option, but the linker will use the same library.
  3122.  
  3123.    4. Compile and link your programs separately, invoking the linker as
  3124.       follows to link the object file with LLIBFMT.LIB:
  3125.  
  3126.           link FMHELLO,,,/NOD:LLIBFOR7 LLIBFMT.LIB;
  3127.  
  3128.       LLIBFMT.LIB contains search directives for DOSCALLS.LIB, so you do not
  3129.       need to reference it explicitly. The /NOD: option turns off the default
  3130.       library search; you may need to specify a library other than LLIBFOR7
  3131.       if you specified a floating-point option other than the default.
  3132.  
  3133.    5. Run the program under OS/2.
  3134.  
  3135.  
  3136.  3.6.3  Troubleshooting Multithread Programs
  3137.  
  3138.  Several problems may occur when creating, linking, or executing a
  3139.  multithread FORTRAN program. Two of the more common ones are listed below:
  3140.  
  3141.       Problem                               Probable Cause
  3142.  
  3143.       LINK searches for LLIBFOR7.LIB or     If you link in a separate step
  3144.       LLIBFORE.LIB.                         and omit the /NOD option from the
  3145.                                             LINK command, the linker searches
  3146.                                             for the default library. The
  3147.                                             default library should not be
  3148.                                             used with multithread programs.
  3149.  
  3150.                                             The /NOD: option tells the linker
  3151.                                             to ignore the default library and
  3152.                                             use the specified library instead
  3153.                                             (see also Section 3.6.2). This
  3154.                                             problem may also be avoided by
  3155.                                             compiling with the /Zl option,
  3156.                                             which suppresses
  3157.                                             default-library-search records in
  3158.                                             the object files. However, you
  3159.                                             must then explicitly specify
  3160.                                             LLIBFMT.LIB on the link command
  3161.                                             line.
  3162.  
  3163.       Protection violation error            Many OS/2 programming errors will
  3164.       occurs.                               cause a protection violation. One
  3165.                                             cause of this error is failure to
  3166.                                             specify the condition "SS is not
  3167.                                             equal to DS" in the FL command
  3168.                                             invocation.
  3169.  
  3170.                                             Specify the correct conditions
  3171.                                             with the /MT option. Recompile
  3172.                                             the program with /MT. See the
  3173.                                             Microsoft FORTRAN Reference for
  3174.                                             specific FL command information.
  3175.                                             Another common cause of
  3176.                                             protection violations is
  3177.                                             over-addressing a common block or
  3178.                                             array without using the $DEBUG
  3179.                                             metacommand.
  3180.  
  3181.  
  3182.  3.7  Using FORTRAN Dynamic-Link Libraries
  3183.  
  3184.  Microsoft FORTRAN 5.0 includes support for dynamic link libraries. You can
  3185.  write routines in FORTRAN in such a way that they can be dynamically linked.
  3186.  In addition, this release provides an object-file library, FDLLOBJS.LIB,
  3187.  that can be used to create a dynamically linked multithread FORTRAN run-time
  3188.  library.
  3189.  
  3190.  Dynamic-link libraries can be debugged with the protected-mode CodeView
  3191.  debugger. (See Chapter 12 in the Microsoft CodeView and Utilities User's
  3192.  Guide.)
  3193.  
  3194.  
  3195.  3.7.1  Creating a Dynamic-Link Library
  3196.  
  3197.  FORTRAN 5.0 allows you to build your own dynamic-link libraries.To create
  3198.  such a library, take the following steps:
  3199.  
  3200.    1. Write a subroutine as you normally would (in a separate file).
  3201.  
  3202.    2. Use the LOADDS attribute on any subroutine name that will be used as an
  3203.       entry point to the dynamic-link library.
  3204.  
  3205.    3. Build a definitions (.DEF) file that exports the appropriate routine
  3206.       names. (That is,  build a file that uses the EXPORT module definition
  3207.       statement to name the routines you want to include in the library
  3208.       available to the calling program.)
  3209.  
  3210.    4. Compile and link the routine to build it as a dynamic-link library.
  3211.  
  3212.  The example in Section 3.7.4 steps through this process in detail. A
  3213.  dynamic-link routine written in this way will require a dynamically linked
  3214.  FORTRAN run-time library if the routine requires run-time support.
  3215.  
  3216.  
  3217.  3.7.2  The LOADDS Attribute
  3218.  
  3219.  You can use this attribute for routines that serve as entry points to your
  3220.  own dynamic-link libraries. The LOADDS attribute causes the data segment
  3221.  (DS) register to be loaded with the base address of the default data segment
  3222.  of the dynamic-link library upon entering the routine named with the
  3223.  attribute. The previous DS value is restored when the routine terminates.
  3224.  
  3225.  You do not need to specify the LOADDS attribute on local routines called
  3226.  from within the dynamic-link library. The correct DS register is set up
  3227.  during the call to the dynamic-link library provided the LOADDS attribute
  3228.  was specified on the entry routine. This attribute must appear with the
  3229.  names of routines that act as interfaces to a dynamic-link library.
  3230.  
  3231.  
  3232.  3.7.3  Multithread Dynamic-Link Libraries: An Overview
  3233.  
  3234.  The FDLLOBJS.LIB OS/2 support file is an object-file library used to create
  3235.  a dynamically linked FORTRAN run-time library. This library is provided as
  3236.  an object library with an associated definition file (FDLLOBJS.DEF) that
  3237.  defines the entry points into the FORTRAN run-time library. These entry
  3238.  points let you choose only those run-time modules that your program requires
  3239.  for a particular application. Three additional start-up object modules are
  3240.  also required to support dynamic linking in FORTRAN:
  3241.  
  3242.       Start-up Module                  Supported files
  3243.  
  3244.       FRTEXE.OBJ                       Start-up code for executable
  3245.                                        files
  3246.  
  3247.       FRTDLL.OBJ                       Start-up code for user-written
  3248.                                        dynamic-link libraries
  3249.  
  3250.       FRTLIB.OBJ                       Start-up code for dynamically
  3251.                                        linked FORTRAN run-time library
  3252.  
  3253.  A FORTRAN run-time library created with FDLLOBJS.LIB is dynamically linked
  3254.  and available to a multithread program and optionally to a group of closely
  3255.  associated dynamic-link libraries. User-written dynamic-link libraries that
  3256.  require run-time support must use an appropriately created, dynamically
  3257.  linked FORTRAN run-time library (see Section 3.7.6).
  3258.  
  3259.  The close association of the multithread program, the FORTRAN run-time
  3260.  library, and a group of dynamic-link libraries is shown in Figure 3.2.
  3261.  
  3262.  The main program (PROGRAM.EXE) and the two dynamic-link libraries (DLL1.DLL
  3263.  and DLL2.DLL) share the FORTRAN run-time data in the file FRTLIB.DLL. Each
  3264.  PROG.EXE, DLL1.DLL, and DLL2.DLL file has its own private data segments.
  3265.  
  3266.  The FORTRAN run-time dynamic-link library is closely tied to the program and
  3267.  the other dynamic-link libraries, because it contains global FORTRAN
  3268.  run-time data, thread-identification numbers, and FORTRAN run-time routines
  3269.  required by the program and other dynamic-link libraries.
  3270.  
  3271.  If you build a program using the dynamically linked multithread support of
  3272.  the FORTRAN run-time library, it can share the FORTRAN run-time library with
  3273.  one or more dynamic-link libraries that are closely related. FORTRAN
  3274.  run-time global data used to manage I/O are shared.
  3275.  
  3276.  Threads are managed in a dynamic-link library by the FORTRAN functions
  3277.  BEGINTHREAD and ENDTHREAD. See Section 3.5.2 for a description of these
  3278.  functions.
  3279.  
  3280.  
  3281.  3.7.4  Creating a Multithread Dynamic-Link Library
  3282.  
  3283.  The process of creating a multithread dynamic-link FORTRAN run-time library
  3284.  under OS/2 is outlined below. This example of how to create a dynamic-link
  3285.  library of the FORTRAN run-time routines is also contained in FDLLOBJS.CMD.
  3286.  
  3287.    1. Create a definitions file (.DEF) that specifies the functions in the
  3288.       FORTRAN run-time library you want the dynamic-link library to export
  3289.       (see Section 3.7.5, below). The file FDLLOBJS.DEF, included with this
  3290.       release, is a sample definitions file that includes all of the FORTRAN
  3291.       run-time functions currently supported.
  3292.  
  3293.    2. Link the special start-up file FRTLIB.OBJ with the files FDLLOBJS.LIB,
  3294.       DOSCALLS.LIB, and the definitions file from step 1. This linking
  3295.       creates a customized FORTRAN run-time dynamic-link library file. If you
  3296.       use the sample file FDLLOBJS.DEF, you'll create a library named
  3297.       FRTLIB.DLL. The following files are then linked together:
  3298.  
  3299.              File Name                   Description
  3300.  
  3301.             FRTLIB.OBJ            Start-up code for library files
  3302.  
  3303.             FDLLOBJS.LIB          FORTRAN run-time-library objects
  3304.  
  3305.             DOSCALLS.LIB          OS/2 support library
  3306.  
  3307.             FDLLOBJS.DEF          Definition module from step 1
  3308.  
  3309.             FRTLIB.DLL            Output from LINK
  3310.  
  3311.       To accomplish this, type the command
  3312.  
  3313.               LINK  FRTLIB.OBJ,FRTLIB.DLL,,FDLLOBJS.LI  B/NOE,
  3314.               FDLLOBJS.DEF
  3315.  
  3316.  
  3317.    3. Run the Microsoft Import Library Manager (IMPLIB) on the definitions
  3318.       file from step 1, and the support file DIFFHLP.DEF supplied with this
  3319.       release, to create a customized imports library file containing the
  3320.       exported functions. The form of the command is shown below:
  3321.  
  3322.               IMPLIB FRTLIB.LIB FDLLOBJS.DEF DIFFHLP.DEF
  3323.  
  3324.  ───────────────────────────────────────────────────────────────────────────
  3325.  NOTE
  3326.     The name FRTLIB.DLL is used only as an example. You should use a unique
  3327.     name particular to your application. If you do not, you run the risk of
  3328.     having a FORTRAN run-time library named FRTLIB.DLL built with any
  3329.     customized routines overwritten by another software vendor's dynamic-link
  3330.     library.
  3331.  ───────────────────────────────────────────────────────────────────────────
  3332.  
  3333.  
  3334.  3.7.5  Creating a Custom FORTRAN Run-Time Definitions File
  3335.  
  3336.  The general process described in Section 3.7.4, "Creating a Multithread
  3337.  Dynamic-Link Library," can be used to build a dynamic-link FORTRAN run-time
  3338.  library which includes only those routines required by a particular
  3339.  application (or set of applications). To do this, create a definitions
  3340.  (.DEF) file that specifies exactly those routines required by your program.
  3341.  You can build a custom definitions file through the following process:
  3342.  
  3343.    1. Print a copy of the sample definitions file, FDLLOBJS.DEF. It will act
  3344.       as a reference.
  3345.  
  3346.    2. Compile your program using the /MD option on the FL command line
  3347.       with-out specifying a library. As a result, the linker will list an
  3348.       "unresolved external" error for every routine referenced in the
  3349.       program. Note the names of each unresolved symbol.
  3350.  
  3351.    3. Create a new file as your custom definitions file. Place the names that
  3352.       appear in both the linker's unresolved symbols list and in the sample
  3353.       definitions file in your new file's EXPORT list. Use the copy of
  3354.       FDLLOBJS.DEF as a syntax guideline for your new file.
  3355.  
  3356.       You can now substitute your custom definitions file in place of the
  3357.       file FDLLOBJS.DEF in the instructions listed in steps 2 and 3 in
  3358.       Section 3.7.4. Be certain to uniquely name any dynamic-link FORTRAN
  3359.       run-time library created this way.
  3360.  
  3361.  
  3362.  3.7.6  Using a Multithread Dynamic-Link Library
  3363.  
  3364.  Once you create a FORTRAN run-time multithread dynamic-link library, it can
  3365.  be used by a program and the program's associated dynamic-link libraries.
  3366.  This release of FORTRAN includes a sample program that calls both a
  3367.  user-written dynamic-link library and a customized version of a dynamic-link
  3368.  FORTRAN run-time library (such as the one created in Section 3.7.4). The
  3369.  sample files FMTMAIN.FOR, FMTMAIN.DEF, FMTDLL.FOR, and FMTDLL.DEF on the
  3370.  distribution disks demonstrate dynamic linking.
  3371.  
  3372.  In order to use a run-time multithread dynamic-link library, follow the
  3373.  steps below as an example. The batch file MKFDLL.CMD included in this
  3374.  release also shows this process.
  3375.  
  3376.    1. Compile and link the main program FMTMAIN.FOR to produce the file
  3377.       FMTMAIN.EXE.
  3378.  
  3379.       Use the FL command
  3380.  
  3381.            FL /MD FMTMAIN.FOR FRTEXE.OBJ FRTLIB.LIB FMTMAIN.DEF
  3382.  
  3383.       See Section 3.8.1 for more information on the /MD option. The above
  3384.       FL command links the following files:
  3385.  
  3386.       File Name                   Description
  3387.  
  3388.             FMTMAIN.OBJ           Output from the compilation of
  3389.  
  3390.             FRTEXE.OBJ            Start-up code for executable
  3391.                                   files
  3392.  
  3393.             FRTLIB.LIB            Customized FORTRAN run-time
  3394.                                   imports library
  3395.  
  3396.             DOSCALLS.LIB          OS/2 support library
  3397.  
  3398.             FMTMAIN.DEF           Definitions (.DEF) file for
  3399.                                   FMTMAIN.FOR
  3400.  
  3401.             FMTMAIN.EXE           Output from LINK
  3402.  
  3403.       Given the object file FMTMAIN.OBJ compiled with the /MD option, you
  3404.       can also invoke the linker separately, with the following command:
  3405.  
  3406.            LINK FMTMAIN+FRTEXE,,,FRTLIB.LIB,FMTMAI N.DEF
  3407.  
  3408.       You must explicitly link the special start-up file FRTEXE.OBJ into any
  3409.       executable program that requires dynamically linked FORTRAN run-time
  3410.       support.
  3411.  
  3412.       An alternate method to the above process would be to build an imports
  3413.       library for FMTDLL.DLL and link FMTMAIN.OBJ with the imports library.
  3414.       This method avoids creating a definitions file which imports the
  3415.       functions.
  3416.  
  3417.    2. Compile and link a dynamic-link-library module (FMTDLL.FOR) to produce
  3418.       FMTDLL.DLL. Do this by entering the command
  3419.  
  3420.            FL /MD /FeFMTDLL.DLL FMTDLL.FOR FRTDLL.OBJ FRTLIB.LIB FMTDLL.DEF
  3421.  
  3422.       The following files are now linked together:
  3423.  
  3424.       File Name                   Description
  3425.  
  3426.             FMTDLL.OBJ            Output from the compilation of
  3427.                                   FMTDLL.FOR
  3428.  
  3429.             FRTDLL.OBJ            Start-up code for
  3430.                                   dynamic-link-library files
  3431.  
  3432.             FRTLIB.LIB            Customized FORTRAN run-time
  3433.                                   imports library
  3434.  
  3435.             DOSCALLS.LIB          OS/2 support library
  3436.  
  3437.             FMTDLL.DEF            Dynamic-link-library definitions
  3438.                                   file
  3439.  
  3440.             FMTDLL.DLL            Output from LINK
  3441.  
  3442.       The FL command compiles and links the dynamic-link library. The /Fe
  3443.       option allows you to rename the output from the linker to the .DLL
  3444.       extension.
  3445.  
  3446.       Given the object file, FMTDLL.OBJ, compiled with /MD, you can also
  3447.       invoke the linker separately with the following command:
  3448.  
  3449.            LINK FMTDLL+FRTDLL,FMTDLL.DLL,,FRTLIB.L IB,FMTDLL.DEF
  3450.  
  3451.       You must explicitly link the special start-up file FRTDLL.OBJ with any
  3452.       user-written dynamic-link library.
  3453.  
  3454.       FMTDLL.DLL performs I/O functions, requiring run-time support (provided
  3455.       by the example file FRTLIB.LIB). If the dynamic-link library does not
  3456.       require run-time support, omit this file from the command line.
  3457.  
  3458.    3. Place the FMTDLL.DLL file (from step 2) and the FRTLIB.DLL file in a
  3459.       directory on your LIB PATH so OS/2 can find it. You can now run the
  3460.       program FMTMAIN.EXE under OS/2.
  3461.  
  3462.  
  3463.  3.7.7  Compiling for Dynamic-Link and Multithread Capabilities
  3464.  
  3465.  The program FMHELLO discussed in Section 3.6 can also be compiled to use the
  3466.  dynamically linked multithread capabilities available with Microsoft FORTRAN
  3467.  5.0. Assuming that the example dynamic-link FORTRAN run-time library is on
  3468.  your LIB PATH, compile FMHELLO with the following command:
  3469.  
  3470.       FL /MD FMHELLO.FOR FRTEXE.OBJ FRTLIB.LIB
  3471.  
  3472.  The /MD option implies multithread support, so the /MT option is not
  3473.  required.
  3474.  
  3475.  
  3476.  3.7.8  FORTRAN OS/2 Libraries
  3477.  
  3478.  Table 3.1 shows the different FORTRAN libraries available under OS/2 and the
  3479.  forms of execution they support.
  3480.  
  3481.  Table 3.1  FORTRAN OS/2 Libraries
  3482.  ───────────────────────────────────────────────────────────────────────────
  3483.                 Executable        Executable          Dynamic-Link
  3484.                 Single-Thread     Multiple-Thread     Multiple-Thread
  3485.  Component      Library           Library             Run-Time Library
  3486.  
  3487.  .OBJ           ---               ---                 FRTDLL.OBJ
  3488.                                                       FRTEXE.OBJ
  3489.                                                       FRTLIB.OBJ
  3490.  
  3491.  .LIB           mLIBFfP.LIB       LLIBFMT.LIB         FDLLOBJS.LIB
  3492.                                   DOSCALLS.LIB        FDLLOBJS.DEF
  3493.                                                       DOSCALLS.LIB
  3494.  
  3495.  
  3496.  3.8  Limits on Multithread and Dynamic-Link Programs
  3497.  
  3498.  There are some restrictions on running multithread and dynamic-link
  3499.  programs. You must work within these limitations when you run a multithread
  3500.  and/or a dynamically linked program. Conventional DOS FORTRAN programs do
  3501.  not face these restrictions.
  3502.  
  3503.  
  3504.  3.8.1  Large and Huge Memory Models (/MT, /MD)
  3505.  
  3506.  You can use both the /MT and /MD options in conjunction with the normal
  3507.  memory model switches /AL and /AH. However, the /AM (medium model) option is
  3508.  strictly disallowed with the /MT and /MD options since the run-time names
  3509.  differ under the medium model. See Chapter 7 the Microsoft FORTRAN Reference
  3510.  for more information on these FL command-line switches.
  3511.  
  3512.  
  3513.  3.8.2  Math Support (/FPi87)
  3514.  
  3515.  The default-floating-point option, /FPi87, is still in effect for /MT and
  3516.  /MD compilation. Note, however, that any other form of /FP is allowed except
  3517.  /FPa (the alternate math option). The LLIBFMT.LIB and FDLLOBJS.LIB files
  3518.  contain the emulator math package. Although the emulator works when linked
  3519.  to object files compiled with any math option, it is recommended that the
  3520.  in-line forms (/FPi and /FPi87) be used for efficiency. A coprocessor will
  3521.  be used if it is available.
  3522.  
  3523.  
  3524.  3.8.3  Limited CHARACTER*(*) Support
  3525.  
  3526.  The FORTRAN Compiler uses a global symbol, _FCclenv, to tell a function the
  3527.  actual length of a character argument or function. If two threads update
  3528.  this variable simultaneously, unpredictable behavior may result. Do not use
  3529.  CHARACTER*(*) or restrict its use to a single thread in multithread
  3530.  programs.
  3531.  
  3532.  ───────────────────────────────────────────────────────────────────────────
  3533.  WARNING
  3534.     The GETARG() subroutine returns its buffer argument in the CHARACTER*(*)
  3535.     form. Therefore, any calls to GETARG() must be restricted to a single
  3536.     thread and use no other CHARACTER*(*) calls.
  3537.  ───────────────────────────────────────────────────────────────────────────
  3538.  
  3539.  
  3540.  3.8.4  The C Attribute and REAL Numbers
  3541.  
  3542.  Functions returning REAL values cannot use the C attribute. A global symbol,
  3543.  _fac, is used to return REAL values when you specify the C attribute for a
  3544.  function. If two threads access this variable simultaneously, the results
  3545.  cannot be predicted. Statically linked multithread programs will resolve
  3546.  this conflict. Therefore, you may not become aware of the problem. It may or
  3547.  may not influence your program. In a dynamically linked program the _fac
  3548.  symbol cannot be accessed outside of the FORTRAN run-time data segment, and
  3549.  therefore cannot be used. The simplest way to avoid this difficulty is to
  3550.  use the default calling convention with any function returning a REAL value.
  3551.  
  3552.  
  3553.  3.8.5  Open Files
  3554.  
  3555.  You can open up to 40 files simultaneously in programs that use the
  3556.  multithread and/or dynamic-link capabilities of FORTRAN. (Since the system
  3557.  reserves a few of these files for its own use and others manage devices, the
  3558.  actual number of files a process can open is slightly less than 40.)
  3559.  
  3560.  Using all available units prior to any terminal I/O may result in an OS/2
  3561.  lack of storage space error. You can prevent this by forcing I/O to the
  3562.  terminal before reaching the system limit.
  3563.  
  3564.  
  3565.  3.9  Recommendations
  3566.  
  3567.  The following points offer some general guidelines for creating multithread
  3568.  and dynamic-link programs. They are not requirements for creating such
  3569.  programs, but recommendations to help you around some common pitfalls.
  3570.  
  3571.    ■  Recompile all code in a multithread or dynamic-link program with the
  3572.       appropriate compile-time option (/MT or /MD), since it is necessary
  3573.       that the compiler assume that the segment addresses stored in the SS
  3574.       (which contains the stack address) and DS (which contains the near data
  3575.       address) registers are not equal. See the discussion of the /MD and /MT
  3576.       options in Chapter 7 of the  Microsoft FORTRAN Reference for more
  3577.       information.
  3578.  
  3579.    ■  Allow threads to conduct I/O only on those units which they explicitly
  3580.       open. Since threads within a process share the resources of that
  3581.       process, it is possi-ble for one thread to perform I/O to units opened
  3582.       by other threads in the same process. This allows the possibility of
  3583.       delaying one request in the event that both threads attempt to access
  3584.       the same file simultaneously.
  3585.  
  3586.    ■  For multithread and dynamic-link programs, note that if the program
  3587.       terminates prematurely due to a MATH-class error, then the system does
  3588.       not flush the final buffer of any output files, since the termination
  3589.       code may not execute properly.
  3590.  
  3591.    ■  Because threads within a single process share resources, take care when
  3592.       using the preconnected units (units 0, 5, and 6 all connect to the
  3593.       terminal) in multithread programs. If a thread reconnects one of these
  3594.       units to a file, then when the process dies or a thread later closes
  3595.       the unit, it reassumes its preconnected status to the terminal. Any
  3596.       other threads which may have been reading or writing to that unit may
  3597.       unexpectedly read and write to the terminal.
  3598.  
  3599.    ■  Do not use a STOP statement inside a routine which is executing as a
  3600.       thread in a multithread program. The STOP statement terminates the
  3601.       process (including flushing and closing all open files), not just the
  3602.       thread that encountered the statement. Instead, use the ENDTHREAD
  3603.       subroutine to cause a thread to terminate itself.
  3604.  
  3605.    ■  In a multithread program, a thread that causes a run-time error in a
  3606.       statement without an explicit error-recovery sequence will cause the
  3607.       entire process to terminate──with a run-time error.
  3608.  
  3609.    ■  Files opened within a thread should be explicitly closed with the CLOSE
  3610.       statement. Closing the files returns the resource to the process and
  3611.       makes the files available to other threads. Thread termination does not
  3612.       implicitly close files in the way that process termination does.
  3613.  
  3614.  
  3615.  3.10  Additional Information
  3616.  
  3617.  The following publications contain more information on OS/2 programming and
  3618.  philosophy:
  3619.  
  3620.  Cortesi, David E. The Programmer's Essential OS/2 Handbook. Redwood City,
  3621.  CA: M&T Publishing Co, 1988.
  3622.  
  3623.  Jamsa, Kris A. Using OS/2. Berkeley, CA: Osborne McGraw-Hill, 1988.
  3624.  
  3625.  Letwin, Gordon. Inside OS/2. Redmond, WA: Microsoft Press, 1987. (An
  3626.  explanation of OS/2 from Microsoft's Chief Architect, Systems Software.)
  3627.  
  3628.  Microsoft Systems Journal, May 1987. (Issue devoted to OS/2.)
  3629.  
  3630.  Petzold, Charles. PC Magazine column "Environments." (A series of articles
  3631.  on OS/2 programming topics begun with the October 13, 1987 issue.)
  3632.  
  3633.  Young, Michael J. Programmer's Guide to OS/2. San Francisco, CA: SYBEX,
  3634.  1988.
  3635.  
  3636.  
  3637.  Chapter 4  Mixed-Language Programming
  3638.  ───────────────────────────────────────────────────────────────────────────
  3639.  
  3640.  Microsoft FORTRAN supports calls to routines written in Microsoft C and
  3641.  Pascal. In addition, if the main program is in Microsoft QuickBASIC 4.0 or
  3642.  later (or Microsoft BASIC Compiler 6.0 or later), then a FORTRAN routine can
  3643.  call a BASIC routine.This chapter describes the elements of mixed-language
  3644.  programming: how languages differ and how to resolve these differences.
  3645.  
  3646.  If you understand the basic principles involved in making a mixed-language
  3647.  call, then you may wish to turn directly to the detailed syntax information
  3648.  in Sections 4.2-4.4. These sections outline procedures for calling routines
  3649.  written in other high-level languages and in assembly language from
  3650.  Microsoft FORTRAN.
  3651.  
  3652.  
  3653.  4.1  Making Mixed-Language Calls
  3654.  
  3655.  Mixed-language programming always involves a call to a function, procedure,
  3656.  or subroutine. For example, a FORTRAN main module may need to execute a
  3657.  specific task programmed in a different language. Instead of writing a new
  3658.  FORTRAN routine, you might decide to call a preexisting function written
  3659.  in──say──C.
  3660.  
  3661.  Mixed-language calls with Microsoft languages necessarily involve multiple
  3662.  modules. Instead of compiling all of your source modules with the same
  3663.  compiler, you use different compilers. In the instance mentioned above, you
  3664.  would compile the main-module source file with the FORTRAN compiler; compile
  3665.  a second source file (written in C) with the C compiler; and then link the
  3666.  two object files together.
  3667.  
  3668.  Figure 4.1 illustrates how the syntax of a mixed-language call works, using
  3669.  the example mentioned above.
  3670.  
  3671.  In the illustration above, the FORTRAN call to C is CALL Prn (), similar to
  3672.  a call to a FORTRAN subprogram. However, there are two differences between
  3673.  this mixed-language call and a call between two FORTRAN modules:
  3674.  
  3675.    ■  The subprogram Prn  is actually implemented in C, using standard C
  3676.       syntax.
  3677.  
  3678.    ■  FORTRAN must use the INTERFACE statement in order to create
  3679.       compatibility with C.
  3680.  
  3681.       The INTERFACE statement is an example of a mixed-language interface
  3682.       statement (it is FORTRAN's interface statement). Each language provides
  3683.       its own form of interface.
  3684.  
  3685.  Despite syntactic differences, C functions, Pascal procedures, BASIC
  3686.  procedures,  Microsoft Macro Assembler MASM routines, and FORTRAN
  3687.  subroutines and functions are all similar. The principal difference is that
  3688.  some kinds of routines return values and others do not. You can interchange
  3689.  routines that have a return value, and you can interchange routines that
  3690.  have no return value. Note that in this chapter, the term "routine" refers
  3691.  to any function, procedure, or subroutine that can be called from another
  3692.  module.
  3693.  
  3694.  Table 4.1 below shows the correspondence between routine calls in different
  3695.  languages.
  3696.  
  3697.  Table 4.1  Language Equivalents for Routine Calls
  3698.  
  3699.       Language            Return Value            No Return Value
  3700.  
  3701.       FORTRAN             Function                Subroutine
  3702.       C                   Function                (Void) function
  3703.       Pascal              Function                Procedure
  3704.       BASIC               FUNCTION procedure      Subprogram
  3705.       Macro Assembler     Procedure               Procedure
  3706.  
  3707.  For example, a BASIC module can make a subprogram call to a FORTRAN
  3708.  subroutine. BASIC needs to make a FUNCTION call in order to call a FORTRAN
  3709.  function; otherwise, the call can be made, but the return value will be
  3710.  lost. This adapts the calling program to the conventions of the called
  3711.  routine.
  3712.  
  3713.  Note that FORTRAN cannot call BASIC DEF FN functions or GOSUB subroutines,
  3714.  since they are not independent from other programs or procedures; that is,
  3715.  they are contained within the main module of a BASIC program.
  3716.  
  3717.  
  3718.  4.1.1  Naming Convention Requirement
  3719.  
  3720.  The term "naming convention" refers to the way a compiler alters the name of
  3721.  the routine before placing it into an object file.
  3722.  
  3723.  When you issue a mixed-language call, it is important that you adopt a
  3724.  consistent naming convention. If the name of the called routine is stored
  3725.  differently in each object file, then the linker will not be able to find a
  3726.  match. Instead, it will report an error.
  3727.  
  3728.  Object files contain not only machine code but also the names of all
  3729.  routines and variables that need to be accessed publicly. The linker must be
  3730.  able to compare the name of a routine called in one module to the name of a
  3731.  routine defined in another module and recognize a match. Names are stored in
  3732.  ASCII format. You can see precisely how they are stored if you use the DEBUG
  3733.  utility to dump an object file's bytes.
  3734.  
  3735.  FORTRAN, Pascal, and BASIC use roughly the same naming conventions. They
  3736.  translate each letter to uppercase. BASIC type declaration characters (%, &,
  3737.  !, #, $) are dropped.
  3738.  
  3739.  However, each language recognizes a different number of characters.
  3740.  Microsoft FORTRAN recognizes the first 31 characters of any name (or 6, if
  3741.  you use the $TRUNCATE metacommand); C the first 31; Pascal the first 8; and
  3742.  BASIC the first 40. If a name is longer than the number of characters the
  3743.  language will recognize, additional characters are dropped. For this reason,
  3744.  any time a FORTRAN program using the $TRUNCATE metacommand calls a routine
  3745.  from another language with a name longer than 6 characters, it must use the
  3746.  ALIAS statement. (See Section 4.2.3 for more information on ALIAS.)
  3747.  
  3748.  C uses a quite different convention. The C compiler does not translate any
  3749.  letters to uppercase, but inserts a leading underscore (_) in front of the
  3750.  name of each routine.
  3751.  
  3752.  Differences in naming conventions are taken care of automatically when you
  3753.  use mixed-language keywords, as long as you follow two rules:
  3754.  
  3755.    1. If you use the $TRUNCATE metacommand, keep all routine names called by
  3756.       FORTRAN to 6 characters or less in length.
  3757.  
  3758.    2. Do not use the /NOIGNORE linker option (which causes the linker to
  3759.       distinguish between Prn and prn). With C modules, this means that you
  3760.       will have to be careful not to rely upon differences between uppercase
  3761.       and lowercase letters.
  3762.  
  3763.       The CL driver and Microsoft QuickC use the /NOIGNORE option when
  3764.       linking. To solve the problems this creates, either link separately
  3765.       with the LINK utility or use all lowercase letters in your C modules.
  3766.  
  3767.  Figure 4.2 illustrates a complete mixed-language development example, which
  3768.  shows how naming conventions enter into the process.
  3769.  
  3770.  Note that the FORTRAN Compiler inserts a leading underscore in front of Prn
  3771.  as it places the name into the object file, because the C attribute directs
  3772.  the FORTRAN compiler to use the C naming convention. FORTRAN will also
  3773.  convert all letters to lowercase when this keyword is used. Note that
  3774.  converting letters to lowercase is not part of the C naming convention, but
  3775.  it is consistent with the programming style of most C programs.
  3776.  
  3777.  
  3778.  4.1.2  Calling Convention Requirement
  3779.  
  3780.  The term "calling convention" refers to the way a language implements a
  3781.  call. The choice of calling convention affects the actual machine
  3782.  instructions that a compiler generates in order to execute──and return
  3783.  from──a function, procedure, or subroutine call.
  3784.  
  3785.  The calling convention is a low-level protocol. It is crucial that the
  3786.  routine issuing a call and the routine being called recognize the same
  3787.  protocol. Otherwise, the processor may receive inconsistent instructions,
  3788.  causing the system to crash.
  3789.  
  3790.  The use of a calling convention affects programming in two ways:
  3791.  
  3792.    1. The calling routine uses a calling convention to determine the order in
  3793.       which to pass arguments (parameters) to another routine. Usually this
  3794.       convention can be specified in a mixed-language interface.
  3795.  
  3796.    2. The called routine uses a calling convention to determine the order in
  3797.       which to receive the parameters that were passed to it. In most
  3798.       languages, including FORTRAN, the routine's heading specifies this
  3799.       convention. BASIC, however, always uses its own convention to receive
  3800.       parameters.
  3801.  
  3802.  In other words, each call to a routine uses a certain calling convention,
  3803.  and each routine heading specifies or assumes some calling convention. The
  3804.  two conventions must be compatible. With each language except BASIC, it is
  3805.  possible to change either calling convention. However, it is usually
  3806.  simplest to adopt the convention of the called routine. For example, a
  3807.  FORTRAN function would use its own convention to call another FORTRAN
  3808.  function and use the C convention to call C.
  3809.  
  3810.  FORTRAN, Pascal, and BASIC use the same standard calling convention. C,
  3811.  however, uses a quite different convention. The Microsoft BASIC, FORTRAN,
  3812.  and Pascal calling conventions each push parameters onto the stack in the
  3813.  order in which they appear in the source code. For example, the FORTRAN
  3814.  statement CALL Calc(A,B) pushes the argument A onto the stack before it
  3815.  pushes B. These conventions specify that the stack is restored by the called
  3816.  routine, before returning control to the caller. The stack is restored by
  3817.  removing parameters.
  3818.  
  3819.  The C calling convention pushes parameters onto the stack in the reverse
  3820.  order in which they appear in the source code. For example, the C function
  3821.  call calc(a,b); pushes b onto the stack before it pushes a. In contrast
  3822.  with other high-level languages, the C calling convention specifies that a
  3823.  calling routine always restores the stack immediately after the called
  3824.  routine returns control.
  3825.  
  3826.  The FORTRAN, Pascal, and BASIC conventions produce slightly less object
  3827.  code. However, the C convention makes calling with a variable number of
  3828.  parameters possible. Because the first parameter is always the last one
  3829.  pushed, it is always on the top of the stack; therefore it has the same
  3830.  address relative to the frame pointer, regardless of how many parameters
  3831.  were actually passed. You don't need to be aware of all variations in
  3832.  calling conventions in order to do mixed-language programming successfully,
  3833.  but you do need to remember that such differences exist.
  3834.  
  3835.  
  3836.  4.1.3  Methods for Passing Parameters
  3837.  
  3838.  Section 4.1.2 discusses the overall protocol (the calling convention) that
  3839.  two routines use to communicate with each other; this section discusses how
  3840.  an individual item of data (a parameter) is actually exchanged.
  3841.  
  3842.  If your routines do not agree on how a parameter is to be sent, then a
  3843.  called routine will receive bad data. It is also possible that the program
  3844.  could cause a system error.
  3845.  
  3846.  Microsoft compilers support three methods for passing a parameter:
  3847.  
  3848.       Method                      Description
  3849.  
  3850.       By near reference           Passes a variable's near (offset)
  3851.                                   address.
  3852.  
  3853.                                   This method gives the called
  3854.                                   routine direct access to the
  3855.                                   variable itself. Any change the
  3856.                                   routine makes to the parameter
  3857.                                   will be reflected in the calling
  3858.                                   routine.
  3859.  
  3860.       By far reference            Passes a variable's far
  3861.                                   (segmented) address.
  3862.  
  3863.                                   This method is similar to passing
  3864.                                   by near reference, except that a
  3865.                                   longer address is passed. This
  3866.                                   method is slower than passing by
  3867.                                   near reference, but it is
  3868.                                   necessary when you pass data that
  3869.                                   is outside the default data
  3870.                                   segment. This is not an issue in
  3871.                                   BASIC or Pascal, unless you have
  3872.                                   specifically requested far
  3873.                                   memory.
  3874.  
  3875.       By value                    Passes only the variable's value,
  3876.                                   not address.
  3877.  
  3878.                                   With this method, the called
  3879.                                   routine knows the value of the
  3880.                                   parameter, but has no access to
  3881.                                   the original variable. Changes to
  3882.                                   a value parameter have no effect
  3883.                                   on the value of the parameter in
  3884.                                   the calling routine, once the
  3885.                                   routine terminates.
  3886.  
  3887.  The fact that there are different parameter-passing methods has two
  3888.  implications for mixed-language programming:
  3889.  
  3890.    ■  You need to make sure that the called routine and the calling routine
  3891.       use the same method for passing each parameter (argument). In most
  3892.       cases, you will need to check the parameter-passing defaults used by
  3893.       each language and possibly make adjustments. Each language has keywords
  3894.       or language features that allow you to change parameter-passing
  3895.       methods.
  3896.  
  3897.    ■  You may want to use a particular parameter-passing method rather than
  3898.       using the defaults of any language because of characteristics of your
  3899.       programming task.
  3900.  
  3901.  Table 4.2 summarizes the parameter-passing defaults for each language. Each
  3902.  language has methods for overriding these defaults.
  3903.  
  3904.  Table 4.2  Parameter-Passing Defaults
  3905.  
  3906.                By Near         By Far
  3907.  Language      Reference       Reference         By Value
  3908.  
  3909.  FORTRAN       All            All             ---
  3910.  C             Near arrays     Far arrays        Nonarrays
  3911.  Pascal        VAR, CONST      VARS, CONSTS      Other parameters
  3912.  BASIC         All BASIC       All               ---
  3913.  
  3914.  
  3915.  4.1.4  Compiling and Linking Considerations
  3916.  
  3917.  After you write your source files and resolve the issues of naming
  3918.  conventions and parameter-passing procedures raised in Sections
  3919.  4.1.1-4.1.3, you are ready to compile individual modules and then link
  3920.  them together. To do this successfully, the different modules need to use
  3921.  compatible memory models──that is, they must agree on where information is
  3922.  stored. These modules also need to know which libraries to reference in
  3923.  order to avoid unresolved external calls or duplicate routine definitions.
  3924.  
  3925.  
  3926.  4.1.4.1  Using Compatible Memory Models
  3927.  
  3928.  With Microsoft FORTRAN, Pascal, and BASIC, no special options are required
  3929.  to compile source files that are part of a mixed-language program.
  3930.  
  3931.  With Microsoft C, however, you need to be aware that not all memory models
  3932.  will be compatible with other languages. FORTRAN, Pascal, and BASIC use only
  3933.  far (segmented) code addresses. Always compile C modules in medium,  large,
  3934.  or huge models because these models also use far code addresses. Compiling
  3935.  in small or compact models causes the mixed-language program to crash as
  3936.  soon as a call is made to or from C. This problem can be averted if you
  3937.  apply the FAR keyword to a C function definition, in order to specify that
  3938.  the function uses a far call and return.
  3939.  
  3940.  Differences in the size of data addresses can be resolved through compile
  3941.  options or in the source code. Your choice of memory model affects the
  3942.  default data pointer size in FORTRAN and C, although this default can be
  3943.  overridden with the NEAR and FAR attributes in FORTRAN, or the near and far
  3944.  keywords in C. The FORTRAN and C memory models also affect whether data
  3945.  objects are located in the default data segment; if a data object is not
  3946.  located in the default data segment, it cannot be directly passed by near
  3947.  reference. For more information on memory models, see Section 2.3.2 in
  3948.  Chapter 2, "Selecting a Memory Model."
  3949.  
  3950.  
  3951.  4.1.4.2  Specifying Libraries
  3952.  
  3953.  In many cases, linking modules compiled with different languages can be done
  3954.  easily. When you use the linker with the FORTRAN libraries you may need to
  3955.  specify the /NOD (no-default libraries) option and specify all the libraries
  3956.  you need directly on the LINK command line. You can also specify these
  3957.  libraries with an automatic-response file (or batch file).
  3958.  
  3959.  If your program uses both FORTRAN and C, then specify the library for the
  3960.  most recent of the two language products first. If you use C 4.0 with
  3961.  FORTRAN 4.0 or later, specify the FORTRAN library first. If you use C 5.1 or
  3962.  later, specify the C library first. In addition, make sure you choose a
  3963.  C-compatible library when you install FORTRAN.
  3964.  
  3965.  If you are listing BASIC libraries on the LINK command line, the BASIC
  3966.  libraries must precede all others, as in the following example:
  3967.  
  3968.       LINK /NOD mod1 mod2,,,GRAFX+LLIBCE+LLIBFORE
  3969.  
  3970.  Here two object modules, mod1  and mod2, are linked with the C 5.1 and
  3971.  FORTRAN 5.0 large-model libraries. In addition, the example links in an
  3972.  extra library, GRAFX.
  3973.  
  3974.  
  3975.  4.2  Calling Other High-Level Languages
  3976.  
  3977.  In addition to the compiling and linking considerations mentioned above,
  3978.  your program will also need to follow some internal conventions for calling
  3979.  a routine written in another language. These considerations include creating
  3980.  an interface to the called routine and using keywords appropriate to the
  3981.  particular language called.
  3982.  
  3983.  For information on transferring data between languages, consult Chapter 5.
  3984.  
  3985.  
  3986.  4.2.1  The INTERFACE Statement
  3987.  
  3988.  To call another language routine from within a FORTRAN function, first write
  3989.  an interface to the routine with the INTERFACE statement. This statement
  3990.  allows you to use special keywords (attributes) that affect the way FORTRAN
  3991.  carries out calls. These keywords allow you to adjust naming conventions,
  3992.  calling conventions, and parameter-passing methods so that you can make
  3993.  routines from other languages compatible with FORTRAN.
  3994.  
  3995.  Here are the guidelines to interfaces for routines from other languages:
  3996.  
  3997.    1. Write an INTERFACE statement for each routine you call.
  3998.  
  3999.       Write the interface to a FUNCTION if the routine returns a value, or to
  4000.       a SUBROUTINE if the routine does not return a value. The INTERFACE
  4001.       statement needs to precede any calls to the routine.
  4002.  
  4003.    2. Apply the C attribute to the routine if it is written in C (unless the
  4004.       C module is compiled with the /Gc routine or is modified with the
  4005.       fortran or pascal keyword).
  4006.  
  4007.       The C attribute causes the routine to be called with the C naming and
  4008.       calling conventions. It also changes the default parameter-passing
  4009.       method for all parameters to pass by value. To apply the C attribute,
  4010.       type [C] immediately after the name of the routine.
  4011.  
  4012.    3. If the routine is called from Pascal, you may want to apply the PASCAL
  4013.       attribute to the routine. This keyword does not change calling or
  4014.       naming conventions, but causes all parameters to pass by value.
  4015.  
  4016.       To apply the PASCAL attribute, type [PASCAL] immediately after the
  4017.       name of the routine.
  4018.  
  4019.    4. If $TRUNCATE is on and the name of the routine is longer than 6
  4020.       characters, use the ALIAS attribute. The use of ALIAS is explained in
  4021.       Section 4.2.3 below.
  4022.  
  4023.    5. Adjust the way parameters are passed by applying the NEAR, FAR, VALUE,
  4024.       and REFERENCE attributes to parameter declarations.
  4025.  
  4026.       The REFERENCE attribute can be useful because the C and PASCAL keywords
  4027.       automatically change the default parameter-passing method to passing by
  4028.       value. For any given parameter, REFERENCE reverts the method to passing
  4029.       by reference. (By default, FORTRAN passes by far reference unless you
  4030.       are using the medium memory model available with FORTRAN, Versions 4.0
  4031.       or later.)
  4032.  
  4033.       To apply an attribute to a parameter declaration, put the attribute in
  4034.       brackets, along with any other attributes that modify the same object,
  4035.       and place the attribute and brackets immediately after the parameter.
  4036.       (See the examples below.)
  4037.  
  4038.    6. Once the proper interface is set up, call the routine just as you would
  4039.       call any FORTRAN function or subroutine.
  4040.  
  4041.  Examples
  4042.  
  4043.  In the examples below, the variables N, I, and J are not significant,
  4044.  except for their types and attributes.
  4045.  
  4046.  This first example declares the subroutine TEST with the PASCAL attribute.
  4047.  
  4048.             INTERFACE TO SUBROUTINE TEST [PASCAL] (N)
  4049.             INTEGER*2 N [NEAR, REFERENCE]
  4050.             END
  4051.  
  4052.  The subroutine takes one argument, N, which contains both of the NEAR and
  4053.  REFERENCE attributes. Therefore N is passed by near reference.
  4054.  
  4055.  The second example declares a C function, CFUN, which returns a value of
  4056.  type REAL*8.
  4057.  
  4058.             INTERFACE TO REAL*8 FUNCTION CFUN [C] (I,J)
  4059.             REAL*8 I [REFERENCE]
  4060.             REAL*8 J
  4061.             END
  4062.  
  4063.  The argument I is passed by far reference because of the REFERENCE
  4064.  attribute; the argument J is passed by value because the C attribute
  4065.  changes the default.
  4066.  
  4067.  
  4068.  4.2.2  An Alternative Interface to C
  4069.  
  4070.  Step 2 of the above guidelines suggests modifying the behavior of FORTRAN
  4071.  with the C attribute when calling a C routine. Alternately, since the pascal
  4072.  and fortran keywords are functionally equivalent, you can modify the
  4073.  behavior of C by applying either keyword to the function definition heading.
  4074.  Or, you can compile the C module with the /Gc option, which specifies that
  4075.  all C functions, calls, and public symbols use the FORTRAN/Pascal/BASIC
  4076.  conventions.
  4077.  
  4078.  For example, the following C function uses the FORTRAN/Pascal/BASIC
  4079.  conventions to receive an integer parameter:
  4080.  
  4081.             int fortran fun1(n)
  4082.             int n;
  4083.  
  4084.  
  4085.  4.2.3  The ALIAS Attribute
  4086.  
  4087.  The ALIAS attribute allows you to refer to a routine by one name in your
  4088.  code while the object code uses another name. The attribute is particularly
  4089.  helpful when the called routine has a cryptic name.
  4090.  
  4091.  The ALIAS attribute uses this syntax ALIAS: ' aliasname '. Note that
  4092.  aliasname is the name FORTRAN will actually place in the object code
  4093.  whenever the declared routine is called. When you use this feature,
  4094.  aliasname is precisely what FORTRAN will place in the object code;
  4095.  therefore, if you are linking to a C routine, be sure to type a leading
  4096.  underscore (_) before the name.
  4097.  
  4098.  The ALIAS feature is necessary when using the $TRUNCATE metacommand and the
  4099.  name of a routine exceeds 6 characters. Without ALIAS, FORTRAN would place
  4100.  only the first 6 characters into the object file, while the other language
  4101.  would place 8 or more characters into the other object file (up to 40 in the
  4102.  case of BASIC). This difference would prevent the linker from finding a
  4103.  match. Without $TRUNCATE, Microsoft FORTRAN will accept up to 31 characters.
  4104.  
  4105.  In the example below, ALIAS is used because PRINTNUM  is longer than 6
  4106.  characters. Note that the leading underscore should be used only when
  4107.  linking to a routine that uses the C naming convention.
  4108.  
  4109.       $TRUNCATE
  4110.             INTERFACE TO PRINTNUM [C, ALIAS:'_printnum'] (N)
  4111.             INTEGER*2 N
  4112.             END
  4113.  
  4114.  
  4115.  4.2.4  FORTRAN Calls to C and Pascal
  4116.  
  4117.  Writing FORTRAN interfaces to C is fairly straightforward. Calling Pascal
  4118.  from FORTRAN is also simple, because the PASCAL attribute causes FORTRAN to
  4119.  use the Pascal default of passing data by value. This section applies the
  4120.  steps outlined in Section 4.2.1 to two examples of FORTRAN-C programs. A
  4121.  brief analysis follows each example.
  4122.  
  4123.  
  4124.  4.2.4.1  Calling C from FORTRAN──No Return Value
  4125.  
  4126.  The example below demonstrates a FORTRAN main module calling a C function,
  4127.  maxparam. This function returns no value but adjusts the lower of two
  4128.  parameters to equal the higher argument.
  4129.  
  4130.       C     FORTRAN SOURCE FILE - CALLS C FUNCTION, NO RETURN
  4131.       C     VALUE
  4132.       C
  4133.             INTERFACE TO SUBROUTINE MAXPARAM [C] (I,J)
  4134.             INTEGER*2 I [NEAR, REFERENCE]
  4135.             INTEGER*2 J [NEAR, REFERENCE]
  4136.             END
  4137.  
  4138.       C
  4139.       C     C ATTRIBUTE DIRECTS FORTRAN TO USE C CONVENTIONS
  4140.       C     EACH PARAMETER PASSED BY NEAR REFERENCE
  4141.       C
  4142.             INTEGER*2 I,J
  4143.             I = 5
  4144.             J = 7
  4145.             WRITE (*,*) 'I = ',I,' J = ', J
  4146.             CALL MAXPARAM(I,J)
  4147.             WRITE (*,*) 'I = ',I,' J = ', J
  4148.             END
  4149.  
  4150.       /* C source file */
  4151.       /* Compile in MEDIUM or LARGE memory model */
  4152.       /* Maxparam declared VOID because no return value */
  4153.  
  4154.       void maxparam(p1, p2)
  4155.       int near *p1;  /* Integer params received by near ref. */
  4156.       int near *p2;  /* NEAR keyword not needed in MEDIUM model */
  4157.       {
  4158.          if (*p1 > *p2)
  4159.                  *p2 = *p1;
  4160.          else
  4161.                  *p1 = *p2;
  4162.        }
  4163.  
  4164.  Both modules place _maxparam  (consistent with the C naming convention) into
  4165.  an object file. The C attribute in the INTERFACE statement causes the
  4166.  MAXPARAM  function to be called with the C calling convention, which pushes
  4167.  param-eters in reverse order and specifies other lower-level differences.
  4168.  
  4169.  Since the function maxparam  may alter the value of either parameter, both
  4170.  must be passed by reference. Near reference is implemented in FORTRAN with
  4171.  the NEAR and REFERENCE attributes and in C by using near pointers. The
  4172.  REFERENCE attribute is necessary in FORTRAN, since the C keyword changes the
  4173.  default-passing method to pass by value.
  4174.  
  4175.  Far reference could have been specified by leaving off the NEAR keyword from
  4176.  the FORTRAN parameter declarations. In that case, the C module would need to
  4177.  use far pointers.
  4178.  
  4179.  
  4180.  4.2.4.2  Calling C from FORTRAN──Function Call
  4181.  
  4182.  The example below demonstrates a FORTRAN main module calling a C function,
  4183.  fact. This function returns the factorial of an integer value.
  4184.  
  4185.       C     FORTRAN SOURCE FILE - CALLS C FUNCTION
  4186.       C
  4187.             INTERFACE TO INTEGER*2 FUNCTION FACT [C] (N)
  4188.             INTEGER*2 N
  4189.             END
  4190.  
  4191.       C
  4192.       C     C ATTRIBUTE DIRECTS FORTRAN TO USE C CONVENTIONS
  4193.       C     PARAMETER PASSED BY VALUE, WHICH IS DEFAULT WHEN
  4194.       C     C ATTRIBUTE IS IN USE
  4195.       C
  4196.             INTEGER*2 FACT
  4197.             INTEGER*2 I,J
  4198.             I = 3
  4199.             J = 4
  4200.             WRITE (*,*) 'The factorial of I   is ',FACT(I)
  4201.             WRITE (*,*) 'The factorial of J   is ',FACT(J)
  4202.             WRITE (*,*) 'The factorial of I+J is ',FACT(I+J)
  4203.             END
  4204.  
  4205.       /* C source file */
  4206.       /* Compile in MEDIUM or LARGE model */
  4207.       /* Factorial function, returning integer */
  4208.  
  4209.       int fact(n)
  4210.       int n; /* Integer received by value, the C default */
  4211.       {
  4212.            int    result = 1;
  4213.  
  4214.            while  (n)
  4215.                   result *= n--; /* Parameter n modified here */
  4216.            return (result);
  4217.       }
  4218.  
  4219.  The C attribute in the INTERFACE statement causes FACT to be called with
  4220.  the C naming convention (as _fact). The C attribute in the INTERFACE
  4221.  statement causes FACT to be called with the C calling convention, which
  4222.  pushes parameters in reverse order and specifies other lower-level
  4223.  differences.
  4224.  
  4225.  The C function above should receive the parameter by value. Otherwise, the
  4226.  function will corrupt the parameter's value in the calling module. Passing
  4227.  by value is the default method for C; it is also the default method for
  4228.  FORTRAN whenever the C attribute is in use.
  4229.  
  4230.  
  4231.  4.2.4.3  Calling Pascal from FORTRAN──Procedure Call
  4232.  
  4233.  The example below demonstrates a FORTRAN main module calling a Pascal
  4234.  procedure, Maxparam. This procedure adjusts the lower of two parameters to
  4235.  equal the higher argument.
  4236.  
  4237.       C     FORTRAN SOURCE FILE - CALLS PASCAL PROCEDURE
  4238.       C
  4239.             INTERFACE TO SUBROUTINE MAXPARAMETER
  4240.            + [ALIAS:'MAXPARAM'] (I,J)
  4241.             INTEGER*2 I [NEAR]
  4242.             INTEGER*2 J [NEAR]
  4243.             END
  4244.  
  4245.       C
  4246.       C     ALIAS NECESSARY BECAUSE 'MAXPARAMETER' LONGER
  4247.       C     THAN 8 CHARS.
  4248.       C     EACH PARAMETER PASSED BY NEAR REFERENCE
  4249.       C
  4250.             INTEGER*2 I,J
  4251.             I = 5
  4252.             J = 7
  4253.             WRITE (*,*) 'I = ',I,' J = ', J
  4254.             CALL MAXPARAMETER(I,J)
  4255.             WRITE (*,*) 'I = ',I,' J = ', J
  4256.             END
  4257.  
  4258.       { Pascal source code - Maxparam procedure. }
  4259.  
  4260.       module Psub;
  4261.        procedure Maxparam(var a:integer; var b:integer);
  4262.  
  4263.       { Two integer parameters are received by near reference. }
  4264.       { Near reference is specified with the VAR keyword. }
  4265.  
  4266.        begin
  4267.           if a > b then
  4268.              b := a
  4269.           else
  4270.              a := b
  4271.        end;
  4272.       end.
  4273.  
  4274.  By default, FORTRAN places all 12 characters of MAXPARAMETER into the
  4275.  object file, whereas Pascal places only 8. The ALIAS attribute resolves this
  4276.  conflict: both modules place MAXPARAM into an object file. FORTRAN and
  4277.  Pascal use the same convention for calling.
  4278.  
  4279.  Since the procedure Maxparam may alter the value of either parameter, both
  4280.  must be passed by reference. Near reference was implemented in FORTRAN with
  4281.  the NEAR attribute, and in Pascal with the VAR keyword. The PASCAL attribute
  4282.  is not used here because no parameter is being passed by value.
  4283.  
  4284.  Far reference could have been specified by leaving off NEAR from the FORTRAN
  4285.  parameter declarations, using VARS instead of VAR in the Pascal module.
  4286.  
  4287.  
  4288.  4.2.4.4  Calling Pascal from FORTRAN──Function Call
  4289.  
  4290.  The example below demonstrates a FORTRAN main module calling a Pascal
  4291.  function, Fact. This function returns the factorial of an integer value.
  4292.  
  4293.       C     FORTRAN SOURCE FILE - CALLS PASCAL FUNCTION
  4294.       C
  4295.             INTERFACE TO INTEGER*2 FUNCTION FACT [PASCAL] (N)
  4296.             INTEGER*2 N
  4297.             END
  4298.  
  4299.       C
  4300.       C     PARAMETER PASSED BY VALUE, WHICH IS DEFAULT WHEN
  4301.       C     PASCAL ATTRIBUTE IS IN USE
  4302.       C
  4303.             INTEGER*2 FACT
  4304.             INTEGER*2 I,J
  4305.             I = 3
  4306.             J = 4
  4307.             WRITE (*,*) 'The factorial of I   is ',FACT(I)
  4308.             WRITE (*,*) 'The factorial of J   is ',FACT(J)
  4309.             WRITE (*,*) 'The factorial of I+J is ',FACT(I+J)
  4310.             END
  4311.  
  4312.       { Pascal source code - factorial function. }
  4313.  
  4314.       module Pfun;
  4315.        function Fact (n : integer) : integer;
  4316.  
  4317.       { Integer parameters received by value, the Pascal default. }
  4318.  
  4319.        begin
  4320.           Fact := 1;
  4321.           while n > 0 do
  4322.               begin
  4323.                   Fact := Fact * n;
  4324.                   n := n - 1;           { Parameter n modified here.}
  4325.               end;
  4326.        end;
  4327.       end.
  4328.  
  4329.  FORTRAN and Pascal use a similar naming convention. The ALIAS statement is
  4330.  unnecessary because the function name does not exceed the Pascal limit of 8
  4331.  characters. FORTRAN and Pascal use the same calling convention.
  4332.  
  4333.  The Pascal function above should receive the parameter by value. Otherwise,
  4334.  the function will corrupt the parameter's value in the calling module.
  4335.  Passing by value is the default method for Pascal; it is also the default
  4336.  method for FORTRAN whenever the PASCAL attribute is in use.
  4337.  
  4338.  
  4339.  4.2.5  C Functions Available with FORTRAN Run-Time Libraries
  4340.  
  4341.  The FORTRAN run-time libraries MLIBFORx.LIB and LLIBFORx.LIB include the
  4342.  system routine and a subset of the spawnlp routine (as well as other
  4343.  rou-tines) originally from the C library. FORTRAN programs access these
  4344.  routines in the FORTRAN run-time libraries; however, these routines may
  4345.  present compatibility problems with future versions of Microsoft C. Sections
  4346.  4.2.5.1-4.2.5.2 show how to access these C routines and discuss future
  4347.  compatibility issues. (The demonstration program DEMOEXEC.FOR included with
  4348.  the Microsoft FORTRAN Compiler also gives examples of how to call these C
  4349.  routines.)
  4350.  
  4351.  
  4352.  4.2.5.1  Accessing system and spawnlp Functions
  4353.  
  4354.  The system function has the following declaration in C:
  4355.  
  4356.            int system (string)
  4357.            char *string;
  4358.  
  4359.  The system function passes a specified C string (ending with a null
  4360.  character) to the DOS command interpreter (COMMAND.COM), which interprets
  4361.  and exe-cutes the string as a DOS command. This allows DOS commands (such as
  4362.  DIR or DEL), batch files, and programs to be executed.
  4363.  
  4364.  The following program fragment shows how to access the system function from
  4365.  a FORTRAN program to display all files in the current directory with the
  4366.  file extension .FOR.
  4367.  
  4368.             INTEGER*2 SYSTEM
  4369.       C     RETURN TYPE MUST BE DECLARED;
  4370.       C     NOTICE THE C LITERAL STRING  '...'C
  4371.             I = SYSTEM ('DIR *.FOR'C)
  4372.  
  4373.  The INTERFACE statement required to access system is given below. The C
  4374.  attribute is specified after the function name. The argument string includes
  4375.  the REFERENCE attribute to indicate that the argument is passed by
  4376.  reference.
  4377.  
  4378.             INTERFACE TO INTEGER*2 FUNCTION SYSTEM [C]
  4379.            + (STRING[REFERENCE])
  4380.             CHARACTER*1 STRING
  4381.             END
  4382.  
  4383.  The spawnlp function has the following declaration in C:
  4384.  
  4385.       int spawnlp (mode,path,arg0,arg1,...,argn)
  4386.          int mode;    /* spawn mode */
  4387.          char *path;  /* pathname of program to execute */
  4388.          char *arg0;  /* should be the same as path */
  4389.          char *arg1,...,*argn;    /* command line arguments */
  4390.          /* argn must be NULL */
  4391.  
  4392.  This function creates and executes a new child process. There must be enough
  4393.  memory to load and execute the child process. The mode argument determines
  4394.  which form of spawnlp is executed. For the version of the spawnlp function
  4395.  in the FORTRAN run-time libraries, this value must be 0, which tells spawnlp
  4396.  to suspend the parent program and execute the child program. When the child
  4397.  program terminates, the parent program resumes execution. The return value
  4398.  from spawnlp is -1 if an error occurs. If the child process runs
  4399.  successfully, the return value is the return code from the child process.
  4400.  
  4401.  The path argument specifies the file to be executed as the child process.
  4402.  The path can specify a full path name from the root directory, a partial
  4403.  path name from the current working directory, or a file name. If the path
  4404.  argument does not have a file-name extension or end with a period (.), the
  4405.  spawnlp call first appends the extension .COM and searches for the file. If
  4406.  spawnlp cannot find the file, it appends the extension .EXE and tries to
  4407.  find the file again. The spawnlp routine also searches for the file in any
  4408.  of the directories specified in the PATH environment variable using the same
  4409.  procedure.
  4410.  
  4411.  The INTERFACE statement required to access spawnlp from a FORTRAN program is
  4412.  given below. The C attribute must appear after the function name. The
  4413.  VARYING attribute indicates that a variable number of arguments may be
  4414.  passed to the function.
  4415.  
  4416.             INTERFACE TO INTEGER*2 FUNCTION SPAWNLP
  4417.            + [C,VARYING] (MODE)
  4418.             INTEGER*2 MODE
  4419.             END
  4420.  
  4421.  If you use the $STRICT or $TRUNCATE metacommands, you must use a name 6
  4422.  characters or less in the INTERFACE statement and use the ALIAS attribute to
  4423.  associate the FORTRAN name SPAWN with the C identifier spawnlp.
  4424.  
  4425.  The following program fragment illustrates how to call the spawnlp function
  4426.  from a FORTRAN program:
  4427.  
  4428.       C     (THE RETURN TYPE MUST BE DECLARED)
  4429.             INTEGER*2 SPAWNLP
  4430.             .
  4431.             .
  4432.             .
  4433.       C      EXECUTE AS A CHILD PROCESS
  4434.             I = SPAWNLP(0, LOC('EXEMOD'C), LOC('EXEMOD'C), c
  4435.            + LOC('DEMOEXEC.EXE'C), INT4(0))
  4436.  
  4437.  Notice in this example that the method used to pass strings to spawnlp is
  4438.  different from the method used to pass strings to system. This is because
  4439.  the string arguments to spawnlp are undeclared in the INTERFACE statement
  4440.  and assumed to be passed by value. The spawnlp function expects the
  4441.  addresses of the strings rather than the actual characters, so the FORTRAN
  4442.  program uses the LOC intrinsic function to pass the address. (Remember that
  4443.  functions with the C attribute pass arguments by value.) The last argument
  4444.  to the spawnlp routine must be a C null pointer (an integer 0), so the
  4445.  FORTRAN program must use either the INT2(0)  or the INT4(0)  intrinsic
  4446.  function (depending on the memory model) to pass this pointer by value as
  4447.  the last argument.
  4448.  
  4449.  
  4450.  4.2.5.2  FORTRAN Libraries and Future Versions of Microsoft C
  4451.  
  4452.  If you plan to mix Microsoft FORTRAN modules with modules compiled using
  4453.  Microsoft C, you should use the SETUP utility to prepare new copies of your
  4454.  FORTRAN run-time libraries. When you create these copies, tell SETUP that
  4455.  you want the copies to interface with C. In these copies, SETUP removes the
  4456.  C routines. Later, when you link FORTRAN modules with C modules, you should
  4457.  link with the appropriate C run-time library for the memory model that you
  4458.  are using. This link will take care of unresolved references from
  4459.  MLIBFORx.LIB and LLIBFORx.LIB. You can still use your original copies of
  4460.  MLIBFORx.LIB and LLIBFORx.LIB for programs that do not include C modules.
  4461.  
  4462.  
  4463.  4.2.6  FORTRAN Calls to BASIC
  4464.  
  4465.  Calls from FORTRAN programs to BASIC (MS QuickBASIC 4.0 or later or
  4466.  Microsoft BASIC Compiler 6.0 or later) programs are not directly supported.
  4467.  No BASIC routine can be executed unless the main program is in BASIC,
  4468.  because a BASIC routine requires the environment to be initialized in a way
  4469.  that is unique to BASIC. No other language will perform this special
  4470.  initialization.
  4471.  
  4472.  It is possible for a program to start up in BASIC, call a FORTRAN function
  4473.  that does most of the work of the program, and then call BASIC subprograms
  4474.  and function procedures as needed. Figure 4.3 illustrates how this can be
  4475.  done.
  4476.  
  4477.  Here are the recommended rules for calling BASIC from FORTRAN:
  4478.  
  4479.    1. Start up in a BASIC main module. You will need to use QuickBASIC,
  4480.       Version 4.0 or later, and may want to use the DECLARE statement to
  4481.       write an interface to the principal FORTRAN routine. (See Section
  4482.       5.1.1, "BASIC Arguments," for more information.)
  4483.  
  4484.    2. Write an interface in FORTRAN for each BASIC routine you plan to call.
  4485.       Since BASIC and FORTRAN use the same calling convention, no special
  4486.       keyword is required to make FORTRAN compatible with BASIC.
  4487.  
  4488.    3. Make sure that all data are passed by near reference. BASIC can pass
  4489.       data in a variety of ways, but is unable to receive data in any form
  4490.       other than near reference.
  4491.  
  4492.       With near pointers, the program assumes that the data are in the
  4493.       default data segment. If you want to pass data that are not in the
  4494.       default data segment (this is only a consideration with large-model
  4495.       programs), then first copy the data to a variable that is in the
  4496.       default data segment.
  4497.  
  4498.  The example below demonstrates a BASIC program which calls a FORTRAN
  4499.  subroutine. The FORTRAN subroutine then calls a BASIC function that returns
  4500.  twice the number passed it, and a BASIC subprogram that prints two numbers.
  4501.  
  4502.       ' BASIC source
  4503.       '
  4504.       DEFINT A-Z
  4505.       DECLARE SUB Fprog ()
  4506.       CALL Fprog
  4507.       END
  4508.       '
  4509.       FUNCTION Dbl(N) STATIC
  4510.           Dbl = N*2
  4511.       END FUNCTION
  4512.       '
  4513.       SUB Printnum(A,B) STATIC
  4514.           PRINT "The first number is ";A
  4515.           PRINT "The second number is ";B
  4516.       END SUB
  4517.  
  4518.  
  4519.       C     FORTRAN subroutine
  4520.       C     Calls a BASIC function that receives one integer,
  4521.       C     and a BASIC subprogram that takes two integers.
  4522.       C
  4523.             INTERFACE TO INTEGER*2 FUNCTION DBL (N)
  4524.             INTEGER*2 N [NEAR]
  4525.             END
  4526.       C
  4527.             INTERFACE TO SUBROUTINE PRINTNUM(N1, N2)
  4528.             INTEGER*2 N1 [NEAR]
  4529.             INTEGER*2 N2 [NEAR]
  4530.             END
  4531.       C
  4532.       C     Parameters must be declared NEAR in the parameter
  4533.       C     declarations; BASIC receives ONLY 2-byte pointers
  4534.  
  4535.       C
  4536.             SUBROUTINE FPROG
  4537.             INTEGER*2 DBL
  4538.             INTEGER*2 A, B
  4539.             A = 5
  4540.             B = 6
  4541.             WRITE (*, *) 'Doubling 5 equals ', DBL(A)
  4542.             CALL PRINTNUM(A, B)
  4543.             END
  4544.  
  4545.  In the example above, note that the NEAR attribute is used in the FORTRAN
  4546.  routines, so that near addresses will be passed to BASIC instead of far
  4547.  addresses.
  4548.  
  4549.  
  4550.  4.3  Using Assembly-Language Routines
  4551.  
  4552.  You may want to consider writing routines in assembly language when you need
  4553.  extreme speed (or when another language would run too slowly). With the
  4554.  Microsoft Macro Assembler (MASM) you can write assembly modules that can be
  4555.  linked to modules developed with Microsoft FORTRAN. This section outlines
  4556.  the recommended programming guidelines for writing assembly routines
  4557.  compatible with Microsoft FORTRAN and gives specific examples.
  4558.  
  4559.  Writing assembly routines for Microsoft FORTRAN is easiest when you use the
  4560.  simplified segment directives provided with the Microsoft Macro Assembler,
  4561.  Version 5.0. In general, this chapter assumes that you have MASM 5.0.
  4562.  
  4563.  A FORTRAN program can call an external assembly procedure with the use of
  4564.  the INTERFACE statement. However, the INTERFACE statement is not strictly
  4565.  necessary unless you intend to change one of the FORTRAN defaults. However,
  4566.  you may find the following guidelines helpful:
  4567.  
  4568.    1. Declare procedures called from FORTRAN as FAR.
  4569.  
  4570.    2. Observe the FORTRAN calling convention.
  4571.  
  4572.       a.   Upon exit, the procedure must reset SP to the value it had before
  4573.            the arguments were placed on the stack. This is accomplished with
  4574.            the instruction RET size, where size is the total size of all the
  4575.            parameters.
  4576.  
  4577.       b.   Arguments are placed on the stack in the same order in which they
  4578.            appear in the FORTRAN source code. The first parameter will be
  4579.            highest in memory (because it is also the first parameter to be
  4580.            placed on the stack, and the stack grows downward).
  4581.  
  4582.       c.   By default, FORTRAN parameters are passed by reference as far
  4583.            addresses if the FORTRAN module is compiled in the large or huge
  4584.            memory model, and as near addresses if the FORTRAN module is
  4585.            compiled in the medium model. Versions of FORTRAN prior to 4.0 are
  4586.            always large model.
  4587.  
  4588.    3. Observe the FORTRAN naming convention.
  4589.  
  4590.       FORTRAN only recognizes the first 6 characters of any name if the
  4591.       metacommand $TRUNCATE is specified, while the assembler recognizes the
  4592.       first 31. By default, FORTRAN recognizes 31 characters.
  4593.  
  4594.  In the following example, FORTRAN calls an assembly procedure that
  4595.  calculates "A x 2^(B)," where A and B are the first and second parameters,
  4596.  respectively. This is done by shifting the bits in A to the left, B times.
  4597.  
  4598.  The following example shows how FORTRAN would call the assembly procedure:
  4599.  
  4600.             INTERFACE TO INTEGER*2 POWER2(A,B)
  4601.             INTEGER*2 A,B
  4602.             END
  4603.       C
  4604.             INTEGER*2 A,B
  4605.             A = 3
  4606.             B = 5
  4607.             WRITE (*,*) '3 times 2 to the power of 5 is ',
  4608.            + POWER2(A,B)
  4609.             END
  4610.  
  4611.  To understand how to write the assembly procedure, consider how the
  4612.  parameters are placed on the stack, as illustrated in Figure 4.4.
  4613.  
  4614.  Figure 4.4 assumes large-model FORTRAN. If you compile the FORTRAN module in
  4615.  medium model, then each argument will be passed as a two-byte, not four-byte
  4616.  address. The return address is four bytes long because procedures called
  4617.  from FORTRAN must always be FAR.
  4618.  
  4619.  Arg 1  (parameter 1) is higher in memory than Arg 2  because FORTRAN pushes
  4620.  arguments (parameters) in the same order that they appear.
  4621.  
  4622.  The assembly procedure can be written as follows:
  4623.  
  4624.       .MODEL LARGE
  4625.       .CODE
  4626.                  PUBLIC  Power2
  4627.       Power2     PROC
  4628.                  push    bp           ; Entry sequence - save old BP
  4629.                  mov     bp,sp        ; Set stack frame pointer
  4630.  
  4631.                  les     bx,[bp+10]   ; Load Arg1 into
  4632.                  mov     ax,es:[bx]   ;   AX
  4633.                  les     bx,[bp+6]    ; Load Arg2 into
  4634.                  mov     cx,es:[bx]   ;   CX
  4635.                  shl     ax,cl        ; AX = AX * (2 to power of CX)
  4636.                                       ; Leave return value in AX
  4637.  
  4638.                  pop     bp           ; Exit sequence - restore old BP
  4639.                  ret     8            ; Return and restore 8 bytes
  4640.        Power2    ENDP
  4641.                  END
  4642.  
  4643.  In the example above, each argument must be loaded using the four-byte
  4644.  address that was pushed onto the stack. The procedure loads four-byte
  4645.  addresses with the les instruction, which loads the destination operand (in
  4646.  this case, BX) with the source operand, and also loads ES with the object
  4647.  two bytes higher in memory. Thus, the instruction
  4648.  
  4649.                 les     bx,[bp+10]
  4650.  
  4651.  loads BX with the value at BP+10 (an offset address), and ES with the
  4652.  value at BP+12 (a segment address), which is necessary to set up the next
  4653.  instruction.
  4654.  
  4655.  Upon exit, the stack is restored with the instruction ret 8, since the total
  4656.  size of parameters pushed onto the stack is eight bytes.
  4657.  
  4658.  4.4  Calling FORTRAN from Other Languages
  4659.  
  4660.  Other compiled Microsoft languages──C, Pascal and BASIC──support calls to
  4661.  compiled FORTRAN subroutines and functions. If there is a set of FORTRAN
  4662.  routines you use regularly, but you also program in one or more of these
  4663.  languages, you can save a duplication of effort by calling these FORTRAN
  4664.  routines rather than translating them into other languages.
  4665.  
  4666.  Note that, unlike Pascal and C, FORTRAN does not have public variables. Only
  4667.  functions, subroutines, and common blocks are public; individual FORTRAN
  4668.  variables cannot be declared public. Therefore, if you want a procedure
  4669.  written in another language to directly access a FORTRAN variable, that
  4670.  variable must appear in a FORTRAN common block. For example, you can declare
  4671.  a common block in a FORTRAN routine, then access it from a C program by
  4672.  declaring an external structure with the same form.
  4673.  
  4674.  Each language has its own conventions and procedures for accessing Microsoft
  4675.  FORTRAN. They are explained in the section of that language's manual which
  4676.  covers mixed-language programming.
  4677.  
  4678.  
  4679.  Chapter 5  Transferring Data between Languages
  4680.  ───────────────────────────────────────────────────────────────────────────
  4681.  
  4682.  Chapter 4 introduced the general concepts of passing parameters by reference
  4683.  and by value. In some situations you may want to pass parameters by a
  4684.  particular method or to pass different types of data (logicals, strings, or
  4685.  arrays as opposed to strictly numerical data). This chapter provides you
  4686.  with the information you'll need.
  4687.  
  4688.  The first section of this chapter discusses ways to change each language's
  4689.  standard manner of passing data. The second section covers numeric, logical,
  4690.  and string data; the third addresses special situations involving structured
  4691.  data (such as arrays) and externally accessed data.
  4692.  
  4693.  
  4694.  5.1  Passing by Reference or Value
  4695.  
  4696.  This section describes how to override the default method each language uses
  4697.  to pass data. The section contains four parts, each of which summarizes
  4698.  parameter-passing methods in a particular language and discusses how to pass
  4699.  arguments by value, by near reference, and by far reference. To successfully
  4700.  pass data between languages, you must consider how each parameter is passed
  4701.  by the calling routine and how each is received by the called routine.
  4702.  
  4703.  
  4704.  5.1.1  BASIC Arguments
  4705.  
  4706.  The default for BASIC is to pass all arguments by near reference. Every
  4707.  BASIC subprogram or function always receives parameters by near reference.
  4708.  
  4709.  A BASIC argument passes by value when the called routine is first declared
  4710.  with a DECLARE statement  and the BYVAL keyword is applied to the argument.
  4711.  Note that BYVAL applies to one argument only; if your routine uses three
  4712.  arguments and you want all of them to pass by value, you must put the BYVAL
  4713.  option in front of each argument.
  4714.  
  4715.  BASIC will pass each argument in a call by far reference when CALLS is used
  4716.  to invoke a routine. Using SEG to modify a parameter in a preceding DECLARE
  4717.  statement will also cause BASIC to pass that parameter by far reference.
  4718.  
  4719.  
  4720.  5.1.2  C Arguments
  4721.  
  4722.  The default for C is to pass all arrays by reference (near or far, depending
  4723.  on the memory model) and all other data types by value. C uses far data
  4724.  pointers for compact, large, and huge models, and near data pointers for
  4725.  small and medium models. FORTRAN supports medium, large, and huge memory
  4726.  models.
  4727.  
  4728.  The C default is to pass all nonarrays (which includes all data types other
  4729.  than those explicitly declared as arrays) by value.
  4730.  
  4731.  Arrays can be passed by value by declaring them as the only member of a
  4732.  structure.
  4733.  
  4734.  In C, passing a pointer to an object is equivalent to passing the object
  4735.  itself by reference. The default for arrays is to pass by reference. In C,
  4736.  near reference is the default for passing pointers in small and medium
  4737.  models. Far reference is the default in the compact, large, and huge models.
  4738.  
  4739.  
  4740.  5.1.3  FORTRAN Arguments
  4741.  
  4742.  The FORTRAN default is to pass and receive all arguments by reference. The
  4743.  size of the address passed depends on the memory model.
  4744.  
  4745.  A parameter passes by value when declared with the VALUE attribute. This
  4746.  declaration can occur either in an INTERFACE statement (which determines how
  4747.  to pass a parameter) or in a function or subroutine declaration (which
  4748.  determines how to receive a parameter).
  4749.  
  4750.  A function or subroutine declared with the PASCAL or C attribute will pass
  4751.  by value all parameters declared in its parameter list except for those
  4752.  parameters declared with the REFERENCE attribute. This change in default
  4753.  passing method applies to function and subroutine definitions, as well as to
  4754.  an INTERFACE statement.
  4755.  
  4756.  Passing by reference is the default for FORTRAN. However, if either the C or
  4757.  PASCAL attribute is applied to a function or subroutine declaration, then
  4758.  you need to apply the REFERENCE attribute to any parameter of the routine
  4759.  that you want passed by reference.
  4760.  
  4761.  Near reference is the default for medium-model FORTRAN programs; far
  4762.  reference is the default for large- and huge-model programs.
  4763.  
  4764.  ───────────────────────────────────────────────────────────────────────────
  4765.  NOTE
  4766.     Versions of FORTRAN prior to 4.0 always compile in large memory model.
  4767.  ───────────────────────────────────────────────────────────────────────────
  4768.  
  4769.  You can apply the NEAR attribute to reference parameters in order to specify
  4770.  near reference. You can apply the FAR attribute to reference parameters in
  4771.  order to specify far reference. These keywords override the default, but
  4772.  have no effect when they specify the same method as the default.
  4773.  
  4774.  You can apply more than one attribute to a given parameter. In that case,
  4775.  enclose both attributes in brackets, separated by a comma:
  4776.  
  4777.             REAL*4 X [NEAR, REFERENCE]
  4778.  
  4779.  
  4780.  5.1.4  Pascal Arguments
  4781.  
  4782.  The Pascal default is to pass all arguments by value. Parameters are passed
  4783.  by near reference when declared as VAR or CONST. Parameters also pass by
  4784.  near reference when the ADR of a variable, or a pointer to a variable, is
  4785.  passed by value. In other words, the address of the variable is first
  4786.  determined, then passed by value. This is essentially the same method used
  4787.  in C.
  4788.  
  4789.  Parameters pass by far reference when declared as VARS or CONSTS. Parameters
  4790.  are also passed by far reference when the ADRS of a variable is passed by
  4791.  value.
  4792.  
  4793.  
  4794.  5.2  Passing Numeric, Logical, and String Data
  4795.  
  4796.  This section explains procedures for passing and receiving different types
  4797.  of data. The discussion focuses on the differences in string formats and on
  4798.  the methods of passing strings between FORTRAN and other languages.
  4799.  
  4800.  
  4801.  5.2.1  Integer and Real Numbers
  4802.  
  4803.  Integers and reals are usually the simplest kinds of data to pass between
  4804.  languages. However, the type of numerical data is named differently in each
  4805.  language; furthermore, not all data types are available in every language,
  4806.  and another type may have to be substituted in some cases.
  4807.  
  4808.  Table 5.1 shows equivalent data types in each language.
  4809.  
  4810.  Table 5.1  Equivalent Numeric Data Types
  4811.  ───────────────────────────────────────────────────────────────────────────
  4812.  
  4813.  BASIC             C                     FORTRAN               Pascal
  4814.  
  4815.  x%                short                 INTEGER*2             INTEGER2
  4816.  INTEGER           int                   ---                   INTEGER (defaul
  4817.  ---               unsigned short       ---                   WORD
  4818.  ---               unsigned              ---                   ---
  4819.  x&                long                  INTEGER*4             INTEGER4
  4820.  LONG              ---                   INTEGER (default)     ---
  4821.  ---               unsigned long        ---                   ---
  4822.  x!                float                REAL*4                REAL4
  4823.  x  (default)      ---                   REAL                  REAL (default)
  4824.  SINGLE            ---                   ---                   ---
  4825.  x#                double                REAL*8                REAL8
  4826.  DOUBLE            ---                   DOUBLE PRECISION      ---
  4827.  ---               unsigned char        CHARACTER*1          BOOLEAN
  4828.  
  4829.  
  4830.  ───────────────────────────────────────────────────────────────────────────
  4831.  WARNING
  4832.     C sometimes performs automatic data conversions that the other languages
  4833.     do not perform. You can prevent C from performing such conversions by
  4834.     declaring a variable as the only member of a structure and then passing
  4835.     this structure. For example, you can pass a variable x of type float by
  4836.     first declaring it as a structure. If you pass a variable of type char or
  4837.     float by value and do not take this precaution, then the C conversion may
  4838.     cause the program to fail.
  4839.  ───────────────────────────────────────────────────────────────────────────
  4840.  
  4841.  
  4842.  5.2.2  FORTRAN COMPLEX Types
  4843.  
  4844.  The FORTRAN types COMPLEX*8 and COMPLEX*16 are not directly implemented in
  4845.  any other language. However, you can write precisely equivalent structures
  4846.  in C, records in Pascal, or user-defined types in BASIC.
  4847.  
  4848.  The type COMPLEX*8 has two fields: The first is a four-byte floating-point
  4849.  number that contains the real component, and the second is a four-byte
  4850.  floating- point number that contains the imaginary component.
  4851.  
  4852.  The type COMPLEX*16 is similar to COMPLEX*8, with the only difference being
  4853.  that each field contains an eight-byte floating-point number. The type
  4854.  COMPLEX is equivalent to the type COMPLEX*8.
  4855.  
  4856.       ┌──────────────────────────────┬───────────────────────────────┐
  4857.       │    Float real component      │    Float imaginary component  │
  4858.       └──────────────────────────────┴───────────────────────────────┘
  4859.       └───────────────┬──────────────┴───────────────┬───────────────┘
  4860.                    4 bytes                        4 bytes
  4861.  
  4862.                         FORTRAN COMPLEX Data Format
  4863.  
  4864.  5.2.3  FORTRAN LOGICAL Type
  4865.  
  4866.  The FORTRAN LOGICAL type is not equivalent to either the Pascal BOOLEAN or C
  4867.  char type. Instead, a FORTRAN LOGICAL*2 is stored as a one-byte indicator
  4868.  value (1=true, 0=false), followed by an unused byte. A FORTRAN  LOGICAL*4 is
  4869.  stored as a one-byte indicator value followed by three unused bytes. The
  4870.  type LOGICAL is equivalent to LOGICAL*4, unless $STORAGE:2 is in effect.
  4871.  
  4872.  To pass or receive a FORTRAN LOGICAL type, declare a C structure, Pascal
  4873.  record, or BASIC user-defined type, with the appropriate fields.
  4874.  
  4875.  
  4876.  5.2.4  Strings
  4877.  
  4878.  Strings are stored in a variety of formats. Therefore, some transformation
  4879.  is frequently required to pass strings between languages.
  4880.  
  4881.  This section presents the string formats used in each language and then
  4882.  describes methods for passing strings from FORTRAN to these languages.
  4883.  
  4884.  
  4885.  5.2.4.1  BASIC Strings
  4886.  
  4887.  Strings are stored in BASIC as four-byte string descriptors, as illustrated
  4888.  below:
  4889.  
  4890.            ┌──────────────────────┬───────────────────────┐
  4891.            │        Length        │   Address (offset)    │
  4892.            └──────────────────────┴───────────────────────┘
  4893.            └───────────┬──────────┴───────────┬───────────┘
  4894.                     2 bytes                2 bytes
  4895.  
  4896.                     BASIC String Descriptor Format
  4897.  
  4898.  The first field of the string descriptor contains a two-byte integer
  4899.  indicating the length of the actual string text. The second field contains
  4900.  the address of this text. This address is an offset into the default data
  4901.  area. BASIC's string management routines reassign this address whenever the
  4902.  length of the string changes, yet these management routines are only
  4903.  available to BASIC. Therefore, FORTRAN should not alter the length of a
  4904.  BASIC string.
  4905.  
  4906.  ───────────────────────────────────────────────────────────────────────────
  4907.  WARNING
  4908.     When you pass a string from BASIC to FORTRAN, the called routine should
  4909.     under no circumstances alter the length of the string. Other languages
  4910.     lack BASIC's string space management routines. Therefore, altering the
  4911.     length of a BASIC string is liable to corrupt parts of the BASIC string
  4912.     space. Changes that do not affect length, however, are relatively safe.
  4913.     The routine that receives the string must not call any BASIC routine. If
  4914.     it does, BASIC's string space management routines may change the location
  4915.     of the string data without warning.
  4916.  ───────────────────────────────────────────────────────────────────────────
  4917.  
  4918.  FORTRAN must receive by near reference. The NEAR attribute makes this
  4919.  adjustment, since the FORTRAN default is to receive by far reference.
  4920.  
  4921.  
  4922.  5.2.4.2  C Strings
  4923.  
  4924.  C stores strings as simple arrays of bytes and uses a null character
  4925.  (numerical 0, ASCII NUL) as a delimiter. For example, consider the string
  4926.  declared as follows:
  4927.  
  4928.       char str[] = "String of text"
  4929.  
  4930.  The string is stored in 15 bytes of memory as
  4931.  
  4932.        ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
  4933.        │ S │ t │ r │ i │ n │ g │   │ o │ f │   │ t │ e │ x │ t │\0 │
  4934.        └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  4935.        C String Format
  4936.  
  4937.  Since str is an array like any other, it is passed by reference, just as
  4938.  other C arrays are. To pass by value, declare the array as a member of a
  4939.  structure. (See Section 5.1.2, "C Arguments," for more information.)
  4940.  
  4941.  When a C string appears in an argument list, C passes the address of the
  4942.  string. C can easily pass data to a fixed-length FORTRAN string.
  4943.  
  4944.  To pass strings to FORTRAN, make sure the called routine receives the string
  4945.  by reference and allocates sufficient space. FORTRAN should expect to
  4946.  receive fixed-length strings. Note, however, that C cannot pass
  4947.  variable-length strings to FORTRAN; the FORTRAN string data are not placed
  4948.  on the stack, but require special low-level variables found only in a
  4949.  FORTRAN program.
  4950.  
  4951.  
  4952.  5.2.4.3  Pascal Strings
  4953.  
  4954.  Pascal has two types of strings, each of which uses a different format: a
  4955.  fixed-length type STRING and the variable-length type LSTRING.
  4956.  
  4957.  The format used for STRING is identical to the FORTRAN string format. The
  4958.  format of an LSTRING stores the length in the first byte. For example,
  4959.  consider an LSTRING declared as
  4960.  
  4961.       VAR STR:LSTRING(14);
  4962.       STR := 'String of text'
  4963.  
  4964.  The string is stored in 15 bytes of memory. The first byte indicates the
  4965.  length of the string text. The remaining bytes contain the string text
  4966.  itself:
  4967.  
  4968.        ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
  4969.        │14 │ S │ t │ r │ i │ n │ g │   │ o │ f │   │ t │ e │ x │ t │
  4970.        └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  4971.        Pascal String Format
  4972.  
  4973.  The Pascal data type LSTRING is not compatible with the format used by
  4974.  FORTRAN. You can pass an LSTRING indirectly, however, by first assigning it
  4975.  to a STRING variable. Pascal supports such assignments by performing a
  4976.  conversion of the data. The Pascal STRING and the FORTRAN CHARACTER*n types
  4977.  are equivalent. Therefore, Pascal fixed-length string variables can be
  4978.  freely passed to  FORTRAN.
  4979.  
  4980.  
  4981.  5.2.4.4  FORTRAN Strings
  4982.  
  4983.  FORTRAN stores strings as a series of bytes at a fixed location in memory.
  4984.  Note that there is no delimiter at the end of the string as in C. Consider
  4985.  the string declared as follows:
  4986.  
  4987.             STR = 'String of text'
  4988.  
  4989.  The string is stored in 14 bytes of memory as:
  4990.  
  4991.        ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
  4992.        │ S │ t │ r │ i │ n │ g │   │ o │ f │   │ t │ e │ x │ t │
  4993.        └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  4994.        FORTRAN String Format
  4995.  
  4996.  Strings are passed by reference, just like other FORTRAN data.
  4997.  Variable-length FORTRAN strings of type CHARACTER*(*) (available in
  4998.  Versions 4.0 and later) cannot effectively be passed to other languages.
  4999.  However, fixed-length strings can be passed without much difficulty; the
  5000.  principal limitation is that the FORTRAN INTERFACE must declare the length
  5001.  of the string in advance.
  5002.  
  5003.  By default, FORTRAN passes strings by reference. However, if you apply the C
  5004.  or PASCAL attribute to a routine, then the default changes to passing by
  5005.  value. The actual string data do not include a delimiter, unless you use the
  5006.  C-string feature described below.
  5007.  
  5008.  FORTRAN cannot directly pass strings to BASIC because BASIC expects to
  5009.  receive a string descriptor when passed a string. However, there is the
  5010.  following indirect method:
  5011.  
  5012.    1. Allocate a fixed-length string in FORTRAN, declare an array of two-byte
  5013.       integers, and treat the array as a string descriptor.
  5014.  
  5015.    2. Assign the address of the string to the first element (using the LOC
  5016.       function), and assign the length of the string to the second element.
  5017.  
  5018.    3. Pass the integer array itself by reference. BASIC can receive and
  5019.       process this array just as it would a string descriptor.
  5020.  
  5021.  The C-string feature overrides the normal FORTRAN format and produces
  5022.  strings that can be effectively manipulated by C. When the C-string feature
  5023.  is used, a null byte is appended to the end of the string, and backslashes
  5024.  that appear in a literal-string text are treated as escapes.
  5025.  
  5026.  You convert FORTRAN strings to C strings by adding C immediately after a
  5027.  string constant. Do not insert commas or any other intervening punctuation,
  5028.  only spaces. Note that the length of the string increases by one byte
  5029.  because of the additional null byte. You need to allow for this when you
  5030.  declare string variables.
  5031.  
  5032.  The following FORTRAN example passes the address of a string to C. The
  5033.  string is in the C format.
  5034.  
  5035.             INTERFACE TO SUBROUTINE CONV [C] (S1)
  5036.             CHARACTER*5 S1 [REFERENCE]
  5037.             END
  5038.       C
  5039.             CHARACTER*5 S1
  5040.             S1 = 'abcd' C
  5041.             CALL CONV (S1)
  5042.  
  5043.  Note that an additional byte is allocated for S1, in consideration of the
  5044.  null byte added by the C-string conversion (done on the line above the
  5045.  call). Also note that the REFERENCE keyword was necessary because the C
  5046.  attribute in the first line changes the parameter-passing default to calling
  5047.  by value.
  5048.  
  5049.  FORTRAN and Pascal use the same fixed-length string types and can therefore
  5050.  easily pass strings between one another.
  5051.  
  5052.  FORTRAN modules should only pass fixed-length strings to Pascal. The Pascal
  5053.  routines, in turn, should expect to receive fixed-length strings. To specify
  5054.  a fixed-length string parameter in Pascal, you first need to declare a type,
  5055.  as in the example below.
  5056.  
  5057.       C     FORTRAN SOURCE CODE
  5058.       C
  5059.             INTERFACE TO SUBROUTINE PS (S1)
  5060.             CHARACTER*4 S1
  5061.             END
  5062.       C
  5063.             S1 = 'wxyz'
  5064.             CALL PS (S1)
  5065.             END
  5066.  
  5067.       { Pascal module }
  5068.  
  5069.       module Psmod;
  5070.       type stype4 = string(4);
  5071.       procedure ps (vars str1 : stype4);
  5072.  
  5073.  
  5074.  5.3  Handling Special Data Types
  5075.  
  5076.  Special types of data that are either structured (contain more than one
  5077.  field) or accessed externally need considerations beyond those already
  5078.  discussed. For example, not all languages index arrays in the same fashion.
  5079.  Custom structures created in one language may not interact properly with
  5080.  another language.
  5081.  
  5082.  
  5083.  5.3.1  Arrays
  5084.  
  5085.  When programming with more than one language, be aware of two special
  5086.  problems specific to arrays:
  5087.  
  5088.    1. Arrays are implemented differently in BASIC, so you must take special
  5089.       precautions when you pass an array from BASIC to FORTRAN.
  5090.  
  5091.    2. Arrays are declared and indexed differently in each language.
  5092.  
  5093.  This section considers each of these problems in turn.
  5094.  
  5095.  ───────────────────────────────────────────────────────────────────────────
  5096.  NOTE
  5097.     Arrays cannot be passed by value in C, unless declared within a
  5098.     structure. However, it is usually most efficient to pass arrays by
  5099.     reference.
  5100.  ───────────────────────────────────────────────────────────────────────────
  5101.  
  5102.  
  5103.  5.3.1.1  Cautions for Passing BASIC Arrays
  5104.  
  5105.  Most Microsoft languages permit you to reference arrays directly. In
  5106.  Microsoft FORTRAN, for example, an address name is equivalent to the address
  5107.  of the first element. This simple implementation is possible because the
  5108.  location of data for an array never changes.
  5109.  
  5110.  BASIC uses an "array descriptor," however, which is similar in some respects
  5111.  to a BASIC string descriptor. The array descriptor is necessary because
  5112.  BASIC may shift the location of array data in memory; BASIC handles memory
  5113.  allocation for arrays dynamically.
  5114.  
  5115.  FORTRAN does not have an equivalent to the BASIC array descriptor. More
  5116.  importantly, it lacks access to BASIC's space-management routines for
  5117.  arrays. Therefore, you may safely pass arrays from BASIC only if you follow
  5118.  these three rules:
  5119.  
  5120.    1. Pass the array's address by applying the VARPTR function to the first
  5121.       element of the array and passing the result by value. To pass the far
  5122.       address of the array, apply both the VARPTR and VARSEG functions and
  5123.       pass each result by value. The receiving language gets the address of
  5124.       the first element and considers it to be the address of the entire
  5125.       array. Arrays can then be accessed with the normal array-indexing
  5126.       syntax. The example below illus-trates how this works.
  5127.  
  5128.    2. The routine that receives the array must not, under any circumstances,
  5129.       make a call back to BASIC. If it does, then the location of the array
  5130.       data may change, and the address that was passed to the routine will
  5131.       become meaningless.
  5132.  
  5133.    3. BASIC may pass any member of an array by value. With this method, the
  5134.       above precautions do not apply.
  5135.  
  5136.  The following example demonstrates how a BASIC array can be passed to
  5137.  FORTRAN:
  5138.  
  5139.       REM   BASIC SOURCE FILE
  5140.       OPTION BASE 1
  5141.       DEFINT A-Z
  5142.       DIM A(20)
  5143.       DECLARE SUB ArrFix(BYVAL Addr AS INTEGER)
  5144.       .
  5145.       .
  5146.       .
  5147.       CALL ArrFix(VARPTR(A(1)))
  5148.       PRINT A(1)
  5149.       END
  5150.  
  5151.       C     FORTRAN SOURCE FILE
  5152.       C
  5153.             SUBROUTINE ARRFIX (ARR)
  5154.             INTEGER*2 ARR [NEAR] (20)
  5155.             ARR(1) = 5
  5156.             END
  5157.  
  5158.  In this example, BASIC considers that the argument passed is the near
  5159.  address of an array element. FORTRAN considers it to be the near address of
  5160.  the array itself. Both languages are correct.
  5161.  
  5162.  The parameter was declared BYVAL Addr AS INTEGER because a near (two-byte)
  5163.  address needed to be passed. If you wanted to pass a far (four-byte)
  5164.  address, then the proper code would be the following:
  5165.  
  5166.             DECLARE SUB ArrFix (BYVAL SegAddr AS INTEGER,
  5167.            + BYVAL Addr AS INTEGER)
  5168.             CALL ArrFix (VARSEG(A(0)), VARPTR(A(0)))
  5169.  
  5170.  The first field is the segment returned by VARSEG. If you use CDECL, then be
  5171.  sure to pass the offset address before the segment address, because CDECL
  5172.  causes parameters to be passed in reverse order:
  5173.  
  5174.             DECLARE SUB ArrFix CDECL (BYVAL Addr AS INTEGER,
  5175.            + BYVAL SegAddr AS INTEGER)
  5176.             CALL ArrFix(VARPTR(A((0)), VARSEG(A(0)))
  5177.  
  5178.  Note that you can apply LBOUND and UBOUND to a BASIC array to determine
  5179.  lower and upper bounds and then pass the results to another routine. This
  5180.  way, the size of the array does not need to be determined in advance.
  5181.  
  5182.  
  5183.  5.3.1.2  Array Declaration and Indexing
  5184.  
  5185.  Each language varies in the way that arrays are declared and indexed. Array
  5186.  indexing is purely a source-level consideration and involves no
  5187.  transformation of data. Following are the differences in the way elements
  5188.  are indexed by each language:
  5189.  
  5190.  Indexing Method                       Explanation
  5191.  
  5192.  Default lower boundary                By default, FORTRAN indexes the
  5193.                                        first element of an array as 1.
  5194.                                        BASIC and C index it as 0. Pascal
  5195.                                        lets the programmer begin
  5196.                                        indexing at any integer value.
  5197.                                        Recent versions of Microsoft
  5198.                                        FORTRAN also give you the option
  5199.                                        of specifying lower bounds at any
  5200.                                        integer values.
  5201.  
  5202.  Row-major order vs. column-major      Affects only arrays with more
  5203.  order                                 than one dimension. With
  5204.                                        row-major order used by C and
  5205.                                        Pascal, the rightmost dimension
  5206.                                        changes the fastest. With
  5207.                                        column-major order used by
  5208.                                        FORTRAN, and BASIC by default,
  5209.                                        the leftmost dimension changes
  5210.                                        the fastest. Thus, in Pascal the
  5211.                                        first four elements of array
  5212.                                        X(3,3)  are:
  5213.  
  5214.                                        X[1,1] X[1,2] X[1,3] X[2,1]
  5215.  
  5216.                                        In FORTRAN, the four elements
  5217.                                        are:
  5218.  
  5219.                                        X(1,1) X(2,1) X(3,1) X(1,2)
  5220.  
  5221.  The example above assumes that both the Pascal and FORTRAN arrays use lower
  5222.  bounds of 1. Table 5.2 shows equivalences for array declarations in each
  5223.  language. In this table, r is the number of elements of the row dimension
  5224.  (which changes more slowly), and c is the number of elements of the column
  5225.  dimension (which changes more quickly).
  5226.  
  5227.  Table 5.2  Equivalent Array Declarations
  5228.  
  5229.  Language          Array Declaration                   Comments
  5230.  
  5231.  FORTRAN           type x(c, r)                        With default lower
  5232.                                                        bounds of 1
  5233.  
  5234.  C                 type x[r][c]                        When passed by
  5235.                                                        reference
  5236.  
  5237.                    struct                              When passed by value
  5238.                    { type x[r][c];}x
  5239.  
  5240.  Pascal            x:array[a..a+r-1, b..b+c-1]         With default lower
  5241.                    of type                             bounds of 1
  5242.  
  5243.  BASIC             DIM x(c-1, r-1)                     With default lower
  5244.                                                        bounds of 0
  5245.  
  5246.  The declarations above extend to any number of dimensions. For example, the
  5247.  C declaration
  5248.  
  5249.       int arr1 [2][10][15][20]
  5250.  
  5251.  is equivalent to the FORTRAN declaration
  5252.  
  5253.             INTEGER*2 ARR1(20, 15, 10, 2)
  5254.  
  5255.  Each of the following describes the same place in memory for an array in the
  5256.  respective language:
  5257.  
  5258.       ARR1(9,3)          ! in FORTRAN, assuming lower bounds of 1
  5259.  
  5260.       arr1[2][8]         /* in C */
  5261.  
  5262.       Arr1[3,9]          {in Pascal, assuming lower bounds of 1}
  5263.  
  5264.       ARR1(8,2)          (in BASIC, assuming lower bounds of 0)
  5265.  
  5266.  When you compile BASIC with the BC command line, select the /R compile
  5267.  option, specifying that row-major rather than column-major order is to be
  5268.  used.
  5269.  
  5270.  ───────────────────────────────────────────────────────────────────────────
  5271.  NOTE
  5272.     The constants used in a C array declaration represent dimensions, not
  5273.     upper bounds, as they do in other languages. Therefore, the last element
  5274.     in the C array declared as  int arr[5][5] is not arr[5][5], but
  5275.     arr[4][4].
  5276.  ───────────────────────────────────────────────────────────────────────────
  5277.  
  5278.  
  5279.  5.3.2  Structures, Records, and User-Defined Types
  5280.  
  5281.  The C struct type, the BASIC user-defined type, the FORTRAN STRUCTURE type,
  5282.  and the Pascal record type are equivalent. Therefore, these data types can
  5283.  be passed between C, Pascal, FORTRAN, and BASIC.
  5284.  
  5285.  However, these types may be affected by the storage method. By default, C,
  5286.  FORTRAN, and Pascal use word alignment (unpacked storage) for all data
  5287.  except byte-sized objects and arrays of byte-sized objects. Figure 5.1
  5288.  shows the contrast between packed and unpacked storage.
  5289.  
  5290.  The unpacked storage method specifies that occasional bytes may be added
  5291.  as padding, so that the word and double-word objects start on an even
  5292.  boundary. In addition, all nested structures and records start on a word
  5293.  boundary.
  5294.  
  5295.  If a structure or record is being passed between a calling routine and the
  5296.  called routine, both routines must agree on a storage method. Otherwise,
  5297.  data will not be properly received. The simplest method for ensuring
  5298.  compatibility between all three languages is to turn on packing for C,
  5299.  FORTRAN, and Pascal modules. The packed storage method may sacrifice some
  5300.  speed, but it has the advantage of creating smaller executable files.
  5301.  
  5302.  The following example shows how FORTRAN can create a structure. This same
  5303.  structure appears in FGRAPH.FD, the graphics library include file that
  5304.  initializes the graphics routines. Several of these graphics routines use
  5305.  similar structures for holding coordinates or pieces of related information.
  5306.  
  5307.  Example
  5308.  
  5309.  An example of the xycoord structure is shown below.
  5310.  
  5311.             INTERFACE TO SUBROUTINE getcurrentposition
  5312.            + [FAR, C, ALIAS:"__f_getcurrentposition"](s)
  5313.             STRUCTURE/xycoord/
  5314.             INTEGER*2 xcoord ! This example creates a structure
  5315.             INTEGER*2 ycoord ! containing two INTEGER*2 values
  5316.             END STRUCTURE
  5317.             RECORD/xycoord/s
  5318.             END
  5319.  
  5320.  
  5321.  5.3.3  External Data
  5322.  
  5323.  You can always share data between FORTRAN and other languages by passing
  5324.  parameters. In the case of local variables and all BASIC variables, passing
  5325.  parameters is the only convenient way to share data.
  5326.  
  5327.  However, FORTRAN, C, and Pascal routines can access "external" data (data
  5328.  that can be directly accessed by any other module) directly. External refers
  5329.  to data that are both static and public──that is, data that you have stored
  5330.  in a specific place in memory (static data) and made publicly available to
  5331.  other modules. Compilers make a data object (variable, structure, or array)
  5332.  available by placing its name, along with size and type information, into
  5333.  the object file.
  5334.  
  5335.  External data can be defined in a FORTRAN, C, Pascal, or assembly module.
  5336.  Note that a data definition is distinct from an external declaration. A
  5337.  definition causes a compiler to create a data object; an external
  5338.  declaration informs a compiler that the object is to be found in another
  5339.  module.
  5340.  
  5341.  There are three requirements for programs that share external data between
  5342.  languages:
  5343.  
  5344.    1. One of the modules must define the static data.
  5345.  
  5346.       You can define a static data object in a FORTRAN or C module by
  5347.       defining a data object outside all functions and subroutines. (Do not
  5348.       use the static keyword in C with a data object you wish to be public.)
  5349.  
  5350.    2. The other modules that will access the data must declare the data as
  5351.       external.
  5352.  
  5353.       In FORTRAN and Pascal, you can declare data as external by adding the
  5354.       EXTERN attribute to the data declaration. In C, you can declare data as
  5355.       external by using an extern declaration, similar to the extern
  5356.       declaration for functions.
  5357.  
  5358.    3. Naming-convention differences must be resolved.
  5359.  
  5360.       In FORTRAN and Pascal, you can adopt the C naming convention by
  5361.       applying the C attribute to the data declaration. Likewise in C, you
  5362.       can adopt the FORTRAN/Pascal/BASIC naming convention by applying
  5363.       fortran or pascal to the data declaration.
  5364.  
  5365.  
  5366.  Examples
  5367.  
  5368.  The examples below illustrate the general language features of external data
  5369.  described above.
  5370.  
  5371.       /* C source code */
  5372.  
  5373.       int        thing1;         /* Thing1 is public and static */
  5374.       extern     int thing2;     /* Thing2 is defined in another module */
  5375.       static     int thing3;     /* Thing3 is static, but not public */
  5376.  
  5377.       ctest()
  5378.       {
  5379.       .
  5380.       .
  5381.       .
  5382.       C     FORTRAN SOURCE CODE
  5383.       C
  5384.             INTEGER*2 THING1 [C, EXTERN]
  5385.             INTEGER*2 THING2 [C]
  5386.       C
  5387.       C     THING1 DEFINED IN ANOTHER MODULE, USING C CONVENTION (_thing1)
  5388.       C
  5389.       C     THING2 DEFINED HERE, USING C CONVENTION (_thing2)
  5390.       .
  5391.       .
  5392.       .
  5393.  
  5394.       { Pascal source code }
  5395.  
  5396.       module Ptest;
  5397.        procedure Test;
  5398.           var
  5399.              thing1 [C, EXTERN] : integer; { Both vars defined elsewhere }
  5400.              thing2 [C, EXTERN] : integer; { and use C naming convention }
  5401.       .
  5402.       .
  5403.       .
  5404.  
  5405.  In these examples, the variables thing1  and thing2  are defined and
  5406.  declared with the C naming convention so they will be placed into each
  5407.  object file as _thing1  and _thing2. However, you can specify the FORTRAN/
  5408.  Pascal/BASIC naming convention by using the following C statements:
  5409.  
  5410.       int        fortran  thing1;
  5411.       extern     int  fortran thing2;
  5412.  
  5413.  The C attribute can then be dropped from the FORTRAN and Pascal source code.
  5414.  Each object file will contain the names THING1  and THING2.
  5415.  
  5416.  
  5417.  5.3.4  Pointers and Address Variables
  5418.  
  5419.  Rather than pass data directly, you may want to pass the address of a piece
  5420.  of data. Passing the address is equivalent to passing the data by reference.
  5421.  In some cases, such as BASIC arrays (see Section 5.3.1.1), passing an
  5422.  address is the only way to share particular kinds of data between two
  5423.  languages.
  5424.  
  5425.  Unlike Pascal and C, FORTRAN does not have formal address types. How-ever,
  5426.  FORTRAN does provide ways for storing and passing addresses.
  5427.  
  5428.  FORTRAN programs determine near and far addresses with the LOC, LOCFAR, and
  5429.  LOCNEAR functions. You store the result as INTEGER*2 (with LOCNEAR) or as
  5430.  INTEGER*4 (with LOCFAR). LOC has the same purpose as LOCNEAR in the medium
  5431.  memory and as LOCFAR in the large memory model.
  5432.  
  5433.  If you pass the result of LOC, LOCNEAR, or LOCFAR to another language, be
  5434.  sure to pass by value.
  5435.  
  5436.  
  5437.  5.3.5  Common Blocks
  5438.  
  5439.  You can pass individual members of a FORTRAN or BASIC common block in an
  5440.  argument list just as you can with any data. However, you can also give a
  5441.  different-language module access to the entire common block at once.
  5442.  
  5443.  Pascal and C modules can reference the items of a common block by first
  5444.  declaring a structure or record, with fields that correspond to the common
  5445.  block variables (see Section 5.3.5.1 below). BASIC modules also employ a
  5446.  user-defined type to access the fields of a FORTRAN common block.
  5447.  
  5448.  Having defined a structure, record, or user-defined type with the
  5449.  appropriate fields, the Pascal or C module must then connect with the common
  5450.  block itself. The next two sections present methods for gaining access to
  5451.  common blocks.
  5452.  
  5453.  
  5454.  5.3.5.1  Passing the Address of the Common Block
  5455.  
  5456.  To pass the address of a common block, simply pass the address of the first
  5457.  variable in the block (that is, pass the first variable by reference.) The
  5458.  receiving C or Pascal module should expect to receive a structure or record
  5459.  by reference.
  5460.  
  5461.  Example
  5462.  
  5463.  In the example below, the C function initcb  receives the address of the
  5464.  variable N, which it considers to be a pointer to a structure with three
  5465.  fields:
  5466.  
  5467.       C     FORTRAN SOURCE CODE
  5468.       C
  5469.             COMMON /CBLOCK/N,X,Y
  5470.             INTEGER*2 N
  5471.             REAL*8 X,Y
  5472.       .
  5473.       .
  5474.       .
  5475.             CALL INITCB(N)
  5476.       .
  5477.       .
  5478.       .
  5479.       /* C source code */
  5480.  
  5481.       struct block_type {
  5482.                int     n;
  5483.                double  x;
  5484.                double  y;
  5485.       };
  5486.  
  5487.       initcb(block_hed)
  5488.       struct block_type *block_hed;
  5489.       {
  5490.                block_hed->n = 1;
  5491.                block_hed->x = 10.0;
  5492.                block_hed->y = 20.0;
  5493.       }
  5494.  
  5495.  
  5496.  5.3.5.2  Accessing Common Blocks Directly
  5497.  
  5498.  You can access FORTRAN common blocks directly by defining a structure (or
  5499.  record in Pascal) with the appropriate fields and then using the methods
  5500.  described in Section 5.3.3, "External Data."
  5501.  
  5502.  
  5503.  Example
  5504.  
  5505.  The example below declares cblock as an external structure. You can
  5506.  reference the individual fields of cblock which will correspond to those of
  5507.  the common block CBLOCK  in the FORTRAN source file.
  5508.  
  5509.       struct block_type {
  5510.                int     n;
  5511.                double  x;
  5512.                double  y;
  5513.       };
  5514.  
  5515.       extern struct block_type fortran cblock;
  5516.  
  5517.  
  5518.  5.3.6  Using a Varying Number of Parameters
  5519.  
  5520.  Some C functions, most notably printf, can be called with a different number
  5521.  of arguments each time. To call such a function from FORTRAN, you need to
  5522.  sup-press the type checking that normally forces a call to be made with a
  5523.  fixed number of parameters. You can call such routines with a variable
  5524.  number of parameters by including the VARYING attribute in your interface to
  5525.  the routine, along with the C attribute. You must use the C attribute
  5526.  because a variable number of parameters is only feasible with the C calling
  5527.  convention.
  5528.  
  5529.  The VARYING attribute prevents FORTRAN from enforcing a matching number of
  5530.  parameters. Each time you call the routine, you will be able to pass more or
  5531.  fewer parameters than are declared in the interface to the routine. However,
  5532.  each actual parameter that you pass will be type checked against whatever
  5533.  formal parameters you have declared in the interface. FORTRAN compares the
  5534.  type of the first actual parameter to the first formal parameter (if any),
  5535.  the second actual parameter to the second formal parameter, and so on.
  5536.  
  5537.  Because the number of parameters is not fixed, the routine you call should
  5538.  have some mechanism for determining how many parameters to expect. Often
  5539.  this information is indicated by the first parameter. For example, the C
  5540.  function printf scans the format string passed as the first parameter. The
  5541.  number of fields in the format string determines how many additional
  5542.  parameters the function should expect.
  5543.  
  5544.  Example
  5545.  
  5546.  The example below demonstrates the use of the VARYING attribute to call
  5547.  printf directly from FORTRAN (the program needs to be compiled and linked to
  5548.  the C large memory model so that printf is linked in).
  5549.  
  5550.             INTERFACE TO INTEGER*2 FUNCTION printf [C, VARYING] ()
  5551.             END
  5552.  
  5553.             CHARACTER*30 str1, str2
  5554.             INTEGER*2 n, printf
  5555.             str1 = 'This is %s string, number %d.'C
  5556.             str2 = 'formatted'C
  5557.             n = 1
  5558.             n = printf(LOC(str1), LOC(str2), n)
  5559.             END
  5560.  
  5561.  In FORTRAN, you can write the interface to printf so that the format string
  5562.  can be of varying lengths, by using the LOC feature.
  5563.  
  5564.  
  5565.  Chapter 6  Record Structures: File Formats and Access
  5566.  ───────────────────────────────────────────────────────────────────────────
  5567.  
  5568.  This chapter describes the record structures (structure of files) created by
  5569.  Microsoft FORTRAN. The data format (or "form") and file access type define a
  5570.  "record structure." Each record structure has its own advantages, and
  5571.  depending on the application you have in mind, you may find that the ease of
  5572.  use of one type is more important than the greater speed or compact size of
  5573.  another.
  5574.  
  5575.  If you want more general information about FORTRAN input/output and file
  5576.  access, see Chapter 3, "The Input-Output System," in the Microsoft FORTRAN
  5577.  Reference.
  5578.  
  5579.  
  5580.  6.1  Understanding Structures: Forms and Access Modes
  5581.  
  5582.  A "record" refers to one entry in a data file. All of the records within a
  5583.  single data file use the same method for storing information. Possible
  5584.  methods are:
  5585.  
  5586.    ■  Formatted
  5587.    ■  Unformatted
  5588.    ■  Binary
  5589.  
  5590.  You can send and retrieve information from a data file in one of two "access
  5591.  modes":
  5592.  
  5593.    ■  Sequential
  5594.    ■  Direct
  5595.  
  5596.  You can access sequential data one record after the other; direct data can
  5597.  be accessed by specifying which record in the file you want. Altogether, six
  5598.  record structures are possible: formatted sequential, formatted direct,
  5599.  unformatted sequential, unformatted direct, binary sequential, and binary
  5600.  direct. The following sections discuss each of these record structures in
  5601.  detail.
  5602.  
  5603.  
  5604.  6.2  Using Formatted Records
  5605.  
  5606.  Formatted files are those files opened with FORM='FORMATTED'. They consist
  5607.  of a series of formatted records of ASCII characters. Each record ends with
  5608.  ASCII carriage-return (CR) and line-feed (LF) characters. If you are not
  5609.  concerned about compact size or high-speed data writing and retrieval,
  5610.  formatted files are typically the easiest structure to use. All internal
  5611.  files (character substrings, character variables, character array elements,
  5612.  character arrays, or noncharacter arrays) must be formatted.
  5613.  
  5614.  
  5615.  6.2.1  Formatted Sequential Records
  5616.  
  5617.  A formatted sequential file is a series of formatted records written and
  5618.  read sequentially. Records may vary in length and may be empty, as shown in
  5619.  Figure 6.1.
  5620.  
  5621.  The following program fragment creates the formatted sequential file shown in
  5622.  Figure 6.2:
  5623.  
  5624.             I=4
  5625.             OPEN (33, FILE='FSEQ')
  5626.       C     (FORMATTED SEQUENTIAL BY DEFAULT)
  5627.             WRITE (33, '(A,I3)') 'RECORD', I/3
  5628.  
  5629.             WRITE (33, '()')
  5630.             WRITE (33, '(11HThe 3rd One)')
  5631.             CLOSE (33)
  5632.             END
  5633.  
  5634.  
  5635.  6.2.2  Formatted Direct Records
  5636.  
  5637.  In a formatted direct file, all of the records are exactly the same length
  5638.  and may be written or read in any order. The record length equals the length
  5639.  specified in the RECL= specifier, plus two bytes for the carriage-return
  5640.  (CR) and line-feed (LF) characters that serve as record separators. Prior to
  5641.  writing the record, these bytes are all undefined.
  5642.  
  5643.  If data does not completely fill a record, the compiler pads the remaining
  5644.  portion of the record with blank spaces. The blanks ensure that the file
  5645.  contains only completely filled records, all of the same length.
  5646.  
  5647.  The following program fragment creates the sample formatted direct file
  5648.  shown in Figure 6.3:
  5649.  
  5650.             OPEN (33, FILE='FDIR',FORM='FORMATTED',
  5651.            + ACCESS='DIRECT',RECL=10)
  5652.             WRITE (33, '(A)', REC=1) 'RECORD ONE'
  5653.  
  5654.             WRITE (33, '(I5)', REC=3) 30303
  5655.             CLOSE (33)
  5656.             END
  5657.  
  5658.  
  5659.  6.3  Using Unformatted Records
  5660.  
  5661.  An unformatted file (FORM='UNFORMATTED') is a series of records composed of
  5662.  "physical blocks" as described below. Each record contains a sequence of
  5663.  values. The lack of formatting makes files of this type more compact than
  5664.  files that store the same information in a formatted form. Access is also
  5665.  faster than with formatted files.
  5666.  
  5667.  
  5668.  6.3.1  Unformatted Sequential Records
  5669.  
  5670.  Unformatted sequential files must access data sequentially. Records may vary
  5671.  in length.
  5672.  
  5673.  Unformatted sequential files are organized in "chunks" of 130 bytes or less
  5674.  called "physical blocks." Each physical block consists of the data you send
  5675.  to the file (up to 128 bytes) plus two one-byte "length bytes" inserted by
  5676.  the compiler. The length bytes indicate the actual amount of data present.
  5677.  
  5678.  Figure 6.4 shows the physical block structure; each "L" represents a length
  5679.  byte.
  5680.  
  5681.  A "logical record" refers to an unformatted record, which contains one or
  5682.  more physical blocks (see Figure 6.5). Logical records can be as big as you
  5683.  like; the compiler will use as many physical blocks as necessary.
  5684.  
  5685.  When you create a logical record consisting of more than one physical block,
  5686.  the compiler sets the length byte to 129 to indicate that the data in the
  5687.  current physical block continues on into the next physical block. Then the
  5688.  length of the data portion of the last physical block in the record has a
  5689.  length (in bytes) of
  5690.  
  5691.       MOD (length, 128)
  5692.  
  5693.  where length equals the total data length in that logical record. (MOD is
  5694.  the remainder intrinsic function.) For example, if you write 140 bytes of
  5695.  data, the logical record has the structure shown in Figure 6.5.
  5696.  
  5697.  The first and last bytes in an unformatted sequential file are reserved;
  5698.  the first contains a value of 75, and the last holds a value of 130.
  5699.  FORTRAN uses these bytes for error checking and end-of-file references.
  5700.  Figure 6.6 illustrates these bytes in a sample unformatted sequential file.
  5701.  
  5702.  The following program fragment creates the unformatted sequential file shown
  5703.  in Figure 6.6:
  5704.  
  5705.             CHARACTER XYZ(3)
  5706.             INTEGER*4 IDATA (35)
  5707.             DATA IDATA /35 * -1/, XYZ /'x', 'y', 'z'/
  5708.       C
  5709.       C     (-1 IS REPRESENTED BY FF FF FF FF HEXADECIMAL)
  5710.       C
  5711.             OPEN (33, FILE='UFSEQ',FORM='UNFORMATTED')
  5712.  
  5713.       C     SEQUENTIAL BY DEFAULT)
  5714.       C
  5715.       C     WRITE OUT A 140-BYTE RECORD (128 AND THEN 12 MORE)
  5716.       C     FOLLOWED BY A 3-BYTE RECORD
  5717.  
  5718.             WRITE (33) IDATA
  5719.             WRITE (33) XYZ
  5720.             CLOSE (33)
  5721.             END
  5722.  
  5723.  
  5724.  6.3.2  Unformatted Direct Records
  5725.  
  5726.  An unformatted direct file is a series of unformatted records. You can write
  5727.  or read the records in any order you choose. All records have the same
  5728.  length, given by the RECL= specifier. No delimiting bytes separate records
  5729.  or otherwise indicate record structure.
  5730.  
  5731.  You can write a partial record to an unformatted direct file. Version 5.0 of
  5732.  Microsoft FORTRAN pads these records to the fixed record length with ASCII
  5733.  NUL characters; in files created by versions of FORTRAN prior to 4.0, random
  5734.  values may be used to pad records. Unwritten records in the file contain
  5735.  undefined data, as shown in the sample unformatted direct file in Figure
  5736.  6.7.
  5737.  
  5738.  The following program fragment creates the sample unformatted direct file
  5739.  shown in Figure 6.7:
  5740.  
  5741.             OPEN (33, FILE='UFDIR', RECL=10,
  5742.            + FORM = 'UNFORMATTED', ACCESS = 'DIRECT')
  5743.             WRITE (33, REC=3) .TRUE., 'abcdef'
  5744.             WRITE (33, REC=1) 2049
  5745.             CLOSE (33)
  5746.             END
  5747.  
  5748.  
  5749.  6.4  Using Binary Records
  5750.  
  5751.  Specifying FORM='BINARY' is particularly useful when a FORTRAN program reads
  5752.  a file created by a program written in another language. Usually, such files
  5753.  do not have an internal structure or a file structure that corresponds to
  5754.  one of the standard FORTRAN file structures. Additionally, binary files are
  5755.  compact; if you store large amounts of data, consider a binary file format.
  5756.  
  5757.  
  5758.  6.4.1  Binary Sequential Records
  5759.  
  5760.  A binary sequential file is a series of values written and read in the same
  5761.  order, and stored as binary numbers. No discernible record boundaries exist,
  5762.  and no special bytes indicate file structure. Data are read and written
  5763.  without changes in form or length. For any I/O list item, the sequence of
  5764.  bytes in memory is the sequence of bytes in the file (see Figure 6.8
  5765.  below).
  5766.  
  5767.  
  5768.  The following program creates the sample binary sequential file shown in
  5769.  Figure 6.8:
  5770.  
  5771.       $STORAGE:4
  5772.             INTEGER*1 BELLS(4)
  5773.             INTEGER IWYS(3)
  5774.             CHARACTER*4 CVAR
  5775.             DATA BELLS /4*7/
  5776.             DATA CVAR /' is '/,IWYS/'What',' you',' see'/
  5777.  
  5778.       C     THIS PROGRAM WRITES THE SENTENCE
  5779.       C     'What you see is what you get!'
  5780.       C     FOLLOWED BY FOUR BELL CHARACTERS (07 HEXADECIMAL)
  5781.  
  5782.             OPEN (33, FILE='BSEQ',FORM='BINARY')
  5783.  
  5784.       C     (SEQUENTIAL BY DEFAULT)
  5785.  
  5786.             WRITE (33) IWYS, CVAR
  5787.             WRITE (33) 'what ', 'you get!'
  5788.             WRITE (33) BELLS
  5789.             CLOSE (33)
  5790.             END
  5791.  
  5792.  
  5793.  6.4.2  Binary Direct Records
  5794.  
  5795.  A binary direct file stores records as a series of binary numbers,
  5796.  accessible in any order. Each record in the file has the same length, as
  5797.  specified by the RECL= argument to the OPEN statement.
  5798.  
  5799.  You can write partial records to binary direct files; any unused portion of
  5800.  the record will contain undefined data.
  5801.  
  5802.  A single read or write operation can transfer more data than a record
  5803.  contains by continuing the operation into the next record(s) of the file.
  5804.  Performing such an operation on an unformatted direct file would cause an
  5805.  error. Valid I/O operations for unformatted direct files produce identical
  5806.  results when they are performed on binary direct files, provided the
  5807.  operations do not depend on zero padding in partial records (see Figure
  5808.  6.9 below).
  5809.  
  5810.  The following program fragment creates the sample binary direct file
  5811.  shown in Figure 6.9:
  5812.  
  5813.       $STORAGE:4
  5814.             OPEN (33, FILE='BDIR',RECL=10,
  5815.            + FORM='BINARY',ACCESS='DIRECT')
  5816.             WRITE (33, REC=1) 'abcdefghijklmno'
  5817.             WRITE (33) 4,5
  5818.             WRITE (33,REC=40) 'pq'
  5819.             CLOSE (33)
  5820.             END
  5821.  
  5822.  
  5823.  Chapter 7  Optimizing Programs
  5824.  
  5825.  ───────────────────────────────────────────────────────────────────────────
  5826.  
  5827.  This chapter discusses techniques for creating smaller and faster executable
  5828.  files with the Microsoft FORTRAN Compiler. Although some of these ideas
  5829.  apply to only a particular class of programs, others are general coding
  5830.  practices that can be used in virtually all programs.
  5831.  
  5832.  The topics covered include program structure and compiler options that
  5833.  improve the compiler's efficiency; coding strategies that decrease the size
  5834.  of data files created by a program; linking and memory usage strategies;
  5835.  conditions for using integer versus real variables; and the efficient use of
  5836.  arrays.
  5837.  
  5838.  
  5839.  7.1  Compiling and Linking Strategies
  5840.  
  5841.  The various FORTRAN compiling and linking options enhance program control
  5842.  and debugging, but some of these options provide this control at the expense
  5843.  of size and speed. With a few judicious choices, you can shrink the size of
  5844.  your program files and sometimes increase their execution speed. The
  5845.  following sections cover the compiling and linking options that reduce the
  5846.  size of executable files and increase their speed.
  5847.  
  5848.  
  5849.  7.1.1  Using Debugging and Integer-Size Options
  5850.  
  5851.  Three FL command-line options can significantly affect the amount of memory
  5852.  your source program requires: the /4Yb (debug), /Zi (CodeView debugging),
  5853.  and /4I2 (integer-size) options.
  5854.  
  5855.  ───────────────────────────────────────────────────────────────────────────
  5856.  NOTE
  5857.     The /4Yb and /4I2 options correspond to the $DEBUG and $STORAGE:2
  5858.     metacommands, respectively, and have the same effects.
  5859.  ───────────────────────────────────────────────────────────────────────────
  5860.  
  5861.  A program that includes the information generated by the debug option can
  5862.  contain up to 40 percent more code than the same program without the
  5863.  debugging information. After you successfully compile, link, and run a
  5864.  program, you can reduce its size and improve its execution speed by
  5865.  recompiling without the /4Yb option (or by removing the $DEBUG metacommands
  5866.  and recompiling).
  5867.  
  5868.  Similarly, the /Zi option prepares the code for debugging with the CodeView
  5869.  debugger. It produces an object file containing full symbolic debugging
  5870.  information──including the symbol table and line numbers──for use with the
  5871.  Microsoft CodeView window-oriented debugger. If you completed debugging with
  5872.  the CodeView debugger, you can reduce the file size by recompiling the
  5873.  finished program without the /Zi option.
  5874.  
  5875.  If your program does not require four bytes of storage for INTEGER and
  5876.  LOGICAL variables (that is, you do not explicitly need long integers or
  5877.  logicals), you can include the /4I2 option at compile time to reduce the
  5878.  size of gen-erated code. This option allocates two bytes (instead of four,
  5879.  the default) for each INTEGER and LOGICAL variable that you declare without
  5880.  an explicit length specification. This allocation shrinks program size
  5881.  because two-byte arithmetic operations require less supporting code than
  5882.  four-byte operations.
  5883.  
  5884.  The $DEBUG and $STORAGE metacommands are discussed in Chapter 6 in the
  5885.  Microsoft FORTRAN Reference.
  5886.  
  5887.  
  5888.  7.1.2  Using 8087/287/387 Math Options
  5889.  
  5890.  When you compile your program, you can specify a floating-point option that
  5891.  selects the math package the program will use and the default library for
  5892.  linking. If you have an 8087, 80287, or 80387 math coprocessor, you can
  5893.  choose the /FPi87 or /FPc87 option, both of which generate instructions in
  5894.  your executable file for the coprocessor. If you link with a library that
  5895.  supports 8087/287/387 coprocessors (LLIBFOR7.LIB or MLIBFOR7.LIB), the
  5896.  resulting executable files will be smaller than executable files resulting
  5897.  from other math options. The math coprocessor also speeds up programs which
  5898.  make extensive use of floating-point calculations.
  5899.  
  5900.  Software emulation of the floating-point processors adds to the program's
  5901.  size. You may reduce the size of executable files by as much as 7K by
  5902.  choosing one of these coprocessor options. See Chapter 1, "Controlling
  5903.  Floating-Point Operations," for more information.
  5904.  
  5905.  
  5906.  7.1.3  Using Overlays
  5907.  
  5908.  At link time, specifying appropriate program modules as overlays reduces
  5909.  file size. An overlay refers to two or more modules that use the same memory
  5910.  space when they execute. For example, assume two different modules, A and
  5911.  B, both contain routines needed by a main program (see Figure 7.1). If the
  5912.  main program calls a routine in module A, the program loads A from the
  5913.  disk into a particular space in memory. If the program later calls a routine
  5914.  in module B, the program loads module B into the same space previously
  5915.  occupied by module A.
  5916.  
  5917.  The program loads overlaid modules into the same memory space only when (and
  5918.  if) they are needed. In general, programs that use overlays are smaller and
  5919.  require less memory than programs that do not. However, programs that use
  5920.  overlays may run more slowly because of the additional time needed to read
  5921.  and reread the overlay code from disk into memory. (See Chapter 7 in the
  5922.  Microsoft FORTRAN Reference for more information about overlays.)
  5923.  
  5924.  
  5925.  7.2  Coding Strategies
  5926.  
  5927.  The manner in which you write a program can dramatically affect both its
  5928.  speed and its size. The types and sizes of files, variables, and arrays you
  5929.  create──and how efficiently you use them──can enhance or detract from your
  5930.  program's performance.
  5931.  
  5932.  The following sections describe ways in which you can write source code to
  5933.  minimize the amount of data space the compiler needs and to minimize the
  5934.  object and executable file sizes.
  5935.  
  5936.  
  5937.  7.2.1  Removing Error-Message Text during SETUP
  5938.  
  5939.  SETUP gives you two options for handling error messages: to build a library
  5940.  that displays the entire error message (the default) or a library that
  5941.  displays only the number of the error message, which you can then look up in
  5942.  Appendix D of the Microsoft FORTRAN Reference. Using a library without the
  5943.  error-message text results in an executable file approximately 2K smaller
  5944.  than the default.
  5945.  
  5946.  
  5947.  7.2.2  Using Consistent File-Access and Format Types
  5948.  
  5949.  Each file format (formatted, unformatted, or binary) and access type
  5950.  (sequential or direct) requires that the compiler incorporate specific
  5951.  supporting code in your program. If the design of your program permits, try
  5952.  to restrict file access to the smallest number of access types and formats.
  5953.  
  5954.  
  5955.  7.2.3  Specifying Edit Lists
  5956.  
  5957.  The edit lists you specify for I/O statements significantly affect the
  5958.  number of run-time routines supporting your program. If you remove
  5959.  formatting information or reference the same specifier for multiple calls,
  5960.  such as three WRITE statements referencing the same FORMAT statement, you
  5961.  decrease the space of your program. The following sections offer specific
  5962.  hints for reducing code size.
  5963.  
  5964.  
  5965.  7.2.3.1  Left Tabbing
  5966.  
  5967.  The TL edit descriptor (or using the T edit descriptor to do left tabbing)
  5968.  increases the size of your executable files. The run-time code used to
  5969.  support left tabbing is included whenever the compiler detects the explicit
  5970.  use of these edit descriptors, or when a variable is used to contain the
  5971.  format string using the descriptor. As a result, you can reduce the size of
  5972.  your executable files if you avoid using left tabbing whenever possible.
  5973.  (See Chapter 3 of the Microsoft FORTRAN Reference for a description of the
  5974.  TL and T edit descriptors.)
  5975.  
  5976.  
  5977.  7.2.3.2  Formatted or List-Directed I/O
  5978.  
  5979.  You will create smaller executable files if you consistently use either
  5980.  formatted or list-directed I/O statements and avoid mixing the two. This
  5981.  will require fewer run-time routines to support your program and therefore
  5982.  decrease its size.
  5983.  
  5984.  
  5985.  7.2.3.3  Character Variables as Format Specifiers
  5986.  
  5987.  Microsoft FORTRAN translates format strings into a more compact internal
  5988.  form wherever possible. However, if the format is specified as a character
  5989.  vari-able, this translation must occur at run time instead of compile time.
  5990.  The associated run-time code for this adds significantly to the size of the
  5991.  executable file. As a result, you create smaller executable files if you use
  5992.  character constants or FORMAT statements as format specifiers. (See Chapter
  5993.  3 of the Microsoft FORTRAN Reference for a description of these
  5994.  alternatives.)
  5995.  
  5996.  
  5997.  7.2.4  Using the BLOCKSIZE Option
  5998.  
  5999.  Using the BLOCKSIZE option in OPEN statements allows you to choose an
  6000.  appropriate trade-off between execution speed and memory requirements for
  6001.  your program.
  6002.  
  6003.  The BLOCKSIZE option gives you control over the size of the internal buffer
  6004.  associated with each file your program opens. This buffer is designed to
  6005.  speed up execution time when your program reads or writes a large number of
  6006.  small items to a file. By default, the run-time system assigns a buffer size
  6007.  of 1,024 bytes for sequential-access files. However, you can use the
  6008.  BLOCKSIZE option to allocate a buffer of a different size.
  6009.  
  6010.  Using the BLOCKSIZE option gives you the following trade-off between program
  6011.  speed and memory requirements:
  6012.  
  6013.    ■  Larger buffer sizes speed up I/O operations but increase the amount of
  6014.       memory allocated for these operations.
  6015.  
  6016.    ■  Smaller buffer sizes result in slower I/O, but they save memory for
  6017.       other purposes.
  6018.  
  6019.  Since the buffers are only allocated when the file is opened, using the
  6020.  option BLOCKSIZE will not affect the size of the program's executable file.
  6021.  However, as a program approaches the memory limits of the machine, a smaller
  6022.  buffer size might allow the program to stay within those limits.
  6023.  
  6024.  The value that you specify for the BLOCKSIZE option only indirectly
  6025.  determines the buffer. The value is rounded up to a multiple of 512 for a
  6026.  sequential-access file for performance reasons. DOS normally formats disks
  6027.  into 512-byte sectors and performs I/O operations to and from disk files in
  6028.  accordance with these sector boundaries. Therefore, the most efficient I/O
  6029.  occurs when the buffer size is also a multiple of 512 for sequential-access
  6030.  files. (See Chapter 3 of the  Microsoft FORTRAN Reference for an explanation
  6031.  of the rules for determining the actual buffer sizes of direct-access and
  6032.  terminal files.)
  6033.  
  6034.  Therefore, if you specify BLOCKSIZE = 1800  when you open a sequential file,
  6035.  the actual buffer size will be the next multiple of 512 not less than 1,800,
  6036.  or 2,048 (4 * 512). BLOCKSIZE will support buffers up to a maximum of 32,256
  6037.  bytes; any values passed to BLOCKSIZE larger than this will result in a
  6038.  buffer of 32,256 bytes.
  6039.  
  6040.  
  6041.  7.2.5  Using Integer and Real Variables
  6042.  
  6043.  Although most FORTRAN programs use both floating-point and integer data,
  6044.  programs that use only integer data are considerably smaller than programs
  6045.  that use floating-point data. Remember, too, that in some situations you can
  6046.  use integers in place of floating-point numbers. Depending on the situation,
  6047.  you may be able to multiply your numbers by a known factor to convert them
  6048.  to integers, perform any manipulations, and convert them back for final
  6049.  printing.
  6050.  
  6051.  If you write a program that uses only integer data (for example, a program
  6052.  that prints out the time but does nothing else), remember either to
  6053.  explicitly declare variables with type INTEGER, or to use variable names
  6054.  that begin with letters that default to INTEGER type. By default, these are
  6055.  the letters "I" through "N." Use the IMPLICIT statement to specify different
  6056.  default letters for each type. (See Chapter 4 of the Microsoft FORTRAN
  6057.  Reference for more information.)
  6058.  
  6059.  
  6060.  7.2.6  Using Arrays and EQUIVALENCE Statements
  6061.  
  6062.  The ways in which you declare arrays and use them in EQUIVALENCE statements
  6063.  can significantly affect the amount of information needed to compile your
  6064.  program. The use of arrays may affect whether the compiler runs out of
  6065.  memory when processing your source files. The fewer assumptions the compiler
  6066.  must make about the types and uses of arrays, the more efficient the
  6067.  compilation.
  6068.  
  6069.  The following sections offer suggestions for using arrays in ways that
  6070.  minimize the amount of data the compiler requires.
  6071.  
  6072.  
  6073.  7.2.6.1  Minimizing Constant Use in Array Declarations
  6074.  
  6075.  If possible, minimize the number of different constants you use in array
  6076.  declarations. Also, place array declarations that use the most constants
  6077.  first. These actions improve efficiency during compilation because the
  6078.  compiler saves copies of the constants and reuses the copies, if possible.
  6079.  
  6080.  The two examples below illustrate this. You compile the declarations shown
  6081.  in the first example more efficiently by declaring the variables X, Y, and Z
  6082.  with the same bounds, as shown in the second example:
  6083.  
  6084.             INTEGER X(11), Y(10), Z(11)
  6085.  
  6086.             INTEGER X(11), Y(11), Z(11)
  6087.  
  6088.  If it is necessary to declare array Y with a bound of 10, the program would
  6089.  compile more efficiently by placing the declarations of X and Z──which have
  6090.  the same constant bounds──first, as in the example below:
  6091.  
  6092.             INTEGER X(11), Z(11)
  6093.  
  6094.             INTEGER Y(10)
  6095.  
  6096.  
  6097.  7.2.6.2  Minimizing Items Declared in Each Type Statement
  6098.  
  6099.  Declare as few items as possible in each type statement. This reduces the
  6100.  complexity of each declaration and, as a result, saves the compiler data
  6101.  space when processing each declaration. This technique has an especially
  6102.  significant effect for array declarations.
  6103.  
  6104.  
  6105.  7.2.6.3  Declaring Array Types before Dimensioning
  6106.  
  6107.  Explicitly declare an array's type before you dimension it. Also, before you
  6108.  use arrays in EQUIVALENCE statements, make sure that each array in the
  6109.  statement list has been completely declared, dimensioned, and (if necessary)
  6110.  declared in a COMMON statement.
  6111.  
  6112.  The examples below show how to declare the array A to use memory most
  6113.  efficiently during compilation.
  6114.  
  6115.             INTEGER A(10,20)
  6116.  
  6117.             INTEGER A
  6118.             DIMENSION A(10,20)
  6119.  
  6120.             INTEGER A
  6121.             COMMON A(10,20)
  6122.  
  6123.  In the declarations shown below, the compiler requires extra data space
  6124.  because the type of the array X is not given before X is used in the
  6125.  EQUIVALENCE statement.
  6126.  
  6127.             DIM X(20)
  6128.             EQUIVALENCE (X(1), J)
  6129.             INTEGER X
  6130.  
  6131.  In the following declarations, the compiler requires extra data space
  6132.  because it cannot determine the types of A and B until it has processed
  6133.  the second line; it does not know that B is an array until it has processed
  6134.  the second line, and it does not know that A and B are in a common block
  6135.  until it has processed the third line:
  6136.  
  6137.             EQUIVALENCE (A(10,20), B)
  6138.             INTEGER A, B(20,30)
  6139.             COMMON /CBA/A, /CBB/B
  6140.  
  6141.  In each case, the compiler must make assumptions that increase the amount of
  6142.  processing and the amount of data space it needs to hold intermediate
  6143.  processing results. To improve efficiency, rewrite the declarations as
  6144.  follows:
  6145.  
  6146.             INTEGER A(10,20), B(20,30)
  6147.             COMMON /CBA/A, /CBB/B
  6148.             EQUIVALENCE (A(10,20), B(1,1))
  6149.  
  6150.  In this series of declarations, the compiler knows immediately that A and B
  6151.  refer to two-dimensional integer arrays and the size of each. The subsequent
  6152.  references to A and B leave no ambiguities for the compiler.
  6153.  
  6154.  
  6155.  ───────────────────────────────────────────────────────────────────────────
  6156.  
  6157.  Part 2  The Microsoft FORTRAN Graphics Library
  6158.  
  6159.  Part 2 introduces the Microsoft FORTRAN Graphics Library and its use. The
  6160.  graphics library supports traditional pixel-based routines such as line
  6161.  drawing, in addition to a collection of font routines that can scale and
  6162.  print text in a variety of typefaces. Numerous examples in the chapters and
  6163.  reference section show how the routines are actually used.
  6164.  
  6165.  
  6166.  Chapter 8  Graphics Library Routines
  6167.  ───────────────────────────────────────────────────────────────────────────
  6168.  
  6169.  The Microsoft FORTRAN DOS run-time graphics library includes a complete set
  6170.  of graphics functions. It supports pixel-based graphics, real-coordinate
  6171.  graphics, and character fonts. In addition, the associated text-based
  6172.  routines are also available under OS/2. This chapter introduces the major
  6173.  categories of library routines and their use. Chapters 9 and 10 cover
  6174.  graphics and fonts, respectively, in more detail. For a complete description
  6175.  of the syntax and use of each individual routine, see Chapter 11, "Graphics
  6176.  Library Reference."
  6177.  
  6178.  Review the contents of this chapter carefully. It provides an overview of
  6179.  all of the routines, and introduces some important fundamental concepts.
  6180.  Several of the routines affect the output of other routines; reading the
  6181.  entire chapter will give you an understanding of how the different classes
  6182.  of routines interact.
  6183.  
  6184.  You can access this graphics library from Microsoft FORTRAN as well as other
  6185.  Microsoft languages that support the FORTRAN calling conventions. The
  6186.  graphics package supports the IBM(R) (and compatible) Enhanced Graphics
  6187.  Adapter (EGA) ; the Color Graphics Adapter (CGA) ; the Multicolor Graphics
  6188.  Array (MCGA); certain operating modes of the Video Graphics Array (VGA)
  6189.  hardware configuration; and the Olivetti(R) video mode present on AT&T
  6190.  personal computers. The package also supports the Hercules(R) Graphics Card,
  6191.  Graphics Card Plus, InColor Card, and 100-percent compatible cards.
  6192.  
  6193.  
  6194.  8.1  Using Graphics and Character-Font Functions
  6195.  
  6196.  The graphics and font routines are supplied in a run-time library, named
  6197.  GRAPHICS.LIB, that you must link to your programs using graphics; the OS/2
  6198.  library GRTEXTP.LIB supports the text-based graphics routines. Graphics
  6199.  routines are functions and subroutines that draw lines, rectangles,
  6200.  ellipses, and similar graphic elements on the screen. The font routines
  6201.  allow your computer to create text in a variety of styles, sizes, and
  6202.  colors.
  6203.  
  6204.  Every program using the graphics library must also explicitly declare any
  6205.  routines it uses. This means that you will need to either write an interface
  6206.  to each routine you call, or reference the include files FGRAPH.FI and
  6207.  FGRAPH.FD; the OS/2 library GRTEXTP.LIB uses these same files. The FGRAPH.FI
  6208.  include file contains procedure declarations in INTERFACE statements; the
  6209.  include file FGRAPH.FD contains both structure and symbolic constant
  6210.  declarations and EXTERNAL statement declarations for the graphics
  6211.  procedures. Together, they contain the declarations necessary to access all
  6212.  of the graphics library routines. To use them, include FGRAPH.FI at the
  6213.  beginning of your program's source files, and FGRAPH.FD in every subprogram
  6214.  that calls a graphics routine.
  6215.  
  6216.  The GRAPHICS.LIB run-time library includes routines corresponding to the
  6217.  various tasks involved in creating and manipulating graphics:
  6218.  
  6219.  Category                              Task
  6220.  
  6221.  Configuring mode and drawing          Selects the proper display mode
  6222.  environment                           for the hardware and establishes
  6223.                                        memory areas for the writing and
  6224.                                        displaying of images
  6225.  
  6226.  Setting coordinates                   Specifies the origin and the
  6227.                                        display area on the screen
  6228.  
  6229.  Setting graphics palettes             Specifies colors available to
  6230.                                        graphics routines
  6231.  
  6232.  Setting attributes                    Specifies background and
  6233.                                        foreground colors and mask and
  6234.                                        line styles for graphics routines
  6235.  
  6236.  Displaying images                     Draws and fills figures on the
  6237.                                        screen
  6238.  
  6239.  Outputting text                       Writes text to the screen
  6240.  
  6241.  Transferring images                   Stores images in memory and
  6242.                                        retrieves them
  6243.  
  6244.  Displaying fonts                      Displays text in specified fonts
  6245.                                        compatible with Microsoft Windows
  6246.                                        286/386
  6247.  
  6248.  The following sections explain each of these tasks in detail. Note that many
  6249.  of the graphics routine names exceed 6 characters, so avoid using the
  6250.  $TRUNCATE metacommand in programs that call graphics routines.
  6251.  
  6252.  
  6253.  8.2  Defining Graphics Characteristics
  6254.  
  6255.  Before you are actually ready to create graphics on your screen, you must
  6256.  invoke routines that define the way both text and graphics will be
  6257.  displayed. Sections 8.2.1-8.2.4 discuss four groups of these routines.
  6258.  
  6259.  
  6260.  8.2.1  Selecting Display Options
  6261.  
  6262.  The Microsoft FORTRAN run-time graphics library contains a number of
  6263.  routines that let you define how you want to display text and graphics.
  6264.  These routines determine the graphics environment characteristics, establish
  6265.  operational modes (text or graphics), and control the cursor.
  6266.  
  6267.       Routine                          Use
  6268.  
  6269.       displaycursor                    Turns the cursor back on or
  6270.                                        leaves the cursor off after
  6271.                                        executing a graphics routine
  6272.  
  6273.       getvideoconfig                   Obtains information about the
  6274.                                        current graphics environment
  6275.  
  6276.       setactivepage                    Sets the memory location for the
  6277.                                        working page; lets you animate
  6278.                                        objects
  6279.  
  6280.       settextrows                      Sets the number of rows available
  6281.                                        for standard text output
  6282.  
  6283.       setvideomode                     Sets a display mode for the
  6284.                                        screen
  6285.  
  6286.       setvideomoderows                 Sets the display mode and the
  6287.                                        number of rows available for
  6288.                                        standard text output
  6289.  
  6290.       setvisualpage                    Sets a memory location for the
  6291.                                        display page
  6292.  
  6293.  The displaycursor routine lets you control whether the cursor will be
  6294.  restored after completing a graphics routine. Either setting you choose
  6295.  remains in effect until the next time you call the routine.
  6296.  
  6297.  The getvideoconfig routine returns information about the current hardware
  6298.  environment. This information is used by several of the other routines. (For
  6299.  example, getvideoconfig returns the value of screen size needed by
  6300.  videoconfig.)
  6301.  
  6302.  The setactivepage and setvisualpage routines set aside memory for the
  6303.  working page and the displayed page, respectively, in configurations that
  6304.  support multiple video pages.
  6305.  
  6306.  The setvideomode routine selects an operating mode (such as the resolution)
  6307.  for the monitor. The settextrows routine sets the number of text rows to be
  6308.  displayed. The setvideomoderows routine combines the two previous functions;
  6309.  it sets the display mode and the number of text rows available.
  6310.  
  6311.  
  6312.  8.2.2  Setting Graphics Coordinates
  6313.  
  6314.  The coordinate-setting routines control where graphics may appear on the
  6315.  screen. Microsoft FORTRAN graphics routines recognize three sets of
  6316.  coor-dinates:
  6317.  
  6318.    1. Fixed "physical coordinates," which are determined by the hardware and
  6319.       the configuration routines used
  6320.  
  6321.    2. "Viewport coordinates," which you define in the application
  6322.  
  6323.    3. "Window coordinates," which you define to simplify scaling of
  6324.       floating-point data values
  6325.  
  6326.  Unless you change it, the viewport-coordinate system is identical to the
  6327.  physical- coordinate system. The physical origin (0, 0) is always in the
  6328.  upper left corner of the display. The x-axis extends in the positive
  6329.  direction left to right, while the  y-axis extends in the positive direction
  6330.  top to bottom.
  6331.  
  6332.  The routines also let you convert between physical-, viewport-, and
  6333.  window-coordinate systems. (For more detailed information on coordinate
  6334.  graphics, see Chapter 9, "Drawing Graphic Elements.")
  6335.  
  6336.       Routine                          Use
  6337.  
  6338.       getcurrentposition               Determines current position in
  6339.                                        viewport coordinates
  6340.  
  6341.       getcurrentposition_w             Determines current position in
  6342.                                        window coordinates
  6343.  
  6344.       getphyscoord                     Converts viewport coordinates to
  6345.                                        physical coordinates
  6346.  
  6347.       getviewcoord                     Converts physical coordinates to
  6348.                                        viewport coordinates
  6349.  
  6350.       getviewcoord_w                   Converts window coordinates to
  6351.                                        viewport coordinates in xycoord
  6352.                                        structure
  6353.  
  6354.       getwindowcoord                   Converts viewport coordinates to
  6355.                                        window coordinates
  6356.  
  6357.       setcliprgn                       Limits graphic output to part of
  6358.                                        the screen
  6359.  
  6360.       setvieworg                       Positions the viewport-coordinate
  6361.                                        origin
  6362.  
  6363.       setviewport                      Limits graphic output and
  6364.                                        positions the viewport-coordinate
  6365.                                        origin within a limited area
  6366.  
  6367.       setwindow                        Defines a window-coordinate
  6368.                                        system
  6369.  
  6370.  The dimensions of the x-  and y-axes depend on the configuration routine
  6371.  used and the current mode (text or graphics). These values are accessible
  6372.  through the numxpixels and numypixels values returned by getvideoconfig.
  6373.  Similarly,  getvideoconfig also returns the range of colors available in the
  6374.  current mode through the bitsperpixel value.
  6375.  
  6376.  The origin of the viewport-coordinate system can be moved to a new position
  6377.  relative to the physical origin with the setvieworg routine. However, you
  6378.  can still determine the location of any point with the getcurrentposition
  6379.  and getcurrentposition_w routines.
  6380.  
  6381.  The window-coordinate system lets you easily scale any set of data to fit on
  6382.  the screen. You define whatever range of coordinates works well for your
  6383.  data (such as 0 to 5,000) as the range for the window-coordinate axes. By
  6384.  telling the program that you want the window-coordinate system to fit in a
  6385.  particular area on the screen (map to a particular set of viewport
  6386.  coordinates), you can scale a chart or drawing to any size you wish. The
  6387.  setwindow routine defines a window-coordinate system bound by the specified
  6388.  values.
  6389.  
  6390.  The getphyscoord routine converts any viewport coordinates to physical
  6391.  coordinates, and the getviewcoord routine translates from physical
  6392.  coordinates to viewport coordinates. Similarly, getviewcoord_w changes
  6393.  window coordinates to viewport coordinates, and getwindowcoord translates
  6394.  viewport coordinates into window coordinates.
  6395.  
  6396.  The setcliprgn routine defines a restricted active display area on the
  6397.  screen (a "clipping region"). The setviewport function does the same thing
  6398.  and also resets the viewport origin to the upper left corner of the clipping
  6399.  region.
  6400.  
  6401.  
  6402.  8.2.3  Setting Palettes
  6403.  
  6404.  Each color on the screen is represented by a unique value called a "color
  6405.  index." To associate a color index with the color on the screen, the
  6406.  graphics library uses the concept of a "palette." A palette is simply a
  6407.  "mapping" (association) of color indexes to the actual display colors.
  6408.  
  6409.  The palette routines assign colors to the functions and subroutines that
  6410.  draw in color. They can also alter the colors of items already drawn on the
  6411.  screen.
  6412.  
  6413.  The three palette routines determine the mapping between the color indexes
  6414.  and the colors drawn on the screen.
  6415.  
  6416.       Routine                          Use
  6417.  
  6418.       remapallpalette                  Assigns a color index to all of
  6419.                                        the displayable colors
  6420.  
  6421.       remappalette                     Assigns a color index to a
  6422.                                        specific color
  6423.  
  6424.       selectpalette                    Selects a predefined palette
  6425.  
  6426.  Depending on the particular graphics mode, a one-, two-, four-, or eight-bit
  6427.  value represents each screen pixel. This bit-value representation of a
  6428.  color called the "color value," is often required by routines as one of
  6429.  their arguments.
  6430.  
  6431.  Most video modes support only one palette. If you select the
  6432.  medium-resolution graphics mode $MRES4COLOR, $MRESNOCOLOR, or $ORESCOLOR,
  6433.  however, you can access multiple palettes. (In these modes, the palette
  6434.  consists of a background color and three other colors.) The selectpalette
  6435.  routine selects a particular palette from the available palettes.
  6436.  
  6437.  EGA and VGA hardware also provide the capability of remapping a palette,
  6438.  allowing any available color index to be mapped to any color value. Two
  6439.  routines allow the EGA and VGA to provide this capability: the remappalette
  6440.  function remaps one color value, and remapallpalette remaps the entire
  6441.  palette.
  6442.  
  6443.  The remappalette, remapallpalette, setbkcolor, and getbkcolor routines are
  6444.  the only routines that recognize color values defined for the EGA or VGA.
  6445.  
  6446.  Many graphics routines operate only on certain hardware or in certain
  6447.  graphics modes. These routines return an error code if you use them on an
  6448.  invalid hardware environment. The reference section (Chapter 11) indicates
  6449.  which routines return error information; if you use these routines, be sure
  6450.  to check the returned value for any errors.
  6451.  
  6452.  
  6453.  8.2.4  Setting Figure Attributes
  6454.  
  6455.  The output routines that draw arcs, ellipses, and other primitive figures do
  6456.  not specify color or line-style information. Instead, they rely on several
  6457.  "attributes" set independently by the routines listed below.
  6458.  
  6459.       Routine                          Use
  6460.  
  6461.       getbkcolor                       Returns the current background
  6462.                                        color
  6463.  
  6464.       getcolor                         Returns the current color
  6465.  
  6466.       getlinestyle                     Returns the current line style
  6467.  
  6468.       getfillmask                      Returns the current fill mask
  6469.  
  6470.       setbkcolor                       Sets the current background color
  6471.                                        to a new color
  6472.  
  6473.       setcolor                         Sets the current color to a new
  6474.                                        color
  6475.  
  6476.       setfillmask                      Sets the current fill mask to a
  6477.                                        new color
  6478.  
  6479.       setlinestyle                     Sets the current line style to a
  6480.                                        new line style
  6481.  
  6482.  The getcolor and setcolor routines obtain or set the "current color"
  6483.  attribute, which the floodfill routine and the closed-figure drawing
  6484.  routines all use. Similarly, the getbkcolor and setbkcolor routines retrieve
  6485.  or set the "current background color," used by the clearscreen function.
  6486.  
  6487.  The getfillmask and setfillmask routines return or set the "current fill
  6488.  mask" attribute. The mask is an 8-by-8-bit array with each bit representing
  6489.  a pixel. If a bit is 0, the pixel in memory is left untouched: the mask is
  6490.  transparent to that pixel. If a bit is 1, the pixel is assigned the current
  6491.  color value. The array acts as a template that repeats over the entire fill
  6492.  area. It "masks" the background with a pattern of pixels drawn in the
  6493.  current color, creating a large number of fill patterns. These routines are
  6494.  particularly useful for shading and slight color-variation effects.
  6495.  
  6496.  The getlinestyle and setlinestyle routines retrieve and set the "current
  6497.  line style." The line style is determined by a 16-bit-long template with
  6498.  each bit cor-responding to a pixel. If a bit is 0, the pixel keeps the
  6499.  current background color (that is, appears transparent). If a bit is 1, the
  6500.  pixel appears in the current color. The template repeats over the entire
  6501.  length of the line. The two routines let you create a wide variety of dashed
  6502.  lines.
  6503.  
  6504.  
  6505.  8.3  Displaying Graphics Output
  6506.  
  6507.  The remaining graphics routines actually allow you to draw geometric
  6508.  features, display text, display font-based characters, and transfer images
  6509.  between memory and the screen. These routines are described in Sections
  6510.  8.3.1-8.3.3.
  6511.  
  6512.  
  6513.  8.3.1  Creating a Graphics Display
  6514.  
  6515.  The Microsoft FORTRAN run-time graphics library routines draw geometric
  6516.  figures using the coordinate system you specify. They use the current line
  6517.  style, fill mask, background color, and foreground color.
  6518.  
  6519.  If you want anything other than the default line style (solid), mask (no
  6520.  mask), background color (green), or foreground color (highest index on the
  6521.  current palette), you must call the appropriate routine prior to calling the
  6522.  drawing routine. Subsequent output routines employ the same attributes until
  6523.  they are changed.
  6524.  
  6525.  The name of each routine describes its task or the figure it draws.
  6526.  
  6527.       Routine                          Use
  6528.  
  6529.       arc, arc_w                       Draws an arc
  6530.  
  6531.       clearscreen                      Erases the screen (fills it with
  6532.                                        the current background color)
  6533.  
  6534.       ellipse, ellipse_w               Draws an ellipse or circle
  6535.  
  6536.       floodfill, floodfill_w           Fills an area of the screen with
  6537.                                        the current mask in the current
  6538.                                        color
  6539.  
  6540.       getcurrentposition,              Finds the coordinates of the
  6541.       getcurrentposition_w             current graphic-output position
  6542.  
  6543.       getpixel, getpixel_w             Returns a pixel's value
  6544.  
  6545.       lineto, lineto_w                 Draws a line from the current
  6546.                                        graphic-output position to a
  6547.                                        specified point
  6548.  
  6549.       moveto, moveto_w                 Moves the current graphic-output
  6550.                                        position to a specified point
  6551.  
  6552.       pie, pie_w                       Draws a pie-slice-shaped figure
  6553.  
  6554.       rectangle,  rectangle_w          Draws a rectangle
  6555.  
  6556.       setpixel, setpixel_w             Sets a pixel's value
  6557.  
  6558.  Most of these routines have multiple forms. Routine names that end with "_w"
  6559.  use the window-coordinate system and DOUBLE PRECISION argument values.
  6560.  Routines without this suffix use the viewport-coordinate system.
  6561.  
  6562.  Curved figures, such as arcs and ellipses, are centered within a "bounding
  6563.  rectangle," which is specified by the upper left and lower right corners of
  6564.  the rectangle. The center of the rectangle becomes the center for the
  6565.  figure, and the rectangle's borders determine the size of the figure. In
  6566.  Figure 8.1 the points (x1, y1) and (x2, y2) define the bounding rectangle.
  6567.  
  6568.  
  6569.  8.3.2  Displaying Text
  6570.  
  6571.  These routines let you send text to the screen in both graphics and text
  6572.  modes. The routines for outputting text in specialized fonts are described
  6573.  in Chapter 10, "Using Fonts from the Graphics Library." Unlike the standard
  6574.  I/O statements, these routines recognize the text-window boundaries used in
  6575.  applications that use windows.
  6576.  
  6577.       Routine                     Use
  6578.  
  6579.       displaycursor               Sets the cursor on or off after
  6580.                                   leaving a graphics routine
  6581.  
  6582.       gettextcolor                Returns the current text color
  6583.  
  6584.       gettextcursor               Returns the current cursor
  6585.                                   attribute (text modes only)
  6586.  
  6587.       gettextposition             Returns the current text-output
  6588.                                   position
  6589.  
  6590.       outtext                     Sends text to the screen at the
  6591.                                   current position
  6592.  
  6593.       settextcolor                Sets the current text color to a
  6594.                                   new color
  6595.  
  6596.       settextcursor               Sets the current cursor attribute
  6597.                                   (text modes only)
  6598.  
  6599.       settextposition             Relocates the current text
  6600.                                   position
  6601.  
  6602.       settextwindow               Sets the current text-display
  6603.                                   window
  6604.  
  6605.       wrapon                      Turns line wrapping on or off
  6606.  
  6607.  These routines do not provide text-formatting capabilities. If you want to
  6608.  print integer or floating-point values, you must convert the values into a
  6609.  string (using an internal WRITE statement) before calling these routines.
  6610.  The text routines specify all screen positions in character-row and column
  6611.  coordinates.
  6612.  
  6613.  The settextwindow routine is the text equivalent to the setcliprgn graphics
  6614.  routine, except that it restricts only the display area for text printed
  6615.  with outtext. It does not affect the standard I/O statements, such as WRITE.
  6616.  The outtext routine displays a string on the screen. You can retrieve or
  6617.  alter the current text color with the gettextcolor and settextcolor
  6618.  routines, respectively. The routines gettextposition and settextposition let
  6619.  you determine or change the location of the next text sent to the screen.
  6620.  
  6621.  ───────────────────────────────────────────────────────────────────────────
  6622.  WARNING
  6623.     The WRITE statement sends its carriage return (CR) and line feed (LF) to
  6624.     the screen at the beginning of the first I/O statement following the
  6625.     WRITE statement. This can cause unpredictable text positioning if you mix
  6626.     the graphics routines settextposition and settext with the WRITE
  6627.     statement. Minimize this effect by using the backslash (\) format
  6628.     descriptor (suppress CR-LF) in the associated FORMAT statement.
  6629.  ───────────────────────────────────────────────────────────────────────────
  6630.  
  6631.  The wrapon function enables or disables automatic "line wrapping." Line
  6632.  wrapping ends a line of text and starts a new one when a word at the end of
  6633.  a line is too long. Without line wrapping the same word would be split,
  6634.  often incoherently, at the end of the first line, with the remainder
  6635.  appearing on the next line.
  6636.  
  6637.  
  6638.  8.3.3  Transferring Images
  6639.  
  6640.  The getimage and putimage groups of routines transfer images between mem-ory
  6641.  and the screen. When you hold an image in memory, the application allocates
  6642.  a buffer (that is, it sets aside part of the computer's memory) for the
  6643.  image. The imagesize routines calculate the size in bytes of the buffer
  6644.  needed to store a given image.
  6645.  
  6646.  Routines that end with "_w" use window coordinates; the other functions in
  6647.  this set use viewport coordinates.
  6648.  
  6649.       Routine                          Use
  6650.  
  6651.       getimage, getimage_w             Stores a screen image in memory
  6652.  
  6653.       imagesize, imagesize_w           Returns image size in bytes
  6654.  
  6655.       putimage, putimage_w             Retrieves an image from memory
  6656.                                        and displays it
  6657.  
  6658.  In systems that support multiple pages, you can send graphics to a page in
  6659.  memory while displaying another page. Once you complete the page in memory,
  6660.  display it on the screen and begin drawing a new page in memory. By
  6661.  repeating this process you can animate objects on the screen.
  6662.  
  6663.  
  6664.  8.3.4  Displaying Font-Based Characters
  6665.  
  6666.  Since the FORTRAN Graphics Library provides a variety of fonts, indicate
  6667.  which font you wish to use when displaying font-based characters. Once you
  6668.  select a font, you can make inquiries about the width of a string or the
  6669.  current font characteristics. The following functions control the display of
  6670.  font-based characters.
  6671.  
  6672.       Routine                          Use
  6673.  
  6674.       getfontinfo                     Returns the current font
  6675.                                       characteristics
  6676.  
  6677.       getgtextextent                  Determines the width of specified
  6678.                                       text in the current font
  6679.  
  6680.       outgtext                        Sends text in the current font to
  6681.                                       the screen at the specified pixel
  6682.                                       position
  6683.  
  6684.       registerfonts                   Initializes the font library
  6685.  
  6686.       setfont                         Finds a single font that matches
  6687.                                       a specified set of
  6688.                                       characteristics and makes this
  6689.                                       font the current font for use by
  6690.                                       the outgtext function
  6691.  
  6692.       unregisterfonts                 Frees memory allocated by
  6693.                                       registerfonts
  6694.  
  6695.  Characters may be drawn ("mapped") in one of two ways: as bit-mapped letters
  6696.  (a "picture" of the letter) or as vector-mapped characters (a series of
  6697.  lines and arcs that make up a letter). See Chapter 10, "Using Fonts from
  6698.  the Graphics Library," for detailed explanations and examples of how to
  6699.  apply fonts and the characteristics of the fonts supplied with Microsoft
  6700.  FORTRAN.
  6701.  
  6702.  
  6703.  8.4  Routines Available under OS/2
  6704.  
  6705.  The OS/2 graphics library, GRTEXTP.LIB, contains the text-based routines
  6706.  available under DOS. The functionality and use of the OS/2 routines are the
  6707.  same as DOS, and the descriptions in Chapter 11, "Graphics Library
  6708.  Reference," all apply. When linking, however, you need to supply GRTEXTP.LIB
  6709.  in place of the DOS GRAPHICS.LIB. Note that both DOS and OS/2 use the same
  6710.  graphics include files.
  6711.  
  6712.  The library GRTEXTP.LIB supports the following routines:
  6713.  
  6714.       clearscreen          getvisualpage        settextwindow
  6715.       displaycursor        outtext              setvideomode
  6716.       getactivepage        setactivepage        setvideomoderows
  6717.       getbkcolor           setbkcolor           setvisualpage
  6718.       gettextcolor         settextcolor         wrapon
  6719.       gettextcursor        settextcursor
  6720.       gettextposition      settextposition
  6721.       getvideoconfig       settextrows
  6722.  
  6723.  
  6724.  
  6725.  Chapter 9  Drawing Graphic Elements
  6726.  ───────────────────────────────────────────────────────────────────────────
  6727.  
  6728.  Graphics can make your screens and data more understandable and informative.
  6729.  All of the building blocks needed to create a wide variety of drawings are
  6730.  discussed in this chapter. The chapter assumes you have read the overview
  6731.  presented in Chapter 8. Note that the OS/2 graphics library, GRTEXTP.LIB,
  6732.  does not support font-based routines. Refer to Chapter 8 for a list of the
  6733.  OS/2 routines available under DOS.
  6734.  
  6735.  The DOS graphics routines provided with the Microsoft FORTRAN Compiler set
  6736.  points, draw lines, change colors, and draw shapes such as circles,
  6737.  rectangles, and arcs. The first section defines some basic graphics terms,
  6738.  lists the steps to using high-resolution graphics, and works through a
  6739.  sample program step by step, showing how to use the elementary routines. The
  6740.  remaining sections explain coordinate systems in detail and how to display
  6741.  graphics inside viewports and windows.
  6742.  
  6743.  
  6744.  9.1  Working with Graphics Modes
  6745.  
  6746.  Before your program can begin drawing graphic elements, you must specify the
  6747.  type of monitor being used, the desired screen resolution, and whether to
  6748.  display in color or black and white──in short, the "mode" you want to use
  6749.  when displaying graphics. This section shows you how to determine an
  6750.  appropriate graphics mode; how to make that mode active; and how to write a
  6751.  typical graphics program.
  6752.  
  6753.  This chapter refers to the following terms frequently. Be sure you are
  6754.  familiar with them:
  6755.  
  6756.    ■  The "origin" (point 0,0) is the upper left corner of your screen. The
  6757.       x- and y-axes start at the origin. You can change the origin in some
  6758.       coordinate systems.
  6759.  
  6760.    ■  The horizontal direction is represented by the x-axis. The maximum
  6761.       number of horizontal "pixels" (picture elements) varies between 320 and
  6762.       720, depending on the graphics card installed and the graphics mode in
  6763.       effect.
  6764.  
  6765.    ■  The vertical direction is represented by the y-axis. The number of
  6766.       vertical pixels ranges from 200 to 480.
  6767.  
  6768.    ■  Each graphics mode offers a color palette. You may access 2, 4, 8, 16,
  6769.       or 256 "color indexes" (an index number associated with a specific
  6770.       screen color), depending on the graphics card in the computer and the
  6771.       graphics mode in effect.
  6772.  
  6773.    ■  The CGA modes use four fixed "palettes" containing predefined colors
  6774.       that cannot be changed. The EGA, MCGA, and VGA modes allow you to
  6775.       change any of the color indexes by providing a color value that
  6776.       describes the mix of colors you want to use.
  6777.  
  6778.    ■  A color index is always an INTEGER*2 number. A color value is always an
  6779.       INTEGER*4 value. When you call graphics routines that require
  6780.       color-related parameters, be aware of the difference between color
  6781.       indexes and color values. (See Section 9.2.1.2, "Color Mixing.")
  6782.  
  6783.  To prepare a system to display graphics, you need to
  6784.  
  6785.    1. Use the getvideoconfig procedure to find the type of video adapter
  6786.       installed. (See Section 9.1.1, "Checking the Current Video Mode.")
  6787.  
  6788.    2. Set the desired graphics mode for the adapter with the setvideomode
  6789.       procedure. (See Section 9.1.2, "Setting the Video Mode.")
  6790.  
  6791.    3. Draw the graphics. (See Section 9.1.3, "Writing a Graphics Program.")
  6792.  
  6793.  When you finish creating the graphics, remember to return to the default
  6794.  text mode before leaving the program.
  6795.  
  6796.  ───────────────────────────────────────────────────────────────────────────
  6797.  WARNING
  6798.     You must always explicitly link the graphics library. See Chapter 7, "The
  6799.     FL Command," of the Microsoft FORTRAN Reference for information about
  6800.     linking libraries.
  6801.  ───────────────────────────────────────────────────────────────────────────
  6802.  
  6803.  
  6804.  9.1.1  Checking the Current Video Mode
  6805.  
  6806.  In order to avoid compatibility problems, call the getvideoconfig routine
  6807.  before entering a video mode. Information about the current system is
  6808.  returned in the videoconfig structure defined in FGRAPH.FD and outlined in
  6809.  the program example below.
  6810.  
  6811.  The videoconfig structure is defined below. You need to recognize the fields
  6812.  and their usage because several other graphics routines require them as
  6813.  arguments:
  6814.  
  6815.       STRUCTURE/videoconfig/
  6816.        INTEGER*2 numxpixels             ! Number of pixels on x-axis
  6817.        INTEGER*2 numypixels             ! Number of pixels on y-axis
  6818.        INTEGER*2 numtextcols            ! Number of text columns available
  6819.        INTEGER*2 numtextrows            ! Number of text rows available
  6820.        INTEGER*2 numcolors              ! Number of color indexes
  6821.        INTEGER*2 bitsperpixel           ! Number of bits per pixel
  6822.        INTEGER*2 numvideopages          ! Number of available video pages
  6823.        INTEGER*2 mode                   ! Current video mode
  6824.        INTEGER*2 adapter                ! Active display adapter
  6825.        INTEGER*2 monitor                ! Active display monitor
  6826.        INTEGER*2 memory                 ! Adapter video memory in K bytes
  6827.       END STRUCTURE
  6828.  
  6829.  You initialize the fields in a structure variable of type videoconfig when
  6830.  you call getvideoconfig.
  6831.  
  6832.  
  6833.  9.1.2  Setting the Video Mode
  6834.  
  6835.  Once you know the current video configuration, you must tell the graphics
  6836.  adapter to switch from text mode to graphics mode. To do this, call the
  6837.  setvideomode routine. This routine will pass a constant to the adapter that
  6838.  tells the adapter which mode to display (see Table 9.1)
  6839.  
  6840.  The include file FGRAPH.FD defines these names as symbolic constants with
  6841.  the appropriate values. The screen dimensions for each mode are listed in
  6842.  pixels for graphics modes and in columns for text modes. The mode
  6843.  type/hardware column indicates the expected environment.
  6844.  
  6845.  ───────────────────────────────────────────────────────────────────────────
  6846.  NOTE
  6847.     If you use a Hercules adapter, you must run the MSHERC.COM program before
  6848.     attempting to display any graphics.
  6849.  ───────────────────────────────────────────────────────────────────────────
  6850.  
  6851.  If setvideomode returns a 0, the hardware does not support the selected
  6852.  mode. You can continue to select alternate video modes until the routine
  6853.  returns a nonzero value. You might use a sequence of high- to low-resolution
  6854.  calls to the setvideomode routine in order to choose the highest resolution
  6855.  available. The SELECT CASE constructs work particularly well. If the
  6856.  hardware configuration does not support any of the selected video modes, the
  6857.  program cannot display graphics.
  6858.  
  6859.  Table 9.1 below shows the names for the different video modes.
  6860.  
  6861.  Table 9.1  Video Modes for Text and Graphics
  6862.  
  6863.  Constant              Video Mode                          Mode Type/Hardware
  6864.  
  6865.  $DEFAULTMODE          Restores to original mode           Both/All
  6866.  
  6867.  $TEXTBW40             40 column text, 16 gray             Text/CGA
  6868.  
  6869.  $TEXTC40              40 column text, 16/8 color          Text/CGA
  6870.  
  6871.  $TEXTBW80             80 column text, 16 gray             Text/CGA
  6872.  
  6873.  $TEXTC80              80 column text, 16/8 color          Text/CGA
  6874.  
  6875.  $MRES4COLOR           320 x 200, 4 color                  Graphics/CGA
  6876.  
  6877.  $MRESNOCOLOR          320 x 200, 4 gray                   Graphics/CGA
  6878.  
  6879.  $HRESBW               640 x 200, BW                       Graphics/CGA
  6880.  
  6881.  $TEXTMONO             80 column text, BW                  Text/MDA
  6882.  
  6883.  $HERCMONO             720   348, BW for HGC               Graphics/HGC
  6884.  
  6885.  $MRES16COLOR          320 x 200, 16 color                 Graphics/EGA
  6886.  
  6887.  $HRES16COLOR          640 x 200, 16 color                 Graphics/EGA
  6888.  
  6889.  $ERESNOCOLOR          640 x 350, BW                       Graphics/EGA
  6890.  
  6891.  $ERESCOLOR            640 x 350, 4 or 16 color            Graphics/EGA
  6892.  
  6893.  $VRES2COLOR           640 x 480, BW                       Graphics/VGA/
  6894.                                                            MCGA
  6895.  
  6896.  $VRES16COLOR          640 x 480, 16 color                 Graphics/VGA
  6897.  
  6898.  $MRES256COLOR         320 x 200, 256 color                Graphics/VGA/
  6899.                                                            MCGA
  6900.  $ORESCOLOR            640                                 400, 1 of 16 colors
  6901.  
  6902.  $MAXCOLORMODE        See Tables R.5 and R.6 for          Graphics/CGA
  6903.                        maximum colors
  6904.  
  6905.  $MAXRESMODE          See Tables R.5 and R.6 for          Graphics/CGA
  6906.                        maximum resolution
  6907.  
  6908.  
  6909.  9.1.3  Writing a Graphics Program (SINE)
  6910.  
  6911.  Like many programs, graphics programs work well in modular form. The use of
  6912.  discrete routines aids debugging by isolating the separate functional
  6913.  components of the program. The following program and its associated
  6914.  subroutines illustrate the processes involved in initializing, drawing, and
  6915.  closing a graphics program.
  6916.  
  6917.  The SINE program creates a sine wave. Its procedures use many of the common
  6918.  graphics routines. The main program (see below) follows a modular structure,
  6919.  calling five functions which carry out the actual graphics commands. All of
  6920.  the functions are defined later in this chapter.
  6921.  
  6922.       CC  SINE.FOR - Illustrates basic graphics commands.
  6923.  
  6924.             INCLUDE 'FGRAPH.FI'
  6925.  
  6926.             CALL graphicsmode()
  6927.             CALL drawlines()
  6928.             CALL sinewave()
  6929.             CALL drawshapes()
  6930.             CALL endprogram()
  6931.             END
  6932.  
  6933.       C     Definitions of subroutines go here
  6934.       .
  6935.       .
  6936.       .
  6937.  
  6938.  The SINE program's output appears in Figure 9.1.
  6939.  
  6940.  
  6941.  9.1.3.1  Activating a Graphics Mode
  6942.  
  6943.  Before your program can display graphics, you must specify a graphics mode.
  6944.  Your program can then call setvideomode to set the video adapter to the
  6945.  appropriate graphics mode.
  6946.  
  6947.  SINE turns on the graphics mode by calling the subroutine graphicsmode
  6948.  below. The subroutine selects the highest possible resolution for the
  6949.  current video adapter (such as CGA and VGA).
  6950.  
  6951.             SUBROUTINE graphicsmode()
  6952.  
  6953.             INCLUDE 'FGRAPH.FD'
  6954.  
  6955.             INTEGER*2            dummy, maxx, maxy
  6956.             RECORD /videoconfig/ myscreen
  6957.             COMMON               maxx, maxy
  6958.  
  6959.       C
  6960.       C     Find graphics mode.
  6961.       C
  6962.             CALL getvideoconfig( myscreen )
  6963.             SELECT CASE( myscreen.adapter )
  6964.                CASE( $CGA )
  6965.                   dummy = setvideomode( $HRESBW )
  6966.                CASE( $OCGA )
  6967.                   dummy = setvideomode( $ORESCOLOR )
  6968.                CASE( $EGA, $OEGA )
  6969.                   IF( myscreen.monitor .EQ. $MONO ) THEN
  6970.                       dummy = setvideomode( $ERESNOCOLOR )
  6971.                   ELSE
  6972.                       dummy = setvideomode( $ERESCOLOR )
  6973.                   END IF
  6974.                CASE( $VGA, $OVGA, $MCGA )
  6975.                   dummy = setvideomode( $VRES2COLOR )
  6976.                CASE( $HGC )
  6977.                   dummy = setvideomode ( $HERCMONO )
  6978.                CASE DEFAULT
  6979.                   dummy = 0
  6980.             END SELECT
  6981.  
  6982.             IF( dummy.EQ.0) STOP 'Error: cannot set graphics mode'
  6983.  
  6984.       C
  6985.       C     Determine the minimum and maximum dimensions.
  6986.       C
  6987.             CALL getvideoconfig( myscreen )
  6988.             maxx = myscreen.numxpixels - 1
  6989.             maxy = myscreen.numypixels - 1
  6990.             END
  6991.  
  6992.  The subroutine begins by calling getvideoconfig and passes the address of
  6993.  the videoconfig structure myscreen. In videoconfig, the element called
  6994.  "adapter" tells the subroutine the type of adapter in use. Given that
  6995.  information and a SELECT CASE block, the program enters the appropriate
  6996.  graphics mode.
  6997.  
  6998.  To find the resolution of the video mode the program chose, you must pass
  6999.  the videoconfig structure to the getvideoconfig routine, using the same
  7000.  structure:
  7001.  
  7002.             CALL getvideoconfig( myscreen )
  7003.             maxx = myscreen.numxpixels - 1
  7004.             maxy = myscreen.numypixels - 1
  7005.  
  7006.  If your computer uses an EGA card, the subroutine graphicsmode sets the
  7007.  video mode to $ERESNOCOLOR. The horizontal screen size is 640 pixels and the
  7008.  vertical screen size is 350. The two assignments give these values
  7009.  to maxx and maxy, less 1. The horizontal resolution might be 640, but the
  7010.  pixels are numbered 0-639. Thus, the maxx variable──the highest available
  7011.  pixel number──must be 1 less than the total number of pixels:
  7012.  
  7013.             myscreen.numxpixels - 1.
  7014.  
  7015.  Two short functions convert from an imaginary 1,000-by-1,000-pixel screen to
  7016.  whatever video mode is in effect. From now on, the program assumes it has
  7017.  1,000 pixels in each direction. To draw the points on the
  7018.  screen, newx and newy change each point to their physical (pixel)
  7019.  coordinates, as follows:
  7020.  
  7021.       CC  NEWX - This function finds new x-coordinates.
  7022.  
  7023.             INTEGER*2 FUNCTION newx( xcoord )
  7024.  
  7025.             INTEGER*2 xcoord, maxx, maxy
  7026.             REAL*4    tempx
  7027.             COMMON    maxx, maxy
  7028.  
  7029.             tempx = maxx / 1000.0
  7030.             tempx = xcoord * tempx + 0.5
  7031.             newx  = tempx
  7032.             END
  7033.  
  7034.       CC  NEWY - This function finds new y-coordinates.
  7035.  
  7036.             INTEGER*2 FUNCTION newy( ycoord )
  7037.  
  7038.             INTEGER*2 ycoord, maxx, maxy
  7039.             REAL*4    tempy
  7040.             COMMON    maxx, maxy
  7041.  
  7042.             tempy = maxy / 1000.0
  7043.             tempy = ycoord * tempy + 0.5
  7044.             newy  = tempy
  7045.             END
  7046.  
  7047.  
  7048.  9.1.3.2  Drawing Lines on the Screen
  7049.  
  7050.  SINE calls the subroutine drawlines next. As the name implies, this
  7051.  subroutine draws several lines on the screen. In this case, a rectangle
  7052.  around the outer edges of the screen and three horizontal lines that divide
  7053.  the screen into quarters are drawn (see Figure 9.1 above).
  7054.  
  7055.       CC  DRAWLINES - This subroutine draws a box and
  7056.       CC              several lines.
  7057.  
  7058.             SUBROUTINE drawlines()
  7059.  
  7060.             INCLUDE 'FGRAPH.FD'
  7061.  
  7062.             EXTERNAL         newx,newy
  7063.             INTEGER*2        dummy, newx, newy, maxx, maxy
  7064.             RECORD /xycoord/ xy
  7065.             COMMON           maxx, maxy
  7066.  
  7067.       C
  7068.       C     Draw the box.
  7069.       C
  7070.             dummy = rectangle( $GBORDER, 0, 0, maxx, maxy )
  7071.             CALL setvieworg( 0, newy( INT2( 500 ) ), xy )
  7072.       C
  7073.       C     Draw the lines.
  7074.       C
  7075.             CALL    moveto( 0, 0, xy )
  7076.             dummy = lineto( newx( INT2( 1000 ) ), 0 )
  7077.             CALL    setlinestyle( #AA3C )
  7078.             CALL    moveto( 0, newy( INT2( -250 ) ), xy )
  7079.             dummy = lineto(newx(INT2( 1000 ) ),
  7080.            +        newy( INT2( -250 ) ) )
  7081.             CALL    setlinestyle( #8888 )
  7082.             CALL    moveto( 0, newy( INT2( 250 ) ), xy )
  7083.             dummy = lineto( newx( INT2( 1000 ) ),
  7084.            +        newy( INT2( 250 ) ) )
  7085.             END
  7086.  
  7087.  The first argument to the rectangle routine is the "fill flag," which may be
  7088.  either $GBORDER or $GFILLINTERIOR. Choose $GBORDER if you want a rectangle
  7089.  of four lines (a border only, in the current line style). Choose
  7090.  $GFILLINTERIOR   if you want a solid rectangle (filled in with the current
  7091.  color and fill pattern). Choosing the color and fill pattern is discussed
  7092.  later in this chapter (see Tables 9.1-9.3).
  7093.  
  7094.  The second and third arguments are the x- and y-coordinates of the upper
  7095.  left corner of the rectangle. The fourth and fifth arguments are the
  7096.  coordinates for the opposite (lower right) corner. Since the coordinates for
  7097.  the two corners are ( 0, 0 ) and ( maxx, maxy ), the call to rectangle
  7098.  frames the screen:
  7099.  
  7100.             dummy = rectangle( $GBORDER, 0, 0, maxx, maxy )
  7101.  
  7102.  The call to the setlinestyle routine changes the line style from a solid
  7103.  line to a dashed line. A series of 16 bits tells the routine the pattern to
  7104.  follow. A "1" indicates a solid line segment and "0" an empty segment.
  7105.  Therefore, to the computer, a solid line looks like 1111 1111 1111 1111. A
  7106.  dashed line might look like 1111 1111 0000 0000 (long dashes) or 1111 0000
  7107.  1111 0000 (short dashes). You may choose any combination of 1s and 0s. The
  7108.  16-bit binary number also may be represented as a hexadecimal or decimal
  7109.  number. In the example below, the hexadecimal constant #AA3C equals the
  7110.  binary value 1010 1010 0011 1100. However you could use the decimal value
  7111.  43,580 as the argument just as effectively.
  7112.  
  7113.  To draw lines, first set any appropriate line style. Then move to where you
  7114.  want the line to begin and draw from that point to where you want the line
  7115.  to end. The SINE program, for example, uses the following:
  7116.  
  7117.             CALL setlinestyle( #AA3C )
  7118.             CALL moveto( 0, newy( INT2( -250 ) ), xy )
  7119.             dummy = lineto( newx( INT2( 1000 ) ),
  7120.            +                newy( INT2( -250 ) ) )
  7121.  
  7122.  The moveto routine positions an imaginary pixel cursor at a spot on the
  7123.  screen (nothing visible appears on the screen), and the lineto routine draws
  7124.  a line. The negative value -250 might seem to be an impossible screen
  7125.  coordinate. How-ever, the program calls setvieworg and changes the
  7126.  viewport-coordinate system to run from -500 at the top of the screen to +500
  7127.  at the bottom. Admittedly, this goes against intuitive convention, but
  7128.  illustrates the routine's ability to alter the viewport coordinates (or, to
  7129.  "viewport") to whatever dimensions or orientation you prefer. (Viewports and
  7130.  the setvieworg routine are explained in more detail in Section 9.3.2.1.)
  7131.  
  7132.  
  7133.  9.1.3.3  Drawing the Sine Curve
  7134.  
  7135.  With the axes and frame in place, SINE is ready to draw the sine curve. The
  7136.  sinewave routine calculates the x and y positions for two cycles of the sine
  7137.  wave and plots them on the screen:
  7138.  
  7139.       CC  SINEWAVE - This subroutine calculates and plots a sine
  7140.       CC             wave.
  7141.  
  7142.             SUBROUTINE sinewave()
  7143.  
  7144.       INCLUDE 'FGRAPH.FD'
  7145.  
  7146.             INTEGER*2        dummy, newx, newy, locx, locy, i
  7147.             DOUBLE PRECISION rad, PI
  7148.             EXTERNAL         newx, newy
  7149.  
  7150.             PARAMETER        ( PI = 3.14159 )
  7151.  
  7152.       C
  7153.       C     Calculate each position and display it on the screen.
  7154.       C
  7155.             DO i = 0, 999, 3
  7156.                rad   = -SIN( PI * i / 250.0 )
  7157.                locx  = newx( i )
  7158.                locy  = newy( INT2( rad * 250.0 ) )
  7159.                dummy = setpixel( locx, locy )
  7160.             END DO
  7161.             END
  7162.  
  7163.  The graphics routine setpixel takes the two location parameters, locx and
  7164.  locy, and turns on the pixel at that position.
  7165.  
  7166.  
  7167.  9.1.3.4  Adding Shapes
  7168.  
  7169.  After drawing the sine curve, the SINE program calls drawshapes to put two
  7170.  rectangles and two ellipses on the screen. The fill flag alternates between
  7171.  $GBORDER and $GFILLINTERIOR:
  7172.  
  7173.       CC  DRAWSHAPES - Draws two boxes and two ellipses.
  7174.  
  7175.             SUBROUTINE drawshapes()
  7176.  
  7177.             INCLUDE 'FGRAPH.FD'
  7178.  
  7179.             EXTERNAL  newx, newy
  7180.             INTEGER*2 dummy, newx, newy
  7181.  
  7182.       C
  7183.       C     Create a masking (fill) pattern.
  7184.       C
  7185.             INTEGER*1 diagmask(8),  linemask(8)
  7186.             DATA diagmask / #93, #C9, #64, #B2, #59, #2C,
  7187.            +                #96, #4B /
  7188.             DATA linemask / #FF, #00, #7F, #FE, #00, #00,
  7189.            +                #00, #CC /
  7190.       C
  7191.       C     Draw the rectangles.
  7192.       C
  7193.  
  7194.             CALL setlinestyle( #FFFF )
  7195.             CALL setfillmask( diagmask )
  7196.             dummy = rectangle( $GBORDER,
  7197.            +       newx( INT2( 50 ) ),  newy( INT2( -325 ) ),
  7198.            +       newx( INT2( 200 ) ), newy( INT2( -425 ) ) )
  7199.             dummy = rectangle( $GFILLINTERIOR,
  7200.            +       newx( INT2( 550 ) ), newy( INT2( -325 ) ),
  7201.            +       newx( INT2( 700 ) ), newy( INT2( -425 ) ) )
  7202.       C
  7203.       C     Draw the ellipses.
  7204.       C
  7205.             CALL setfillmask( linemask )
  7206.             dummy = ellipse( $GBORDER,
  7207.            +       newx( INT2( 50 ) ), newy( INT2(325 ) ),
  7208.            +       newx( INT2( 200 ) ), newy( INT2(425 ) ) )
  7209.             dummy = ellipse( $GFILLINTERIOR,
  7210.            +       newx( INT2( 550 ) ), newy( INT2( 325 ) ),
  7211.            +       newx( INT2( 700 ) ), newy( INT2( 425 ) ) )
  7212.             END
  7213.  
  7214.  Note that setlinestyle resets the line pattern to solid. If you omit this
  7215.  routine, the first rectangle would be drawn with dashes instead of a solid
  7216.  line.
  7217.  
  7218.  The ellipse routine draws an ellipse using parameters similar to those for
  7219.  the rectangle routine, both requiring a fill flag and two corners of a
  7220.  bounding rectangle. (Figure 8.1 in Chapter 8 shows how an ellipse uses a
  7221.  bounding rectangle.)
  7222.  
  7223.  The $GFILLINTERIOR flag fills the shape with the current fill pattern. To
  7224.  create a pattern, you must pass the address of an eight-byte array of
  7225.  unsigned bytes to the setfillmask routine. Then diagmask is initialized with
  7226.  the pattern shown in Table 9.1.
  7227.  
  7228.  Table 9.1  Fill Patterns
  7229.  ───────────────────────────────────────────────────────────────────────────
  7230.  
  7231.              Bit Pattern                Value in diagmask
  7232.  Bit No.     7  6  5  4  3  2  1  0
  7233.  
  7234.              █        █        █  █     diagmask(0) = #93
  7235.  
  7236.              █  █        █        █     diagmask(1) = #C9
  7237.  
  7238.                 █  █        █           diagmask(2) = #64
  7239.  
  7240.              █     █  █        █        diagmask(3) = #B2
  7241.  
  7242.                 █     █  █        █     diagmask(4) = #59
  7243.  
  7244.                    █     █  █           diagmask(5) = #2C
  7245.  
  7246.              █        █     █  █        diagmask(6) = #96
  7247.  
  7248.                 █        █     █  █     diagmask(7) = #4B
  7249.  
  7250.  
  7251.  9.1.3.5  Exiting Graphics Mode
  7252.  
  7253.  The final routine called by the SINE program, the endprogram, waits for the
  7254.  ENTER key to be pressed and then sets the screen back to normal:
  7255.  
  7256.       CC  ENDPROGRAM - This subroutine waits for the ENTER key to
  7257.       CC               be pressed, then resets the screen before
  7258.       CC               returning.
  7259.  
  7260.             SUBROUTINE endprogram()
  7261.  
  7262.             INCLUDE 'FGRAPH.FD'
  7263.             INTEGER*2  dummy
  7264.  
  7265.             READ (*,*)      ! Wait for ENTER to be pressed
  7266.             dummy = setvideomode( $DEFAULTMODE )
  7267.             END
  7268.  
  7269.  Note that resetting the screen is an important step in any graphics program.
  7270.  Other applications may make assumptions about your monitor and its
  7271.  resolution with unpredictable results. These assumptions could conflict with
  7272.  any changes your program made to the current graphics mode. Resetting to the
  7273.  original mode resolves any potential conflicts.
  7274.  
  7275.  
  7276.  9.2  Adding Color
  7277.  
  7278.  The Microsoft FORTRAN Graphics Library supports CGA, EGA, and VGA color
  7279.  graphics. Color can add variety and impact to your graphics, but it must be
  7280.  suited to your application.
  7281.  
  7282.  Color graphics can be an improvement over black and white, but using color
  7283.  requires a compromise. When you request the maximum number of colors, you
  7284.  sacrifice some resolution──a maximum resolution of 320-by-200 pixels instead
  7285.  of a higher resolution. For example, the program COLOR (see Section
  7286.  9.2.1.5) always selects the highest possible resolution. In a color mode,
  7287.  the program always creates a screen only 320 pixels wide and 200 pixels
  7288.  high.
  7289.  
  7290.  
  7291.  9.2.1  Color Graphics Modes
  7292.  
  7293.  The Microsoft FORTRAN Graphics Library has graphics modes particular to each
  7294.  of the CGA, EGA, and VGA adapters. In addition, higher resolution hardware
  7295.  can support the lower resolution modes. That is, EGA and VGA hardware can
  7296.  both display the CGA modes, and VGA hardware can also display EGA modes. Any
  7297.  hardware that supports color graphics modes also supports the
  7298.  black-and-white graphics modes.
  7299.  
  7300.  
  7301.  9.2.1.1  CGA Color Graphics Modes
  7302.  
  7303.  The CGA color graphics modes $MRES4COLOR and $MRESNOCOLOR display four
  7304.  colors selected from one of several predefined color palettes. They display
  7305.  these foreground colors against a background color, which can be any one of
  7306.  the 16 available colors. With the CGA hardware, the palette of foreground
  7307.  colors is predefined and cannot be changed. Each palette number is an
  7308.  integer, as shown in Table 9.2.
  7309.  
  7310.  Table 9.2  Available CGA Colors
  7311.  
  7312.                                Color Index
  7313.  
  7314.       Palette
  7315.       Number        1               2                 3
  7316.       0             Green           Red               Brown
  7317.       1             Cyan            Magenta           Light gray
  7318.       2             Light green     Light red         Yellow
  7319.       3             Light cyan      Light magenta     White
  7320.  
  7321.  On black-and-white monitors, the $MRESNOCOLOR graphics mode produces
  7322.  palettes containing various shades of gray. It displays colors when used
  7323.  with a color display. However, only two palettes are available with a color
  7324.  display. You can use the selectpalette routine to select one of these
  7325.  predefined palettes. Table 9.3 shows the $MRESNOCOLOR color indexes and
  7326.  palettes.
  7327.  
  7328.  Table 9.3  CGA Colors:  $MRESNOCOLOR Mode
  7329.  
  7330.                                 Color Index
  7331.       Palette
  7332.       Number        1               2             3
  7333.       0             Blue            Red           Light gray
  7334.       1             Light blue      Light red     White
  7335.  
  7336.  The selectpalette routine works only with the graphics modes $MRES4COLOR and
  7337.  $MRESNOCOLOR. To change palettes in other graphics modes, use the
  7338.  remappalette or remapallpalette functions.
  7339.  
  7340.  The following program sets the video mode to $MRES4COLOR and then cycles
  7341.  through the background colors and palette combinations. It works on
  7342.  computers equipped with CGA, EGA, MCGA, or VGA cards and requires a color
  7343.  monitor.
  7344.  
  7345.       CC  CGA.FOR - Demonstrates CGA colors.
  7346.  
  7347.             INCLUDE  'FGRAPH.FI'
  7348.             INCLUDE  'FGRAPH.FD'
  7349.  
  7350.             INTEGER*2 dummy2, i, j, k
  7351.             INTEGER*4 dummy4
  7352.             INTEGER*4 bkcolor(8) /
  7353.            +          $BLACK, $BLUE   , $GREEN, $CYAN,
  7354.            +          $RED  , $MAGENTA, $BROWN, $WHITE /
  7355.  
  7356.             CHARACTER*7  bkcolorname(8) /
  7357.            +             'BLACK', 'BLUE'   , 'GREEN', 'CYAN',
  7358.            +             'RED'  , 'MAGENTA', 'BROWN', 'WHITE' /
  7359.  
  7360.             RECORD / rccoord / curpos
  7361.  
  7362.             IF( setvideomode( $MRES4COLOR ) .EQ. 0 )
  7363.            +    STOP 'Error:  cannot set CGA graphics mode'
  7364.  
  7365.             DO i = 0, 3
  7366.                dummy2 = selectpalette( i )
  7367.                DO k = 1, 8
  7368.                   dummy4 = setbkcolor( bkcolor(k) )
  7369.                   DO j = 0, 3
  7370.                      CALL settextposition( 1, 1, curpos )
  7371.                      WRITE (*, 9000) bkcolorname(k), i, j
  7372.                      dummy2 = setcolor( INT4( j ) )
  7373.                      dummy2 = rectangle( $GFILLINTERIOR,
  7374.            +                             160, 100, 320, 200 )
  7375.                      READ (*,*)     ! Wait for ENTER to be pressed
  7376.                   END DO
  7377.                END DO
  7378.             END DO
  7379.             dummy2 = setvideomode( $DEFAULTMODE )
  7380.  
  7381.        9000 FORMAT( ' background color: ', A / ' palette:', I3 /
  7382.            +        ' color:  ', I3 / )
  7383.  
  7384.             END
  7385.  
  7386.  
  7387.  9.2.1.2  Color Mixing
  7388.  
  7389.  At the beginning of this chapter, we mentioned the difference between color
  7390.  indexes and color values. Imagine an analogy: a painter owns 64 tubes of
  7391.  paint but has a palette only large enough to hold 16 globs of paint. A
  7392.  painting created under these constraints could contain only 16 colors
  7393.  (selected from a total of 64).
  7394.  
  7395.  One of the EGA graphics modes ($ERESCOLOR) is similar: 16 color indexes
  7396.  chosen from a total of 64 color values. Color indexes are sometimes called
  7397.  "color attributes," or "pixel values"; color values are sometimes called
  7398.  "actual colors."
  7399.  
  7400.  The VGA offers the widest variety of color values: 262,144 (256K). The VGA
  7401.  palette size may contain 2, 16, or 256 color indexes, depending on the
  7402.  graphics mode. When you select a color value, you specify a level of
  7403.  intensity with a range of 0-63 for each of the red, green, and blue color
  7404.  values. The long integer that defines a color value consists of four bytes
  7405.  (32 bits),
  7406.  
  7407.       MSB                             LSB
  7408.       zzzzzzzz zzBBBBBB zzGGGGGG zzRRRRRR
  7409.  
  7410.  where z  refers to zero and B, G, and R  represent the bit values for blue,
  7411.  green, and red intensities. The most significant byte (MSB ) must contain
  7412.  all zeros. The two high bits in the remaining three bytes must also be 0. To
  7413.  mix a light red (pink), turn red all the way up and mix in some green and
  7414.  blue:
  7415.  
  7416.       00000000 00100000 00100000 00111111
  7417.  
  7418.  In hexadecimal notation this number equals #0020203F. You could also use the
  7419.  statement function
  7420.  
  7421.       RGB (r,g,b) = (#3f3f3f.AND.(ISHFT(b,16).OR.ISHFT(9,8).OR.r))
  7422.  
  7423.  where r, g, and b  were previously declared as integers.
  7424.  
  7425.  You can pass decimal values (more familiar and intuitive to most of us) to
  7426.  this macro. Keep in mind that 1 (binary 00000001) represents a low color
  7427.  intensity and that 63 (binary 00111111) equals full color intensity. Then,
  7428.  to create pure yellow (100-percent red plus 100-percent green) and assign it
  7429.  to a variable y1, use this line:
  7430.  
  7431.             y1 = RGB( 63, 63, 0 )
  7432.  
  7433.  For white, turn all of the colors on:
  7434.  
  7435.             RGB( 63, 63, 63 )
  7436.  
  7437.  For black, set all of the colors to 0:
  7438.  
  7439.             RGB( 0, 0, 0 )
  7440.  
  7441.  Mixing colors in EGA modes is similar to the mixing described above, but
  7442.  there are fewer intensities for the red, green, and blue components. In the
  7443.  modes that offer 64 colors, the R, G, and B  values cover only two bits and
  7444.  can therefore range from decimal 0 to 3. The integer that defines an RGB
  7445.  color looks like this:
  7446.  
  7447.       MSB                             LSB
  7448.       zzzzzzzz zzBB???? zzGG???? zzRR????
  7449.  
  7450.  The bits marked z must be zeros and the bits marked with question marks can
  7451.  be any value (although zeros tend to improve readability). To form a pure
  7452.  red color value, you would use the hexadecimal constant #00000030. For cyan
  7453.  (blue plus green), use  #00303000. The RGB statement function defined above
  7454.  is easily modified for EGA monitors:
  7455.  
  7456.             EGARGB (r,g,b) = ( #303030 .AND.1   ( ISHFT( b,20 )
  7457.            + .OR.ISHFT( g,12 ).OR.ISHFT( r,4 ) ) )
  7458.  
  7459.  In this statement function, you would pass values in the range of 0-3
  7460.  instead of 0-63. You could now assign the pure red as
  7461.  
  7462.             r1 = EGARGB( 0,0,3 )
  7463.  
  7464.  
  7465.  9.2.1.3  EGA Color Graphics Modes
  7466.  
  7467.  The $MRES16COLOR, $HRES16COLOR, or $ERESCOLOR video modes display color
  7468.  graphics best with an EGA adapter. The CGA modes will also display on the
  7469.  EGA adapter, but with lower resolution and decreased color options.
  7470.  
  7471.  The remappalette routine assigns a new color value to a color index. For
  7472.  example, when you first enter an EGA graphics mode, color index 1 equals the
  7473.  color value blue. To reassign the pure red color value to color index 1, you
  7474.  could use this line:
  7475.  
  7476.             dummy4 = remappalette( 1, #000030 )
  7477.  
  7478.  Or, use the symbolic constant $RED, which is defined in the FGRAPH.FI file:
  7479.  
  7480.             dummy4 = remappalette( 1, $RED )
  7481.  
  7482.  After this routine call, any object currently drawn in color index 1 will
  7483.  instantly switch from blue to red.
  7484.  
  7485.  For EGA graphics, the first value is an integer in the range of 0-15, and
  7486.  the second value is an INTEGER*4 defined as a mixture of red, green, and
  7487.  blue.
  7488.  
  7489.  The remapallpalette routine changes all of the color indexes simultaneously.
  7490.  You pass it an array of color values. The first color value in the list
  7491.  becomes the new color associated with the color index 0, the second becomes
  7492.  associated with the color index 1, and so on.
  7493.  
  7494.  The argument passed to routines that set colors (such as setcolor) is the
  7495.  index for a color in the current palette. In the default text palette, an
  7496.  index of 1 refers to blue. When a palette changes, a color's index number
  7497.  also changes. As a result, the color produced by a given index number also
  7498.  changes. If you create a drawing in one palette and then change the palette,
  7499.  the color indexes will suddenly refer to different colors and the entire
  7500.  drawing will change color. The number of  color indexes available depends on
  7501.  the number of colors supported by the current video mode.
  7502.  
  7503.  The remappalette and remapallpalette routines work in all modes but only
  7504.  with the EGA, MCGA, or VGA hardware. The routines remappalette and
  7505.  remapallpalette fail and return a value of -1 if you attempt to remap a
  7506.  palette without the necessary hardware.
  7507.  
  7508.  The following program draws a rectangle with a red interior. In the default
  7509.  EGA palette, color index 4 is red. In the program EGA, this color index is
  7510.  changed to $BLUE.
  7511.  
  7512.       CC  EGA.FOR - Demonstrates use of EGA palettes.
  7513.  
  7514.             INCLUDE 'FGRAPH.FI'
  7515.             INCLUDE 'FGRAPH.FD'
  7516.  
  7517.             INTEGER*2        dummy2
  7518.             INTEGER*4        dummy4
  7519.             RECORD /xycoord/ xy
  7520.  
  7521.             dummy2 = setvideomode( $ERESCOLOR )
  7522.             dummy2 = setcolor( 4 )
  7523.             dummy2 = rectangle( $GFILLINTERIOR, 50, 50, 200, 200 )
  7524.       C
  7525.       C     Display normal palette message.
  7526.       C
  7527.             CALL settextposition( 1, 1, xy )
  7528.             CALL outtext( 'Normal palette   ')
  7529.             CALL outtext( 'Press  ENTER to continue')
  7530.             READ (*,*)          ! Wait for ENTER to be pressed
  7531.             dummy4 = remappalette( 4, $BLUE )
  7532.       C
  7533.       C     Display new palette message.
  7534.       C
  7535.             CALL settextposition( 1, 1, xy )
  7536.             CALL outtext( 'Remapped palette ')
  7537.             CALL outtext( 'Press ENTER to continue')
  7538.             READ (*,*)
  7539.             dummy4 = remappalette( 4, $RED )
  7540.       C
  7541.       C     Display original palette message.
  7542.       C
  7543.             CALL settextposition( 1, 1, xy )
  7544.             CALL outtext( 'Restored palette ')
  7545.             CALL outtext( 'Press ENTER to clear the screen')
  7546.             READ (*,*)
  7547.       C
  7548.       C     Return to original video mode.
  7549.       C
  7550.             CALL clearscreen( $GCLEARSCREEN )
  7551.             dummy2 = setvideomode( $DEFAULTMODE )
  7552.             END
  7553.  
  7554.  
  7555.  9.2.1.4  VGA Color Graphics Modes
  7556.  
  7557.  The VGA card adds graphics modes $VRES2COLOR, $VRES16COLOR, and
  7558.  $MRES256COLOR to your repertoire. EGA and CGA modes are available with the
  7559.  VGA hardware, providing either lower resolution or fewer color choices.
  7560.  
  7561.  The VGA color graphics modes operate with a range of 262,144 (256K) color
  7562.  values. The graphics mode $VRES2COLOR displays 2 colors, the graphics mode
  7563.  $VRES16COLOR displays 16 colors, and the graphics mode $MRES256COLOR
  7564.  displays 256 colors from the available VGA colors.
  7565.  
  7566.  The remappalette routine changes a color index to a specified color value.
  7567.  The following function remaps the color index 1 to the color value given by
  7568.  the symbolic constant $RED. After this statement is executed, whatever was
  7569.  displayed as blue will now appear as red:
  7570.  
  7571.       remappalette( 1, dummy 4=$RED )  ! Reassign color index 1
  7572.                                        ! to VGA red
  7573.  
  7574.  The remapallpalette routine remaps one or more color indexes simultaneously.
  7575.  The routine's argument references an array of color values that reflect the
  7576.  remapping. The first color number in the list becomes the new color
  7577.  associated with color index 0, the second with color index 1, and so on.
  7578.  
  7579.  Symbolic constants (names) for the default color numbers are supplied so
  7580.  that the remapping of VGA colors is compatible with EGA practice. The names
  7581.  are self-descriptive: the color numbers for black, light yellow, and red are
  7582.  represented by the symbolic constants $BLACK, $LIGHTYELLOW, and $RED.
  7583.  
  7584.  All of the VGA display modes operate with any VGA monitor. Colors appear as
  7585.  shades of gray on compatible monochrome monitors.
  7586.  
  7587.  The example program HORIZON illustrates the impact possible with the full
  7588.  range of 256 colors available with a VGA card:
  7589.  
  7590.       CC  HORIZON.FOR - Illustrates VGA graphics with cycling of
  7591.       CC                256 colors.
  7592.  
  7593.             INCLUDE 'FGRAPH.FI'
  7594.             INCLUDE 'FGRAPH.FD'
  7595.  
  7596.             INTEGER*2   MYRED, MYBLU, MYWHT, STEP
  7597.             PARAMETER ( MYRED = #000003FF )
  7598.             PARAMETER ( MYBLU = #003F0000 )
  7599.             PARAMETER ( MYWHT = #003F3F3F )
  7600.             PARAMETER ( STEP  = 21 )
  7601.  
  7602.             INTEGER*2        dummy, i, j
  7603.             INTEGER*4        rainbow(0:511), col, ngray
  7604.  
  7605.  
  7606.       RECORD /rccoord/ curpos
  7607.             RECORD /xycoord/ xy
  7608.       C
  7609.       C     Check to see if adapter can handle 256 colors.
  7610.       C
  7611.             IF( setvideomode( $MRES256COLOR ) .EQ. 0 )
  7612.            +    STOP 'This program requires a VGA card.'
  7613.       C
  7614.       C     Create the colors.
  7615.       C
  7616.             DO col = 0, 63
  7617.                ngray = ( col .OR. ISHFT( col,8 ) )
  7618.            +                .OR. ISHFT( col,16 )
  7619.                rainbow( col)            = MYBLU .AND. ngray
  7620.                rainbow( col + 256)      = rainbow( col )
  7621.                rainbow( col + 64)       = MYBLU .OR. ngray
  7622.                rainbow( col + 64 + 256) = rainbow( col + 64 )
  7623.                rainbow( col + 128)      = MYRED .OR.
  7624.            +                           ( MYWHT .AND. .NOT. ngray )
  7625.                rainbow( col + 128 + 256) = rainbow( 64 + 128 )
  7626.                rainbow( col + 192)       = MYRED .AND. .NOT. ngray
  7627.                rainbow( col + 192 + 256) = rainbow( col + 192 )
  7628.             END DO
  7629.             CALL setvieworg( 160, 85, xy )
  7630.       C
  7631.       C     Draw shapes on screen.
  7632.       C
  7633.             DO i = 0, 254
  7634.                dummy = setcolor( INT4( 255 - i ) )
  7635.                CALL    moveto(  i, i - 255, xy )
  7636.                dummy = lineto( -i, 255 - i )
  7637.                CALL    moveto( -i, i - 255, xy )
  7638.                dummy = lineto(  i, 255 - i )
  7639.                dummy = ellipse( $GBORDER, -i, -i / 2, i, i / 2 )
  7640.             END DO
  7641.       C
  7642.       C     Cycle through the colors.
  7643.       C
  7644.             i = 0
  7645.             DO j = 1, 256
  7646.                dummy = remapallpalette( rainbow(i) )
  7647.                i     = MOD( i + STEP, 256 )
  7648.             END DO
  7649.  
  7650.             dummy = settextcolor( 15 )
  7651.             CALL settextposition( 25, 1, curpos )
  7652.             CALL outtext( 'Press ENTER to exit')
  7653.             READ (*,*)
  7654.             dummy = setvideomode( $DEFAULTMODE )
  7655.             END
  7656.  
  7657.  
  7658.  9.2.1.5  Color Graphics Programs (COLOR and GRAPHIC)
  7659.  
  7660.  The sample program COLOR sets a mode with as many colors as possible for the
  7661.  available hardware:
  7662.  
  7663.       CC  COLOR.FOR - Sets a medium resolution mode
  7664.       CC              with maximum color choices.
  7665.  
  7666.             INCLUDE 'FGRAPH.FI'
  7667.             INCLUDE 'FGRAPH.FD'
  7668.  
  7669.             INTEGER*2            dummy
  7670.             RECORD /videoconfig/ vc
  7671.  
  7672.       C
  7673.       C     Set mode for maximum number of colors.
  7674.       C
  7675.             IF( setvideomode( $MAXCOLORMODE ) .EQ. 0 )
  7676.            +    STOP 'Error:  no color graphics capability'
  7677.             CALL getvideoconfig( vc )
  7678.  
  7679.             WRITE (*, 9000) vc.numcolors, vc.numxpixels,
  7680.            +                vc.numypixels
  7681.             READ (*,*)       ! Wait for ENTER to be pressed
  7682.             CALL clearscreen( $GCLEARSCREEN )
  7683.             dummy = setvideomode( $DEFAULTMODE )
  7684.  
  7685.        9000 FORMAT( ' available colors: ', I5 /
  7686.            +        ' horizontal pixels:', I5 /
  7687.            +        ' vertical pixels:  ', I5 )
  7688.             END
  7689.  
  7690.  Use the routine clearscreen, which clears the screen in any video mode). To
  7691.  view every possible graphics mode, run the program GRAPHIC shown below.
  7692.  Explanations of various color graphics modes (CGA, EGA, and VGA) follow.
  7693.  
  7694.       CC  GRAPHIC.FOR - Displays every graphics mode.
  7695.  
  7696.             INCLUDE  'FGRAPH.FI'
  7697.             INCLUDE  'FGRAPH.FD'
  7698.  
  7699.             INTEGER*2 key
  7700.             EXTERNAL  printmenu
  7701.             EXTERNAL  showmode
  7702.  
  7703.             CALL printmenu( key )
  7704.             DO WHILE( key .NE. 0 )
  7705.                CALL showmode( key )
  7706.             END DO
  7707.             END
  7708.  
  7709.       SUBROUTINE printmenu( key )
  7710.  
  7711.             INCLUDE  'FGRAPH.FD'
  7712.  
  7713.             INTEGER*2  dummy, key
  7714.  
  7715.             key = -1
  7716.             DO WHILE( (key .LT. 0)  .OR.  (key .GT. 12) )
  7717.                dummy = setvideomode( $DEFAULTMODE )
  7718.                WRITE (*, 9000)
  7719.                READ (*,*) key
  7720.             END DO
  7721.  
  7722.        9000 FORMAT( ' Please ENTER a graphics mode.' /
  7723.            +        ' ( To exit, ENTER 0. )' /// ' 0 Exit' /
  7724.            +        '  1 $MRES4COLOR'   / '  2 $MRESNOCOLOR' /
  7725.            +        '  3 $HRESBW'       / '  4 $HERCMONO'    /
  7726.            +        '  5 $MRES16COLOR'  / '  6 $HRES16COLOR' /
  7727.            +        '  7 $ERESNOCOLOR'  / '  8 $ERESCOLOR'   /
  7728.            +        '  9 $VRES2COLOR'   / ' 10 $VRES16COLOR' /
  7729.            +        ' 11 $MRES256COLOR' / ' 12 $ORESCOLOR'   / )
  7730.             END
  7731.  
  7732.  
  7733.             SUBROUTINE showmode( which )
  7734.  
  7735.             INCLUDE  'FGRAPH.FD'
  7736.  
  7737.             INTEGER*2 which, dummy, i, height, width
  7738.             INTEGER*2 modes(12) /
  7739.            +   $MRES4COLOR, $MRESNOCOLOR, $HRESBW, $HERCMONO ,
  7740.            +   $MRES16COLOR, $HRES16COLOR, $ERESNOCOLOR,
  7741.            +   $ERESCOLOR, $VRES2COLOR, $VRES16COLOR,
  7742.            +   $MRES256COLOR, $ORESCOLOR /
  7743.  
  7744.             RECORD /videoconfig/ screen
  7745.  
  7746.             IF( setvideomode( modes(which) ) .NE. 0 ) THEN
  7747.                CALL getvideoconfig( screen )
  7748.                width  = screen.numxpixels / screen.numcolors
  7749.                height = screen.numypixels / 2
  7750.                DO i = 0, screen.numcolors - 1
  7751.                   dummy = setcolor( INT4( i ) )
  7752.                   dummy = rectangle( $GFILLINTERIOR, i * width, 0,
  7753.            +                       ( i + 1 ) * width, height )
  7754.                END DO
  7755.             ELSE
  7756.                WRITE (*, 9000)
  7757.             END IF
  7758.  
  7759.       READ (*,*)       ! Wait for ENTER to be pressed
  7760.             dummy = setvideomode( $DEFAULTMODE )
  7761.             CALL printmenu( which )
  7762.  
  7763.        9000 FORMAT ( ' Video mode is not available.' /
  7764.            +         ' Please press ENTER.   ' / )
  7765.             END
  7766.  
  7767.  
  7768.  9.2.2  Using the Color Video Text Modes
  7769.  
  7770.  Two color video text modes, $TEXTC40 and  $TEXTC80, work with the CGA, EGA,
  7771.  and VGA displays. These modes display steady or blinking text in any one of
  7772.  the 16 foreground colors with any one of the 8 background colors.
  7773.  
  7774.  In a video text mode, each displayed character requires two bytes of video
  7775.  memory. The first byte contains the ASCII code representing the character;
  7776.  the second byte contains the display attribute. In the CGA color video text
  7777.  modes, the attribute byte determines the color and whether or not it will
  7778.  blink. Sixteen colors are available: the CGA color values, and the default
  7779.  EGA and VGA color values. Since the EGA and VGA palette can be remapped,
  7780.  these values can correspond to any set of 16 colors with the appropriate
  7781.  palette mapping.
  7782.  
  7783.  
  7784.  9.2.2.1  Using Text Colors
  7785.  
  7786.  Use gettextcolor and getbkcolor to find the current text mode's foreground
  7787.  and background colors. Values in the range 0-15 represent normal colors.
  7788.  Values in the range of 16-31 are the same colors as those in the range 0-15,
  7789.  but with blinking text.  Set the foreground and background colors with
  7790.  settextcolor and setbkcolor. Both use a single argument specifying the color
  7791.  value for text displayed with outtext. The text mode color indexes are
  7792.  defined in Table 9.4.
  7793.  
  7794.  Table 9.4  Text Colors
  7795.  
  7796.       Number   Color       Number    Color
  7797.  
  7798.       0        Black       8         Dark gray
  7799.       1        Blue        9         Light blue
  7800.       2        Green       10        Light green
  7801.       3        Cyan        11        Light cyan
  7802.       4        Red         12        Light red
  7803.       5        Magenta     13        Light magenta
  7804.       6        Brown       14        Light brown
  7805.       7        White       15        Light white
  7806.  
  7807.  Use settextposition to move the cursor to a particular row and column for
  7808.  displaying text. The outtext routine prints the text on the screen.
  7809.  
  7810.  
  7811.  9.2.2.2  Text Color Program (COLTEXT)
  7812.  
  7813.  The following program displays a chart showing all possible combinations of
  7814.  text and background colors.
  7815.  
  7816.       CC  COLTEXT.FOR - Displays text color with various color or
  7817.       CC                monochrome attributes.
  7818.  
  7819.             INCLUDE 'FGRAPH.FI'
  7820.             INCLUDE 'FGRAPH.FD'
  7821.  
  7822.             INTEGER*2          dummy2, blink, fgd
  7823.             INTEGER*4          dummy4, bgd
  7824.             CHARACTER*2        str
  7825.             RECORD / rccoord / curpos
  7826.  
  7827.             CALL clearscreen( $GCLEARSCREEN )
  7828.             CALL outtext('Text color/monochrome attributes:')
  7829.  
  7830.             DO  blink = 0, 16, 16
  7831.                DO bgd = 0, 7
  7832.                   dummy4 = setbkcolor( bgd )
  7833.                   CALL settextposition( INT2( bgd ) +
  7834.            +          ( ( blink / 16 ) * 9) + 3, 1, curpos )
  7835.                   dummy2 = settextcolor( 15 )
  7836.                   WRITE (str, '(I2)') bgd
  7837.                   CALL outtext( 'Back:' // str // '  Fore:')
  7838.       C
  7839.       C         Loop through 16 foreground colors. For monochrome,
  7840.       C         these will be underscore and low/high intensity.
  7841.       C
  7842.                   DO fgd = 0, 15
  7843.                      dummy2 = settextcolor( fgd + blink )
  7844.                      WRITE ( str, '(I2)' ) fgd + blink
  7845.                      CALL outtext( '  ' // str )
  7846.                   END DO
  7847.                END DO
  7848.             END DO
  7849.  
  7850.             WRITE (*, '(///// A \)') ' Press ENTER to exit . . . '
  7851.             READ (*,*)
  7852.             dummy2 = setvideomode( $DEFAULTMODE )
  7853.             END
  7854.  
  7855.  
  7856.  9.3  Understanding Coordinate Systems
  7857.  
  7858.  Chapter 8, "Graphics Library Routines," introduced the general concepts
  7859.  behind the different coordinate systems available to the Microsoft FORTRAN
  7860.  Graphics Library. Each system performs a particular task and uses
  7861.  coordinates appropriate to that function. Text coordinates work in rows and
  7862.  columns; physical coordinates serve as an absolute reference and as a
  7863.  starting place for creating custom window and viewport coordinates. As a
  7864.  convenience, the Microsoft FORTRAN Graphics Library supports several
  7865.  routines for converting to the different coordinate systems.
  7866.  
  7867.  
  7868.  9.3.1  Text Coordinates
  7869.  
  7870.  Before you can write a program to print a word on the screen, you need a
  7871.  system that describes to the compiler where you want to write the text. The
  7872.  text modes divide the text screen into rows and columns (see Figure 9.2).
  7873.  
  7874.  Keep in mind these text-mode conventions:
  7875.  
  7876.    ■  Numbering starts at 1. An 80-column screen contains columns 1-80.
  7877.    ■  The row is always listed before the column.
  7878.  
  7879.  If the screen supports a video text mode that displays 25 rows and 80
  7880.  columns (as in Figure 9.2), the rows are numbered 1-25 and the columns are
  7881.  numbered 1-80. The text-positioning routines, such as settextposition, use
  7882.  row and column coordinates.
  7883.  
  7884.  
  7885.  9.3.2  Graphics Coordinates
  7886.  
  7887.  As stated in Chapter 8, "Graphics Library Routines," there are three
  7888.  coordinate systems for describing the location of pixels on the screen:
  7889.  physical coordinates, viewport coordinates, and window coordinates. The
  7890.  coordinate systems identify pixel locations on the screen. They all apply
  7891.  the following conventions:
  7892.  
  7893.    ■  Numbering starts at 0, not 1. If there are 640 pixels, they are
  7894.       numbered 0-639.
  7895.    ■  The - x-coordinate is listed before the y-coordinate.
  7896.  
  7897.  Sections 9.3.2.1-9.3.2.3 describe each coordinate system in detail.
  7898.  
  7899.  
  7900.  9.3.2.1  Physical Coordinates
  7901.  
  7902.  Suppose you write a program that calls setvideomode and puts the screen into
  7903.  the VGA graphics mode $VRES16COLOR. This gives you a screen containing 640
  7904.  horizontal pixels and 480 vertical pixels. Each individual pixel is referred
  7905.  to by its location relative to the x-axis and y-axis, as shown in Figure
  7906.  9.3 below.
  7907.  
  7908.  The upper left corner is the "origin." The x- and y-coordinates for the
  7909.  origin are always (0, 0).
  7910.  
  7911.  Physical coordinates refer to each pixel directly and are therefore integers
  7912.  (that is, the screen cannot display a fractional pixel). If you use
  7913.  variables to refer to pixel locations, declare them as integers.
  7914.  
  7915.  When you first enter graphics mode, the "viewport" or drawing area is
  7916.  equivalent to the physical screen. The setvieworg routine changes the
  7917.  location of the viewport's origin. You pass it two integers, which represent
  7918.  the x and y physical screen coordinates for the new origin. For example, the
  7919.  following line moves the origin to the physical screen location (50, 100):
  7920.  
  7921.             CALL setvieworg(50, 100)
  7922.  
  7923.  The effect on the screen is illustrated in Figure 9.4 below.
  7924.  
  7925.  The number of pixels hasn't changed, but the coordinates used to refer to
  7926.  the points have changed. The x axis now ranges from -50 to +589 instead of 0
  7927.  to 639. The y axis now covers the values -100 to +379. If you use an adapter
  7928.  other than the VGA, the numbers are different but the effect is the same.
  7929.  
  7930.  All graphics routines that use viewport coordinates are affected by the new
  7931.  origin, including moveto, lineto, rectangle, ellipse, arc, and pie. For
  7932.  example, if you call the rectangle routine after relocating the viewport
  7933.  origin, and pass it the values (0, 0) and (40, 40), the upper left corner of
  7934.  the rectangle would appear 50 pixels from the left edge of the screen and
  7935.  100 pixels from the top. It would not appear in the upper left corner of the
  7936.  screen.
  7937.  
  7938.  The setcliprgn routine creates an invisible rectangular area on the screen
  7939.  called a "clipping region." You can draw inside the clipping region, but
  7940.  attempts to draw outside the region fail (that is, nothing appears outside
  7941.  the clipping region).
  7942.  
  7943.  The default clipping region occupies the entire screen. The graphics library
  7944.  ignores any attempts to draw outside the screen.
  7945.  
  7946.  Change the clipping region by calling setcliprgn. For example, suppose you
  7947.  entered the CGA graphics mode $MRES4COLOR, which has a screen resolution of
  7948.  320 by 200 pixels. If you draw a diagonal line from (0, 0) to (319, 199),
  7949.  the top left to the bottom right corner, the screen looks like Figure 9.5.
  7950.  
  7951.  You could create a clipping region by entering
  7952.  
  7953.             CALL setcliprgn(10, 10, 309, 189)
  7954.  
  7955.  With the clipping region in effect, the same lineto command would put the
  7956.  line shown in Figure 9.6 on the screen. The dashed lines indicate the outer
  7957.  bounds of the clipping region and do not actually print on the screen.
  7958.  
  7959.  
  7960.  9.3.2.2  Viewport Coordinates
  7961.  
  7962.  The viewport is the area on the screen where you actually draw. Viewport
  7963.  coordinates represent the pixels within the current viewport. The
  7964.  setviewport routine establishes a new viewport within the boundaries of the
  7965.  physical screen. A standard viewport has two distinguishing features:
  7966.  
  7967.    1. The origin of a viewport is in the upper left corner.
  7968.  
  7969.    2. The default clipping region matches the outer boundaries of the
  7970.       viewport.
  7971.  
  7972.  The setviewport routine has the same effect as the setvieworg and setcliprgn
  7973.  routines combined.
  7974.  
  7975.  In Figure 9.5 the clipping region allows a call to lineto to draw a line
  7976.  that touches the rectangle's opposite corners. Figure 9.6 uses the same
  7977.  lineto call, but a smaller clipping region keeps the line from touching the
  7978.  surrounding rectangle.
  7979.  
  7980.  Note that you must first establish a viewport if you wish to use window
  7981.  coordinates. Window coordinates use the current viewport as their
  7982.  boundaries. The sample program REALG.FOR in Section 9.3.3 shows how to
  7983.  create multiple window-coordinate sets, each in a separate viewport, on a
  7984.  single screen.
  7985.  
  7986.  
  7987.  9.3.2.3  Window Coordinates
  7988.  
  7989.  Functions that refer to coordinates on the physical screen and within the
  7990.  viewport require integer values. However, in many applications you may need
  7991.  to use floating-point values──for frequency, viscosity, mass, and so on. The
  7992.  setwindow routine allows you to scale the screen to almost any size. In
  7993.  addition, window-related functions accept double-precision values.
  7994.  
  7995.  A window "overlays" the current viewport; window graphics appear in the
  7996.  portion of screen defined as the current viewport.
  7997.  
  7998.  For example, you may want to graph 12 months of average Venusian
  7999.  temperatures that range from -50 to +450. You could do so by adding the
  8000.  following line to your program:
  8001.  
  8002.             dummy = setwindow(.TRUE., 1.0, -50.0, 12.0, 450.0)
  8003.  
  8004.  The first argument is the invert flag, which puts the lowest y value in the
  8005.  bottom left corner. The minimum x- and y- and maximum x- and y-coordinates
  8006.  follow; the decimal point marks them as floating-point values. The new
  8007.  organization of the screen is shown in Figure 9.7.
  8008.  
  8009.  Note that January and December plot on the left and right edges of the
  8010.  screen. In an application like this, it might be better to number the x-axis
  8011.  from 0.0 to 13.0, to provide some extra space.
  8012.  
  8013.  If you next plot a point with setpixel_w or draw a line with lineto_w, the
  8014.  values are automatically scaled to the established window.
  8015.  
  8016.  To use window coordinates with floating-point values, take the following
  8017.  steps:
  8018.  
  8019.    1. Enter a graphics mode with setvideomode.
  8020.  
  8021.    2. Use setviewport to create a viewport area. This step is optional if you
  8022.       plan to use the entire screen.
  8023.  
  8024.    3. Create a real-coordinate window with setwindow, passing a LOGICAL
  8025.       invert flag and four DOUBLE PRECISION x- and y-coordinates for the
  8026.       minimum and maximum values.
  8027.  
  8028.    4. Draw graphics shapes with rectangle_w and similar routines. Do not
  8029.       confuse rectangle (the viewport routine) with rectangle_w (the window
  8030.       routine for drawing rectangles). All window functions end with an
  8031.       underscore (_) and the letter "w."
  8032.  
  8033.  Real-coordinate graphics give you much flexibility. For example, you can fit
  8034.  either axis into a small range (such as 151.25-151.45) or into a large range
  8035.  (-50000.-+80000.), depending on the type of data you graph. In addition, by
  8036.  changing the window coordinates, you can create the effects of zooming in or
  8037.  panning across a figure.
  8038.  
  8039.  
  8040.  9.3.3  Real Coordinates Program (REALG)
  8041.  
  8042.  The program below illustrates some ways to use the real-coordinate windowing
  8043.  functions.
  8044.  
  8045.       CC  REALG.FOR - Illustrates real coordinate graphics.
  8046.  
  8047.             INCLUDE  'FGRAPH.FI'
  8048.             INCLUDE  'FGRAPH.FD'
  8049.  
  8050.             LOGICAL  fourcolors
  8051.             EXTERNAL fourcolors
  8052.  
  8053.             IF( fourcolors() ) THEN
  8054.                CALL threegraphs()
  8055.             ELSE
  8056.               WRITE (*,*) ' This program requires a CGA, EGA, or',
  8057.            +              ' VGA graphics card.'
  8058.             END IF
  8059.             END
  8060.  
  8061.       C     Additional functions defined below
  8062.       .
  8063.       .
  8064.       .
  8065.  
  8066.  
  8067.  The main body of the program is very short. It calls the fourcolors
  8068.  function (defined below), which attempts to enter a graphics mode with at
  8069.  least four colors. If it succeeds, the threegraphs subroutine is called,
  8070.  which will draw three graphs. See the program output in Figure 9.8.
  8071.  
  8072.  Note that the gridshape subroutine (defined below) which draws the graphs
  8073.  uses the same data in each case. However, the program uses three different
  8074.  real-coordinate windows. The two viewports in the top half are the same size
  8075.  in physical coordinates, but they have different window sizes. Each window
  8076.  uses different maximum and minimum values. In all three cases, the grid is 2
  8077.  units wide. In the upper left corner, the window is 4 units wide; in the
  8078.  upper right, the window is 6 units wide, which makes the graph appear
  8079.  smaller.
  8080.  
  8081.  In two of the three graphs, one of the lines goes off the edge, outside the
  8082.  clipping region. The lines do not intrude into the other viewports, since
  8083.  defining a viewport creates a clipping region.
  8084.  
  8085.  Finally, note that the graph on the bottom inverts the data with respect to
  8086.  the two graphs above it.
  8087.  
  8088.  
  8089.  9.3.3.1  Checking the Adapter
  8090.  
  8091.  The first step in any graphics program is to enter a graphics mode. The
  8092.  function fourcolors  performs this step:
  8093.  
  8094.       CC  FOURCOLORS - Function to enter graphics mode for REALG.
  8095.  
  8096.             LOGICAL FUNCTION fourcolors()
  8097.  
  8098.             INCLUDE 'FGRAPH.FD'
  8099.  
  8100.             INTEGER*2            dummy
  8101.             RECORD /videoconfig/ screen
  8102.             COMMON               screen
  8103.  
  8104.       C
  8105.       C     Set to maximum number of available colors.
  8106.       C
  8107.             CALL getvideoconfig( screen )
  8108.             SELECT CASE( screen.adapter )
  8109.                CASE( $CGA, $OCGA )
  8110.                   dummy = setvideomode( $MRES4COLOR )
  8111.                CASE( $EGA, $OEGA )
  8112.                   dummy = setvideomode( $ERESCOLOR )
  8113.                CASE( $VGA, $OVGA )
  8114.                   dummy = setvideomode( $VRES16COLOR )
  8115.                CASE DEFAULT
  8116.                   dummy = 0
  8117.             END SELECT
  8118.  
  8119.             CALL getvideoconfig( screen )
  8120.             fourcolors = .TRUE.
  8121.             IF( dummy .EQ. 0 ) fourcolors = .FALSE.
  8122.             END
  8123.  
  8124.  The getvideoconfig routine transfers screen information into the videoconfig
  8125.  structure screen. Then the element screen.adapter in the SELECT CASE
  8126.  construct turns on the matching graphics mode. The modes containing the
  8127.  letter "O" are Olivetti modes.
  8128.  
  8129.  The function fourcolors returns .TRUE. if the computer supports color.
  8130.  Otherwise it returns .FALSE., which causes the program to skip the
  8131.  subroutine threegraphs.
  8132.  
  8133.  
  8134.  9.3.4  Drawing the Graphs
  8135.  
  8136.  If the fourcolors function returns .TRUE., the main program calls the
  8137.  subroutine below, which prints the three graphs.
  8138.  
  8139.       CC  THREEGRAPHS - Displays three graphs for REALG.
  8140.  
  8141.             SUBROUTINE threegraphs()
  8142.  
  8143.             INCLUDE  'FGRAPH.FD'
  8144.  
  8145.             INTEGER*2            dummy, halfx, halfy
  8146.             INTEGER*2            xwidth, yheight, cols, rows
  8147.             RECORD /videoconfig/ screen
  8148.             COMMON               screen
  8149.  
  8150.             CALL clearscreen( $GCLEARSCREEN )
  8151.             xwidth  = screen.numxpixels
  8152.             yheight = screen.numypixels
  8153.             cols    = screen.numtextcols
  8154.             rows    = screen.numtextrows
  8155.             halfx   = xwidth / 2
  8156.             halfy   = (yheight / rows) * ( rows / 2 )
  8157.       C
  8158.       C     First window
  8159.       C
  8160.             CALL setviewport( 0, 0, halfx - 1, halfy - 1 )
  8161.             CALL settextwindow( 1, 1, rows / 2, cols / 2 )
  8162.             dummy = setwindow( .FALSE., -2.0, -2.0, 2.0, 2.0 )
  8163.             CALL gridshape( INT2( rows / 2 ) )
  8164.             dummy = rectangle( $GBORDER, 0, 0, halfx-1, halfy-1 )
  8165.       C
  8166.       C     Second window
  8167.       C
  8168.             CALL setviewport( halfx, 0, xwidth - 1, halfy - 1 )
  8169.             CALL settextwindow( 1, (cols/2) + 1, rows/2, cols)
  8170.             dummy = setwindow( .FALSE., -3.0, -3.0, 3.0, 3.0 )
  8171.             CALL gridshape( INT2( rows / 2 ) )
  8172.             dummy = rectangle_w( $GBORDER, -3.0, -3.0, 3.0, 3.0 )   C
  8173.       C     Third window
  8174.       C
  8175.             CALL setviewport( 0, halfy, xwidth - 1, yheight - 1 )
  8176.             CALL settextwindow( (rows / 2 ) + 1, 1, rows, cols )
  8177.             dummy = setwindow( .TRUE., -3.0, -1.5, 1.5, 1.5 )
  8178.             CALL gridshape( INT2( (rows / 2) + MOD( rows, 2 ) ) )
  8179.             dummy = rectangle_w( $GBORDER, -3.0, -1.5, 1.5, 1.5 )
  8180.  
  8181.       READ (*,*)         ! Wait for ENTER to be pressed
  8182.             dummy = setvideomode( $DEFAULTMODE )
  8183.             END
  8184.  
  8185.  Although entering a graphics mode automatically clears the screen, it
  8186.  doesn't hurt to be sure, so threegraphs calls the clearscreen routine:
  8187.  
  8188.             CALL clearscreen( $GCLEARSCREEN )
  8189.  
  8190.  The $GCLEARSCREEN constant clears the entire physical screen. Other options
  8191.  include $GVIEWPORT and $GWINDOW, which clear the current viewport and the
  8192.  current text window, respectively.
  8193.  
  8194.  After assigning values to some variables, the threegraphs routine creates
  8195.  the first window:
  8196.  
  8197.             CALL setviewport( 0, 0, halfx - 1, halfy - 1 )
  8198.             CALL settextwindow( 1, 1, rows / 2, cols / 2 )
  8199.             dummy = setwindow( .FALSE., -2.0, -2.0, 2.0, 2.0 )
  8200.  
  8201.  The first line defines a viewport which covers the upper left quarter of the
  8202.  screen. Next, a text window is defined within the boundaries of that border.
  8203.  Note that the numbering starts at 1 and the row location precedes the
  8204.  column. Finally, the third line creates a window with both x and y values
  8205.  ranging from -2.0 to 2.0. The .FALSE. constant forces the y-axis to increase
  8206.  from top to bottom, which is the reverse of the "normal" convention.
  8207.  
  8208.  Next, the function gridshape inserts the grid and plots the data, and a
  8209.  border is added to the window:
  8210.  
  8211.             CALL gridshape( INT2( rows / 2 ) )
  8212.             dummy = rectangle( $GBORDER, 0, 0,
  8213.            +                   halfx - 1, halfy - 1 )
  8214.  
  8215.  Note that this is the standard rectangle routine, which takes coordinates
  8216.  relative to the viewport, not window coordinates.
  8217.  
  8218.  The two other windows are similar to the first. All three windows call the
  8219.  gridshape function (defined below), which draws a grid from location (-1.0,
  8220.  -1.0) to (1.0, 1.0). The grid appears in different sizes because the
  8221.  coordinates in the windows vary. The second window ranges from (-3.0, -3.0)
  8222.  to (3.0, 3.0), and the third from (-3.0,-1.5) to (1.5, 1.5), so the widths
  8223.  change accordingly.
  8224.  
  8225.  Also note that the third window contains a .TRUE. inversion argument. This
  8226.  causes the y-axis to increase from bottom to top, instead of top to bottom.
  8227.  As a result, this graph appears upside down with respect to the other two.
  8228.  
  8229.  After calling gridshape, the program frames each window, using a statement
  8230.  such as the following:
  8231.  
  8232.       dummy = rectangle_w( $GBORDER, -3.0, -1.5, 1.5, 1.5 )
  8233.  
  8234.  All three functions contain a fill flag as the first argument. The routine
  8235.  rectangle takes integer arguments that refer to the viewport coordinates.
  8236.  The rectangle_w routine takes four double-precision floating-point values
  8237.  referring to window coordinates: upper left x, upper left y, lower right x,
  8238.  and lower right y.
  8239.  
  8240.  The gridshape subroutine plots the data on the screen:
  8241.  
  8242.       CC  GRIDSHAPE - This subroutine plots data for the REALG
  8243.       CC              program.
  8244.  
  8245.             SUBROUTINE gridshape( numc )
  8246.  
  8247.             INCLUDE 'FGRAPH.FD'
  8248.  
  8249.             INTEGER*2            dummy, numc, i
  8250.             CHARACTER*2          str
  8251.             DOUBLE PRECISION     bananas(21), x
  8252.             RECORD /videoconfig/ screen
  8253.             RECORD /wxycoord/    wxy
  8254.             RECORD /rccoord/     curpos
  8255.             COMMON               screen
  8256.       C
  8257.       C     Data for the graph:
  8258.       C
  8259.             DATA bananas/ -0.3  , -0.2 , -0.224, -0.1, -0.5  ,
  8260.            +               0.21 ,  2.9 ,  0.3  ,  0.2,  0.0  ,
  8261.            +              -0.885, -1.1 , -0.3  , -0.2,  0.001,
  8262.            +               0.005,  0.14,  0.0  , -0.9, -0.13 ,
  8263.            +               0.31 /
  8264.  
  8265.       C
  8266.       C     Print colored words on the screen.
  8267.       C
  8268.             IF(screen.numcolors .LT. numc)
  8269.            +                numc = screen.numcolors-1
  8270.             DO i = 1, numc
  8271.                CALL settextposition( i, 2, curpos )
  8272.                dummy = settextcolor( i )
  8273.                WRITE ( str, '(I2)' ) i
  8274.                CALL outtext( 'Color ' // str )
  8275.             END DO
  8276.       C
  8277.       C     Draw a bordered rectangle around the graph.
  8278.       C
  8279.  
  8280.             dummy = setcolor( 1 )
  8281.             dummy = rectangle_w( $GBORDER, -1.00, -1.00, 1.00,
  8282.            +                                1.00 )
  8283.             dummy = rectangle_w( $GBORDER, -1.02, -1.02, 1.02,
  8284.            +                                1.02 )
  8285.       C
  8286.       C     Plot the points.
  8287.       C
  8288.             x = -0.90
  8289.             DO i = 1, 19
  8290.                dummy = setcolor( 2 )
  8291.                CALL    moveto_w( x, -1.0, wxy )
  8292.                dummy = lineto_w( x,  1.0 )
  8293.                CALL    moveto_w( -1.0, x, wxy )
  8294.                dummy = lineto_w(  1.0, x )
  8295.                dummy = setcolor( 14 )
  8296.                CALL    moveto_w( x - 0.1, bananas( i ), wxy )
  8297.                dummy = lineto_w( x, bananas( i + 1 ) )
  8298.                x     = x + 0.1
  8299.             END DO
  8300.  
  8301.             CALL    moveto_w( 0.9, bananas( i ), wxy )
  8302.             dummy = lineto_w( 1.0, bananas( i + 1 ) )
  8303.             dummy = setcolor( 3 )
  8304.             END
  8305.  
  8306.  First, the number of available color indexes is assigned to the rows
  8307.  variable and a DO loop displays all of the available colors:
  8308.  
  8309.       IF(screen.numcolors .LT. numc) numc = screen.numcolors - 1
  8310.             DO i = 1, numc
  8311.                CALL settextposition( i, 2, curpos )
  8312.                dummy = settextcolor( i )
  8313.                WRITE ( str, '(I2)' ) i
  8314.                CALL outtext( 'Color ' // str )
  8315.             END DO
  8316.  
  8317.  The names of the functions are self-explanatory. Using outtext in graphics
  8318.  mode  allows you to control the text color and position (unlike WRITE).
  8319.  
  8320.  The routine names that end with "_w" work the same as their viewport
  8321.  equivalents, except that you pass double-precision floating-point values
  8322.  instead of integers. For example, you pass integers to lineto, but double
  8323.  precision values to lineto_w.
  8324.  
  8325.  Once you create various graphic elements, you may wish to use the
  8326.  font-oriented routines to polish the appearance of titles, headings,
  8327.  comments, or labels. The next chapter describes in more detail how to print
  8328.  text in the various fonts supplied with the Microsoft FORTRAN Graphics
  8329.  Library.
  8330.  
  8331.  
  8332.  Chapter 10  Using Fonts from the Graphics Library
  8333.  ───────────────────────────────────────────────────────────────────────────
  8334.  
  8335.  The Microsoft FORTRAN Graphics Library includes DOS routines that print text
  8336.  in various sizes and type styles. These routines provide much more control
  8337.  over the appearance of your text than the WRITE statement; they add visual
  8338.  interest to your screen displays.
  8339.  
  8340.  A "font" is a set of stylized text characters of a particular size. This
  8341.  chapter assumes you have read Chapter 9, "Drawing Graphics Elements," and
  8342.  that you understand the general terminology it introduces. You should also
  8343.  be familiar with the basic properties of both the setvideomode and moveto
  8344.  routines.
  8345.  
  8346.  The first section of this chapter reviews the fonts provided with the
  8347.  FORTRAN Graphics Library and some of the associated terminology. The next
  8348.  two sections cover the actual process of registering, setting, and using
  8349.  fonts in the graphics environment. The last section describes problems
  8350.  commonly encountered in using fonts and suggests solutions.
  8351.  
  8352.  
  8353.  10.1  Available Typefaces
  8354.  
  8355.  The Microsoft FORTRAN Graphics Library includes six typefaces. A "typeface"
  8356.  (or "type style") refers to the style of the displayed text──Courier, for
  8357.  example, or Times Roman. The list below shows the typefaces available with
  8358.  Microsoft FORTRAN.
  8359.  
  8360.  "Type size" measures the screen area occupied by individual characters. The
  8361.  term comes from the printer's lexicon, but uses screen pixels as the unit of
  8362.  measure rather than the traditional "points." For example, "Courier 129"
  8363.  denotes the Courier typeface, with each character occupying a screen area of
  8364.  12 vertical pixels by 9 horizontal pixels. The word "font," therefore,
  8365.  implies both a typeface and a type size.
  8366.  
  8367.  The graphic library's font routines use two methods to create fonts. The
  8368.  first technique generates Courier, Helv, and Tms Rmn fonts through a
  8369.  "bit-mapping" (or "raster-mapping") technique. Bit-mapping describes each
  8370.  character in a binary data "map." Each bit in the map corresponds to a
  8371.  screen pixel. If the bit equals 1, its associated pixel is set to the
  8372.  current screen color. Bit values of 0 appear in the current background
  8373.  color. Video adapters use this same technique to display text in graphics
  8374.  mode.
  8375.  
  8376.  The three remaining type styles──Modern, Script, and Roman──use a
  8377.  "vector-mapping" technique to create the fonts. Vector-mapping represents
  8378.  each of the characters as lines and arcs. In a literal sense, the computer
  8379.  draws each vector-mapped character on the screen. In contrast, bit-mapping
  8380.  resembles stenciling or placing a picture of each character on the screen.
  8381.  
  8382.  Each method has advantages and disadvantages. Bit-mapped characters appear
  8383.  smoother because of the predetermined pixel-mapping. However, they cannot be
  8384.  scaled. You can scale vector-mapped text to any size, but the characters
  8385.  tend to lack the solid appearance of the bit-mapped characters.
  8386.  
  8387.  Table 10.1 lists available sizes for each font. Notice that the bit-mapped
  8388.  fonts come in preset sizes measured in pixels. The exact size of any font
  8389.  character depends on screen resolution and display type.
  8390.  
  8391.  Table 10.1  Typefaces and Type Sizes in the FORTRAN Graphics Library
  8392.  
  8393.  Typeface      Mapping             Size (in pixels)     Spacing
  8394.  
  8395.  Courier       Bit                 108, 129, 1512       Fixed
  8396.  Helv          Bit                 105, 127, 158        Proportional
  8397.                                    189, 2212, 2816
  8398.  Tms Rmn       Bit                 105, 126, 158        Proportional
  8399.                                    169, 2012, 2616
  8400.  Modern        Vector              Scaled               Proportional
  8401.  Script        Vector              Scaled               Proportional
  8402.  Roman         Vector              Scaled               Proportional
  8403.  
  8404.  
  8405.  A.2  Using Microsoft FORTRAN Fonts
  8406.  
  8407.  Disk files with the .FON extension contain the data for both bit-mapped and
  8408.  vector-mapped fonts. The base names of the files indicate their content. For
  8409.  example, the files MODERN.FON, SCRIPT.FON, and ROMAN.FON hold data for the
  8410.  three vector-mapped fonts.
  8411.  
  8412.  FORTRAN's .FON files are identical to the .FNT files used in the Microsoft
  8413.  Windows operating environment. If you run Windows, you can use any of its
  8414.  .FNT files with FORTRAN's font functions. (You can also purchase Windows
  8415.  .FNT files separately.) In addition, several vendors offer software that
  8416.  create or modify .FNT files, allowing you to design your own fonts.
  8417.  
  8418.  To use the fonts in your program, you should
  8419.  
  8420.    1. Register the fonts
  8421.    2. Set a current font from the register
  8422.    3. Display text using the current font
  8423.  
  8424.  The following sections describe each of the steps in detail. See Section
  8425.  10.3 for an example program that demonstrates these steps.
  8426.  
  8427.  
  8428.  10.2.1  Registering Fonts
  8429.  
  8430.  You must first organize the fonts you want to use into a list in memory, a
  8431.  process called "registering." The register list gives the computer
  8432.  information about the available .FON files. Register the fonts by calling
  8433.  registerfonts. The routine reads header information from specified .FON
  8434.  files and builds a list of file information, but the routine does not read
  8435.  mapping data from the files.
  8436.  
  8437.  The FGRAPH.FD file declares the registerfonts routine as
  8438.  
  8439.             INTERFACE TO FUNCTION registerfonts(filename)
  8440.             INTEGER*2 registerfonts
  8441.            + [FAR, C, ALIAS:"__f_registerfonts"]
  8442.             CHARACTER*(*) filename[FAR, REFERENCE]
  8443.             END
  8444.  
  8445.  The argument refers to the file name of the desired .FON file. The name can
  8446.  include wild cards, which allow you to register several fonts with one call
  8447.  to the registerfonts routine.
  8448.  
  8449.  If the computer successfully reads one or more .FON files, registerfonts
  8450.  returns the number of fonts registered. If the function fails, it returns a
  8451.  negative error code. (Refer to Appendix D of the Microsoft FORTRAN Reference
  8452.  for a description of the error codes.)
  8453.  
  8454.  
  8455.  10.2.2  Setting the Font and Displaying Text
  8456.  
  8457.  Before the computer can display text in a particular font, it must know
  8458.  which of the fonts you want to use. After you register the fonts you expect
  8459.  to use, setfont makes one of the registered fonts the current (or "active")
  8460.  font. It then reads the mapping data from the appropriate .FON file into
  8461.  memory.
  8462.  
  8463.  The FGRAPH.FD include file declares the setfont routine as
  8464.  
  8465.             INTERFACE TO FUNCTION setfont(options)
  8466.             INTEGER*2 setfont[FAR, C, ALIAS:"__f_setfont"]
  8467.             CHARACTER*(*) options[FAR, REFERENCE]
  8468.             END
  8469.  
  8470.  The function's argument consists of letter codes that describe the desired
  8471.  font.
  8472.  
  8473.       Option                           Meaning
  8474.  
  8475.       t'fontname'                      Typeface of the font in single
  8476.                                        quotes. The fontname may be one
  8477.                                        of the following:
  8478.  
  8479.                                        courier          modern
  8480.                                        helv             script tms
  8481.                                        rmn              roman
  8482.  
  8483.                                        Notice the space in the name "tms
  8484.                                        rmn." Additional font files use
  8485.                                        other names for fontname. Refer
  8486.                                        to the vendor's documentation for
  8487.                                        these names.
  8488.  
  8489.       hy                               Character height, where y is the
  8490.                                        height in pixels.
  8491.  
  8492.       wx                               Character width, where x is the
  8493.                                        width in pixels.
  8494.  
  8495.       f                                Select only a fixed-spaced font.
  8496.  
  8497.       p                                Select only a proportional-spaced
  8498.                                        font.
  8499.  
  8500.       v                                Select only a vector-mapped font.
  8501.  
  8502.       r                                Select only a bit-mapped (or
  8503.                                        "raster-mapped") font.
  8504.  
  8505.       b                                Select the best fit from the
  8506.                                        registered fonts. The b option
  8507.                                        instructs setfont to accept the
  8508.                                        closest-fitting font if a font of
  8509.                                        the specified size is not
  8510.                                        registered.
  8511.  
  8512.                                        If at least one font is
  8513.                                        registered, the b option always
  8514.                                        sets a current font. If you do
  8515.                                        not specify the b option and an
  8516.                                        exact matching font is not
  8517.                                        registered, setfont will fail. In
  8518.                                        this case, any existing current
  8519.                                        font remains current.
  8520.  
  8521.                                        The best fit is based on four
  8522.                                        criteria: pixel height, typeface,
  8523.                                        pixel width, and spacing (fixed
  8524.                                        or proportional). If you request
  8525.                                        a vector-mapped font, setfont
  8526.                                        sizes the font to correspond with
  8527.                                        the specified pixel height and
  8528.                                        width; a bit-mapped font, setfont
  8529.                                        chooses the closest available
  8530.                                        size. If the requested type size
  8531.                                        fits exactly between two
  8532.                                        registered fonts, the smaller
  8533.                                        size takes precedence.
  8534.  
  8535.       nx                               Select font number x, where x is
  8536.                                        less than or equal to the value
  8537.                                        returned by registerfonts. For
  8538.                                        example, the option n3 makes the
  8539.                                        third registered font the current
  8540.                                        font (provided three or more
  8541.                                        fonts are registered).
  8542.  
  8543.  You can list the option codes in any order and in upper- or lowercase. The
  8544.  options may be separated with spaces.
  8545.  
  8546.  The setfont routine updates a data area with specifics about the current
  8547.  font. The data area stores the information in a structure defined by the
  8548.  include file FGRAPH.FD to have the following form:
  8549.  
  8550.       STRUCTURE/fontinfo/
  8551.          INTEGER       type        ! Set = vector,clear = bit map
  8552.          INTEGER       ascent      ! Pix dist from top to base
  8553.          INTEGER       pixwidth    ! Character width in pixels
  8554.          INTEGER       pixheight   ! Character height in pixels
  8555.          INTEGER       avgwidth    ! Average character width
  8556.          CHARACTER*81  filename    ! Filename including path
  8557.          CHARACTER*32  facename    ! Font name
  8558.       END STRUCTURE
  8559.  
  8560.  If you want the parameters of the current font, call the getfontinfo
  8561.  routine. Once you register the fonts you want and make one the active font,
  8562.  follow these two steps to display the text on the screen:
  8563.  
  8564.    1. Select a starting position for the text with the moveto routine.
  8565.  
  8566.    2. Send the text to the screen at that position (in the current font) with
  8567.       outgtext.
  8568.  
  8569.  The moveto routine takes pixel coordinates as arguments. Those coordinates
  8570.  are for the upper left corner of the cell of the first character in the
  8571.  string. The following section describes a sample program included with
  8572.  Microsoft FORTRAN that displays the provided fonts.
  8573.  
  8574.  
  8575.  10.3  Example Program (SAMPLER)
  8576.  
  8577.  SAMPLER displays sample text in the available fonts, returning to DOS when
  8578.  you press a key. First, make sure the .FON files are in the current
  8579.  directory.
  8580.  
  8581.       CC  SAMPLER.FOR - Displays sample text in various fonts.
  8582.       CC
  8583.  
  8584.             INCLUDE  'FGRAPH.FI'
  8585.             INCLUDE  'FGRAPH.FD'
  8586.  
  8587.             INTEGER*2            NFONTS
  8588.             INTEGER*2            dummy, i, iend
  8589.             CHARACTER*30         list
  8590.             CHARACTER*64         fontpath
  8591.             RECORD /videoconfig/ vc
  8592.             RECORD /xycoord/     xy
  8593.  
  8594.       PARAMETER ( NFONTS   = 6 )
  8595.  
  8596.             CHARACTER* ( 7 )  text ( 2 * NFONTS )/
  8597.            +                   "COURIER",       "courier" ,
  8598.            +                   "HELV"   ,       "helv"    ,
  8599.            +                   "TMS RMN",       "tms rmn" ,
  8600.            +                   "MODERN" ,       "modern"  ,
  8601.            +                   "SCRIPT" ,       "script"  ,
  8602.            +                   "ROMAN"  ,       "roman"   /
  8603.  
  8604.             CHARACTER*( 10 ) option (NFONTS) /
  8605.            +                   "t'courier'",    "t'helv'"  ,
  8606.            +                   "t'tms rmn'",    "t'modern'",
  8607.            +                   "t'script'" ,    "t'roman'" /
  8608.       C
  8609.       C     Locate .FON files and register fonts by reading header
  8610.       C     information from all files.
  8611.       C
  8612.             IF( registerfonts( '*.FON' ). LT. 0 ) THEN
  8613.            +  WRITE (*, '(A/)') ' Enter directory for .FON files:'
  8614.                READ  (*, '(A )')  fontpath
  8615.                iend = INDEX( fontpath, ' ' )
  8616.                fontpath(iend:iend + 5) = '\*.FON'
  8617.                IF( registerfonts( fontpath ). LT. 0 )
  8618.            +       STOP 'Error:  cannot find font files'
  8619.             ENDIF
  8620.  
  8621.       C
  8622.       C     Find graphics mode.
  8623.       C
  8624.             IF( setvideomode( $MAXRESMODE ) .EQ. 0 )
  8625.            +    STOP 'Error:  cannot set graphics mode'
  8626.  
  8627.       C
  8628.       C     Copy video configuration into structure vc.
  8629.       C
  8630.             CALL getvideoconfig( vc )
  8631.  
  8632.       C
  8633.       C     Display six lines of sample text.
  8634.       C
  8635.             DO i = 1, NFONTS
  8636.                list = option(i) // 'h30w24b'
  8637.                IF( setfont( list ) .EQ. 0 ) THEN
  8638.                   dummy = setcolor( INT4( i ) )
  8639.                   CALL moveto( 0, (i - 1) *
  8640.            +                vc.numypixels / NFONTS, xy )
  8641.                   CALL outgtext( text((i * 2) - 1) )
  8642.  
  8643.       CALL moveto( vc.numxpixels/2,
  8644.            +                (i - 1) * vc.numypixels / NFONTS, xy )
  8645.                   CALL outgtext( text(i * 2) )
  8646.             ELSE
  8647.                   dummy = setvideomode( $DEFAULTMODE )
  8648.                   STOP 'Error:  cannot set font'
  8649.                END IF
  8650.             END DO
  8651.  
  8652.             READ (*,*)
  8653.             dummy = setvideomode( $DEFAULTMODE )
  8654.       C
  8655.       C     Return memory when finished with fonts.
  8656.       C
  8657.             CALL unregisterfonts()
  8658.             END
  8659.  
  8660.  Notice that SAMPLER calls the setfont routine to specify the typeface and
  8661.  best fit for a character height of 30 pixels and a width of 24 pixels. Then
  8662.  the graphics routine moveto establishes the starting point for each text
  8663.  string. When the program finds the font, it sends a message to the screen.
  8664.  
  8665.  
  8666.  10.4  Using Fonts Effectively
  8667.  
  8668.  Printing with fonts is straightforward, and using fonts requires little
  8669.  programming effort. However, keep the following in mind when working with
  8670.  fonts:
  8671.  
  8672.    ■  The video mode should be set only once. If you create an image and want
  8673.       to incorporate font-based text into it, do not reset the video mode
  8674.       prior to calling the font routines. Doing so will clear the screen,
  8675.       which destroys the original image.
  8676.  
  8677.    ■  The setfont function reads specified .FON files to obtain mapping data
  8678.       for the current font. Each call to setfont overwrites the old font data
  8679.       in memory. If you want to show text of different styles on the same
  8680.       screen, display all of the text of one font before moving on to the
  8681.       others. Minimizing the number of calls to setfont reduces the time
  8682.       spent in disk I/O and memory reloads.
  8683.  
  8684.    ■  When your program finishes with the fonts library, you might wish to
  8685.       free the memory occupied by the register list. Call the subroutine
  8686.       unregisterfonts to do this. As its name implies, this subroutine frees
  8687.       the memory allocated by registerfonts. The register information for
  8688.       each type size of each font takes up approximately 140 bytes of memory,
  8689.       so the amount of memory returned by unregisterfonts is significant only
  8690.       if you have many fonts registered.
  8691.  
  8692.  For additional syntax and usage information on each of the font routines,
  8693.  read the appropriate material on individual routines in the following
  8694.  chapter,  "Graphics Library Reference."
  8695.  
  8696.  
  8697.  Chapter 11  Graphics Library Reference
  8698.  ───────────────────────────────────────────────────────────────────────────
  8699.  
  8700.  This chapter describes each routine in the Microsoft FORTRAN DOS graphics
  8701.  library, GRAPHICS.LIB, in alphabetical order. The text-based routines are
  8702.  also supported under OS/2 by the library GRTEXTP.LIB, as noted in the text
  8703.  and in Chapter 8. In some cases, similar or related routines are clustered
  8704.  in the same description, with differences noted where appropriate.
  8705.  
  8706.  The name of each routine appears at the top of the page. The Interface
  8707.  section shows the complete interface needed in order to use the routine,
  8708.  although you will find it more convenient to reference the include file
  8709.  FGRAPH.FD──which contains the same declarations──than to recreate each
  8710.  interface yourself. The Description section outlines what the routine does,
  8711.  along with any pertinent additional information. The Return Value section
  8712.  describes any values returned by the routine. Such values can help in
  8713.  testing for errors before you use the results of the routine call. The See
  8714.  Also section lists similar or related routines. Finally, the Example section
  8715.  provides a typical application of the routine, or refers you to a routine
  8716.  with the same or similar application. (This section does not appear with
  8717.  every reference entry.)
  8718.  
  8719.  
  8720.  arc, arc_w
  8721.  
  8722.  ■  Interface
  8723.  
  8724.       INTERFACE TO FUNCTION arc(x1, y1, x2, y2, x3, y3, x4, y4)
  8725.       INTEGER*2 arc[FAR,
  8726.       C, ALIAS:"__arc"] INTEGER*2 x1, y1      ! Upper left corner of bounding
  8727.       INTEGER*2 x2, y2                        ! Lower right corner of bounding
  8728.       INTEGER*2 x3, y3                        ! Start vector
  8729.       INTEGER*2 x4, y4                        ! End vector
  8730.       END
  8731.  
  8732.       INTERFACE TO FUNCTION arc_w(wx1, wy1, wx2, wy2, wx3, wy3, wx4, wy4)
  8733.       INTEGER*2 arc_w[FAR, C, ALIAS:"__f_arc_w"]
  8734.       DOUBLE PRECISION wx1, wy1               ! Upper left corner of bounding
  8735.       DOUBLE PRECISION wx2, wy2               ! Lower right corner of bounding
  8736.       DOUBLE PRECISION wx3, wy3               ! Start vector
  8737.       DOUBLE PRECISION wx4, wy4               ! End vector
  8738.       END
  8739.  
  8740.  ■  Description
  8741.  
  8742.  The arc routines draw elliptical arcs.
  8743.  
  8744.  The arc routine uses the viewport-coordinate system. The center of the arc
  8745.  is the center of the bounding rectangle defined by the points (x1, y1) and
  8746.  (x2, y2). The arc starts at the point where it intersects the vector defined
  8747.  by (x3, y3) and ends where it intersects the vector defined by (x4, y4).
  8748.  
  8749.  The arc_w routine uses the window-coordinate system. The center of the arc
  8750.  is the center of the bounding rectangle defined by the window-coordinate
  8751.  pairs (wx1, wy1) and (wx2, wy2). The arc starts at the point where it
  8752.  intersects the vector defined by (wx3, wy3)  and ends where it intersects
  8753.  the vector defined by (wx4, wy4).
  8754.  
  8755.  In both cases, the arc is drawn using the current color, moving
  8756.  counterclockwise. Since an arc does not define a closed area, it is not
  8757.  filled.
  8758.  
  8759.  ■  Return value
  8760.  
  8761.  The arc and arc_w routines return a nonzero value if the arc is successfully
  8762.  drawn; otherwise, they return 0.
  8763.  
  8764.  ■  See also
  8765.  
  8766.       ellipse, lineto, pie, rectangle, setcolor
  8767.  
  8768.  ■  Example
  8769.  
  8770.             INCLUDE   'FGRAPH.FI'
  8771.             INCLUDE   'FGRAPH.FD'
  8772.             INTEGER*2 dummy
  8773.  
  8774.             dummy = setvideomode( $MRES16COLOR )
  8775.             dummy = arc( 80, 50, 240, 150, 0, 50, 240, 150 )
  8776.             READ (*,*)          ! Press ENTER to exit
  8777.             dummy = setvideomode( $DEFAULTMODE )
  8778.             END
  8779.  
  8780.  This program draws the arc shown in Figure R.1.
  8781.  
  8782.  See also the example program for setpixel.
  8783.  
  8784.  
  8785.  clearscreen
  8786.  
  8787.  ■  Interface
  8788.  
  8789.       INTERFACE TO SUBROUTINE
  8790.     + clearscreen[FAR, C, ALIAS:"__clearscreen"](area)
  8791.       INTEGER*2 area                   ! Target area
  8792.       END
  8793.  
  8794.  ■  Description
  8795.  
  8796.  The clearscreen subroutine erases the target area, filling it with the
  8797.  current background color. The area parameter can be one of the following
  8798.  symbolic constants (defined in FGRAPH.FD):
  8799.  
  8800.       Constant                     Action
  8801.  
  8802.       $GCLEARSCREEN               Clears and fills the entire
  8803.                                   screen
  8804.  
  8805.       $GVIEWPORT                  Clears and fills only within the
  8806.                                   current viewport
  8807.  
  8808.       $GWINDOW                    Clears and fills only within the
  8809.                                   current text window
  8810.  
  8811.  This subroutine is also available under OS/2.
  8812.  
  8813.  ■  Return value
  8814.  
  8815.  There is no return value.
  8816.  
  8817.  ■  See also
  8818.  
  8819.       getbkcolor, setbkcolor
  8820.  
  8821.  ■  Example
  8822.  
  8823.  See the example program for gettextcolor and setvieworg.
  8824.  
  8825.  
  8826.  displaycursor
  8827.  
  8828.  ■  Interface
  8829.  
  8830.       INTERFACE TO FUNCTION displaycursor(toggle)
  8831.       INTEGER*2 displaycursor[FAR, C, ALIAS:"__displaycursor"]
  8832.       INTEGER*2 toggle               ! Cursor state
  8833.       END
  8834.  
  8835.  ■  Description
  8836.  
  8837.  On entry into each graphics routine, the screen cursor is turned off. The
  8838.  displaycursor function determines whether the cursor will be turned back on
  8839.  when programs exit graphic routines. If toggle is set to $GCURSORON, the
  8840.  cursor will be restored on exit. If toggle is set to $GCURSOROFF, the cursor
  8841.  will be left off.
  8842.  
  8843.  This function is also available under OS/2.
  8844.  
  8845.  ■  Return value
  8846.  
  8847.  Returns the previous value of toggle.
  8848.  
  8849.  ■  See also
  8850.  
  8851.       gettextcursor, settextcursor
  8852.  
  8853.  ■  Example
  8854.  
  8855.  See the example program for settextcursor.
  8856.  
  8857.  
  8858.  ellipse, ellipse_w
  8859.  
  8860.  ■  Interface
  8861.  
  8862.       INTERFACE TO FUNCTION ellipse(control, x1, y1, x2, y2)
  8863.       INTEGER*2 ellipse[FAR, C, ALIAS:"__ellipse"]
  8864.       INTEGER*2 control                  ! Fill flag
  8865.       INTEGER*2 x1, y1                   ! Upper left corner of bounding recta
  8866.       INTEGER*2 x2, y2                   ! Lower right corner of bounding rect
  8867.       END
  8868.  
  8869.       INTERFACE TO FUNCTION ellipse_w(control, wx1, wy1, wx2, wy2)
  8870.       INTEGER*2 ellipse_w[FAR, C, ALIAS:"__f_ellipse_w"]
  8871.       INTEGER*2 control                  ! Fill flag
  8872.       DOUBLE PRECISION wx1, wy1          ! Upper left corner of bounding recta
  8873.       DOUBLE PRECISION wx2, wy2          ! Lower right corner of bounding rect
  8874.       END
  8875.  
  8876.  ■  Description
  8877.  
  8878.  The ellipse functions draw an ellipse. The border is drawn in the current
  8879.  color. In the ellipse function, the center of the ellipse is the center of
  8880.  the bounding rectangle defined by the viewport-coordinate points (x1, y1)
  8881.  and (x2, y2).
  8882.  
  8883.  In the ellipse_w function, the center of the ellipse is the center of the
  8884.  bounding rectangle defined by the window-coordinate points (wx1, wy1) and
  8885.  (wx2, wy2).
  8886.  
  8887.  If the bounding-rectangle arguments define a point or a vertical or
  8888.  horizontal line, no figure is drawn.
  8889.  
  8890.  The control argument can be one of the following symbolic constants:
  8891.  
  8892.        Constant                    Action
  8893.  
  8894.        $GFILLINTERIOR              Fills the ellipse using the
  8895.                                    current fill mask
  8896.  
  8897.        $GBORDER                    Does not fill the ellipse
  8898.  
  8899.  The control option given by $GFILLINTERIOR is equivalent to a subsequent
  8900.  call to the floodfill function using the center of the ellipse as the start
  8901.  point and the current color (set by setcolor) as the boundary color.
  8902.  
  8903.  ■  Return value
  8904.  
  8905.  The ellipse and ellipse_w functions return a nonzero value if the ellipse is
  8906.  drawn successfully; otherwise, they return 0.
  8907.  
  8908.  ■  See also
  8909.  
  8910.       arc, floodfill, lineto, pie, rectangle, setcolor, setfillmask
  8911.  
  8912.  ■  Example
  8913.  
  8914.             INCLUDE   'FGRAPH.FI'
  8915.             INCLUDE   'FGRAPH.FD'
  8916.             INTEGER*2 dummy
  8917.  
  8918.             dummy = setvideomode( $MRES16COLOR )
  8919.             dummy = ellipse( $GFILLINTERIOR, 80, 50, 240, 150 )
  8920.             READ (*,*)          ! Press ENTER to exit
  8921.             dummy = setvideomode( $DEFAULTMODE )
  8922.             END
  8923.  
  8924.  This program draws the shape shown in Figure R.2.
  8925.  
  8926.  See also the example program for setpixel and setvieworg.
  8927.  
  8928.  
  8929.  floodfill, floodfill_w
  8930.  
  8931.  ■  Interface
  8932.  
  8933.       INTERFACE TO FUNCTION floodfill(x, y, boundary)
  8934.       INTEGER*2 floodfill[FAR, C, ALIAS:"__floodfill"]
  8935.       INTEGER*2 x, y            ! Start point
  8936.       INTEGER*2 boundary        ! Fills boundary color
  8937.       END
  8938.  
  8939.       INTERFACE TO FUNCTION floodfill_w(wx, wy, boundary)
  8940.       INTEGER*2 floodfill_w[FAR, C, ALIAS:"__f_floodfill_w"]
  8941.       DOUBLE PRECISION wx, wy    ! Start point
  8942.       INTEGER*2 boundary         ! Fills boundary color
  8943.       END
  8944.  
  8945.  ■  Description
  8946.  
  8947.  These functions fill an area using the current color and fill mask.
  8948.  
  8949.  The floodfill function begins filling at the viewport-coordinate point (x,
  8950.  y).
  8951.  
  8952.  The floodfill_w function begins filling at the window-coordinate point (wx,
  8953.  wy).
  8954.  
  8955.  If this point lies inside a figure, the interior is filled; if it lies
  8956.  outside a figure, the background is filled. The point must be inside or
  8957.  outside the figure to be filled, not on the figure boundary itself. Filling
  8958.  occurs in all directions, stopping at the color of boundary.
  8959.  
  8960.  ■  Return value
  8961.  
  8962.  The floodfill and floodfill_w functions return a nonzero value if the fill
  8963.  is successful. They return 0 if the fill could not be completed; if the
  8964.  start point lies on the boundary color; or if the start point lies outside
  8965.  the clipping region.
  8966.  
  8967.  ■  See also
  8968.  
  8969.       ellipse, getcolor, getfillmask, pie, setcliprgn, setcolor, setfillmask
  8970.  
  8971.  ■  Example
  8972.  
  8973.  See the example program for setlinestyle.
  8974.  
  8975.  
  8976.  getactivepage
  8977.  
  8978.  ■  Interface
  8979.  
  8980.       INTERFACE TO FUNCTION getactivepage()
  8981.       INTEGER*2 getactivepage[FAR, C, ALIAS:"__getactivepage"]
  8982.       END
  8983.  
  8984.  ■  Description
  8985.  
  8986.  The getactivepage function returns the current active page number.
  8987.  
  8988.  ■  Return value
  8989.  
  8990.  Returns the page number of the current active page. All hardware
  8991.  combinations support at least one page (page number 0).
  8992.  
  8993.  This function is also available under OS/2.
  8994.  
  8995.  ■  See also
  8996.  
  8997.       getactivepage, gettextcolor, gettextposition, getvisualpage,
  8998.       outtext, settextcolor,  settextposition, settextwindow, setvideomode,
  8999.       setvisualpage, wrapon
  9000.  
  9001.  ■  Example
  9002.  
  9003.       CC    PAGE.FOR - Illustrates animation effects by changing the video pag
  9004.       CC             The video page functions demonstrated include:
  9005.       CC             getactivepage  getvisualpage  setactivepage  setvisualpag
  9006.  
  9007.             INCLUDE  'FGRAPH.FI'
  9008.             INCLUDE  'FGRAPH.FD'
  9009.  
  9010.             INTEGER*2        dummy, oldapage, oldvpage
  9011.             INTEGER*2        i, j, k, l
  9012.             CHARACTER*3      jumper(4,3)
  9013.             RECORD /rccoord/ curpos
  9014.  
  9015.             DATA jumper / '\o/', '_o_', ' o ', ' o ',
  9016.            +              ' O ', ' O ', '/O\', ' O ',
  9017.            +              '/ \', '( )', '/ \', '( )' /
  9018.  
  9019.             oldapage  = getactivepage()
  9020.             oldvpage  = getvisualpage()
  9021.             IF( setvideomode( $TEXTBW40 ) .EQ. 0 )
  9022.            +    STOP 'Error:  cannot set 40-column mode'
  9023.             dummy     = displaycursor( $GCURSOROFF )
  9024.  
  9025.       C
  9026.       C     Draw 24 images on each page.
  9027.       C
  9028.             DO i = 1, 4
  9029.                dummy = setactivepage( i - 1 )
  9030.                DO j = 1, 22, 7
  9031.                   DO k = 1, 36, 7
  9032.                      DO l = 0, 2
  9033.  
  9034.       CALL settextposition( j + l, k, curpos )
  9035.                         CALL outtext( jumper(i,l + 1) )
  9036.                      END DO
  9037.                   END DO
  9038.                END DO
  9039.             END DO
  9040.  
  9041.       C
  9042.       C     Cycle 10 times through pages 0-3.
  9043.       C
  9044.             DO i = 1, 10
  9045.                DO j = 0, 3
  9046.                   dummy = setvisualpage( j )
  9047.                   CALL delay( INT2( 10 ) )
  9048.                END DO
  9049.             END DO
  9050.  
  9051.       C
  9052.       C     Restore original page.
  9053.       C
  9054.             dummy = setvideomode( $DEFAULTMODE )
  9055.             dummy = setactivepage( oldapage )
  9056.             dummy = setvisualpage( oldvpage )
  9057.             END
  9058.  
  9059.  
  9060.       CC  DELAY - Pauses for a specified number of 1/100 seconds.
  9061.       CC
  9062.       CC  Params:  Wait - pause time in 0.01 seconds
  9063.  
  9064.             SUBROUTINE delay( wait )
  9065.             INTEGER*2 wait, tick0, tick1, tick, kount, dummy
  9066.  
  9067.             kount = 0
  9068.             CALL GETTIM( dummy, dummy, dummy, tick0 )
  9069.             DO WHILE( kount .LT. wait )
  9070.                CALL GETTIM( dummy, dummy, dummy, tick1 )
  9071.                tick = tick1 - tick0
  9072.                IF( tick .LT. 0 ) tick = tick + 100
  9073.                tick0 = tick1
  9074.                kount = kount + tick
  9075.             END DO
  9076.             RETURN
  9077.             END
  9078.  
  9079.  This program fills the screen with animated figures.
  9080.  
  9081.  
  9082.  getbkcolor
  9083.  
  9084.  ■  Interface
  9085.  
  9086.       INTERFACE TO FUNCTION getbkcolor()
  9087.       INTEGER*4 getbkcolor[FAR, C, ALIAS:"__getbkcolor"]
  9088.       END
  9089.  
  9090.  ■  Description
  9091.  
  9092.  The getbkcolor function retrieves the pixel value of the current background
  9093.  color. The default is 0.
  9094.  
  9095.  In a color text mode (such as $TEXTC80), setbkcolor accepts (and getbkcolor
  9096.  returns) a color index. For example, setbkcolor(2) sets the background color
  9097.  to pixel value 2. The actual color displayed depends on the palette mapping
  9098.  for color index 2. The default is green in a color text-mode.
  9099.  
  9100.  In a color graphics mode (such as $ERESCOLOR), setbkcolor accepts (and
  9101.  getbkcolor returns) a color value (as used in remappalette). The value for
  9102.  the background color is given by the symbolic constants defined in the
  9103.  FGRAPH.FD include file. For example, setbkcolor($GREEN) sets the background
  9104.  color in a graphics mode to green. These symbolic constants are provided as
  9105.  a convenience in defining and manipulating the most common colors. The
  9106.  actual range of colors is, in general, much greater.
  9107.  
  9108.  The function setcolor accepts an INTEGER*2 value as an argument. It is a
  9109.  color index.
  9110.  
  9111.  Whenever an argument is INTEGER*4, it refers to a color value, and whenever
  9112.  it is INTEGER*2, it refers to a color index. The two exceptions are the
  9113.  functions setbkcolor and getbkcolor, described above. A more complete
  9114.  discussion of colors is given in the reference page for the remappalette
  9115.  function.
  9116.  
  9117.  This function is also available under OS/2.
  9118.  
  9119.  ■  Return value
  9120.  
  9121.  Returns the current background color value.
  9122.  
  9123.  ■  See also
  9124.  
  9125.       remappalette, setbkcolor
  9126.  
  9127.  ■  Example
  9128.  
  9129.  See the example program for gettextcolor.
  9130.  
  9131.  
  9132.  getcolor
  9133.  
  9134.  ■  Interface
  9135.  
  9136.       INTERFACE TO FUNCTION getcolor()
  9137.       INTEGER*2 getcolor[FAR, C, ALIAS:"__getcolor"]
  9138.       END
  9139.  
  9140.  ■  Description
  9141.  
  9142.  The getcolor function returns the current color index. The default is the
  9143.  highest legal value of the current palette.
  9144.  
  9145.  ■  Return value
  9146.  
  9147.  Returns the current color index.
  9148.  
  9149.  ■  See also
  9150.  
  9151.       setcolor
  9152.  
  9153.  ■  Example
  9154.  
  9155.              PROGRAM colors
  9156.  
  9157.              INCLUDE 'FGRAPH.FI'
  9158.              INCLUDE 'FGRAPH.FD'
  9159.  
  9160.              INTEGER*2 loop, loop1, dummy2       REAL rnd1, rnd2
  9161.  
  9162.              dummy2 = setvideomode( $MRES16COLOR )
  9163.              DO loop1 = 1, 20
  9164.                 dummy2 = setcolor
  9165.            +             ( MOD( getcolor()+1, 16 ) ) ! Set next color
  9166.                 DO loop = 1, 3200
  9167.       C
  9168.       C            Set a random pixel, normalized to be on the screen C
  9169.  
  9170.                    CALL RANDOM( rnd1 )
  9171.                    CALL RANDOM( rnd2 )
  9172.                    dummy2 = setpixel( INT2( rnd1*320 ),
  9173.            +                          INT2( rnd2*200 ) )
  9174.                 END DO
  9175.              END DO
  9176.  
  9177.              dummy2 = setvideomode( $DEFAULTMODE )
  9178.              END
  9179.  
  9180.  This program assigns different colors to randomly selected pixels.
  9181.  
  9182.  
  9183.  getcurrentposition, getcurrentposition_w
  9184.  
  9185.  ■  Interface
  9186.  
  9187.       INTERFACE TO SUBROUTINE
  9188.     + getcurrentposition[FAR, C, ALIAS:"__f_getcurrentposition"](s)
  9189.       STRUCTURE/xycoord/
  9190.               INTEGER*2 xcoord                    ! x-coordinate
  9191.               INTEGER*2 ycoord                    ! y-coordinate
  9192.       END STRUCTURE
  9193.       RECORD/xycoord/s [FAR, REFERENCE]           ! Returns with current posit
  9194.       END
  9195.  
  9196.       INTERFACE TO SUBROUTINE
  9197.     + getcurrentposition_w[FAR, C, ALIAS:"__f_getcurpos_w"](s)
  9198.       STRUCTURE/wxycoord/
  9199.               DOUBLE PRECISION wx                 ! x-window coordinate
  9200.               DOUBLE PRECISION wy                 ! y-window coordinate
  9201.       END STRUCTURE
  9202.       RECORD/wxycoord/s [FAR, REFERENCE]          ! Returns with current posit
  9203.       END
  9204.  
  9205.  ■  Description
  9206.  
  9207.  The getcurrentposition functions return the coordinates of the current
  9208.  graphics output position in s. The getcurrentposition function returns the
  9209.  position as an xycoord structure, defined in FGRAPH.FD. The
  9210.  getcurrentposition_w function returns the position as the wxycoord
  9211.  structure, defined in FGRAPH.FD.
  9212.  
  9213.  The current position can be changed by the arc, lineto, and moveto
  9214.  functions.
  9215.  
  9216.  Only graphics output starts at the current position; it does not affect text
  9217.  output, which begins at the current text position, a separate concept (see
  9218.  settextposition).
  9219.  
  9220.  ■  Return value
  9221.  
  9222.  There is no return value.
  9223.  
  9224.  ■  See also
  9225.  
  9226.       moveto
  9227.  
  9228.  ■  Example
  9229.  
  9230.             PROGRAM Movept
  9231.  
  9232.             INCLUDE 'FGRAPH.FI'
  9233.             INCLUDE 'FGRAPH.FD'
  9234.  
  9235.             RECORD/xycoord/ position
  9236.  
  9237.             CHARACTER*255 buffer
  9238.             INTEGER*2 dummy2
  9239.             REAL rnd1, rnd2
  9240.  
  9241.             dummy2 = setvideomode( $MRES16COLOR )
  9242.             CALL RANDOM( rnd1 )
  9243.             CALL RANDOM( rnd2 )
  9244.             CALL moveto( INT2( rnd1*160+80 ),
  9245.            + INT2( rnd2*100+50 ), position )
  9246.             CALL getcurrentposition( position )
  9247.             WRITE( buffer,"( ' x=',I3,', y=',I3,\ )" ) position.xcoord,
  9248.            +                                           position.ycoord
  9249.             CALL settextposition( position.xcoord/8,   position.ycoord/8,
  9250.            +                      position )
  9251.             CALL outtext( buffer( 1:LEN_TRIM(buffer ) ) )
  9252.  
  9253.             READ(*, *)          ! Wait for ENTER to be pressed
  9254.             dummy2 = setvideomode( $DEFAULTMODE )
  9255.             END
  9256.  
  9257.  This program moves the current graphics output position to a random point,
  9258.  calls getcurrentposition to obtain the coordinates, and then writes the
  9259.  coordinates to a buffer. It then sets the current text position to those
  9260.  coordinates and outputs the coordinates to the screen, beginning at the
  9261.  current position.
  9262.  
  9263.  
  9264.  getfillmask
  9265.  
  9266.  
  9267.  ■  Interface
  9268.  
  9269.       INTERFACE TO SUBROUTINE
  9270.     + getfillmask[FAR, C, ALIAS:"__getfillmask"](mask)
  9271.       INTEGER*1 mask [FAR, REFERENCE](8)
  9272.       END
  9273.  
  9274.  ■  Description
  9275.  
  9276.  Some graphics routines (floodfill, pie, ellipse, and rectangle) can fill
  9277.  part or all of the screen with the current color or background color. The
  9278.  filling can be controlled with the current fill mask.
  9279.  
  9280.  The getfillmask subroutine returns the current fill mask. The mask is an
  9281.  8-by-8-bit array, where each bit represents a pixel. A 1 bit sets the
  9282.  corresponding pixel to the current color, while a 0 bit leaves the pixel
  9283.  unchanged. The mask is repeated over the entire fill area. If no fill mask
  9284.  is set, or mask is all zeros, only the current color is used in fill
  9285.  operations. If no mask is present, the subroutine sets mask to all zeros.
  9286.  
  9287.  ■  Return value
  9288.  
  9289.  There is no return value.
  9290.  
  9291.  ■  See also
  9292.  
  9293.       floodfill, ellipse, pie, rectangle, setfillmask
  9294.  
  9295.  ■  Example
  9296.  
  9297.             PROGRAM Fill
  9298.  
  9299.             INCLUDE 'FGRAPH.FI'
  9300.             INCLUDE 'FGRAPH.FD'
  9301.  
  9302.             INTEGER*1 style( 8,6 )/  #78,#30,#30,#78,#30,#30,#78,#30,
  9303.            +                         #78,#32,#30,#78,#30,#38,#78,#32,
  9304.            +                         #78,#39,#38,#78,#63,#36,#78,#33,
  9305.            +                         #78,#65,#36,#78,#33,#38,#78,#62,
  9306.            +                         #78,#66,#63,#78,#65,#65,#78,#37,
  9307.            +                         #78,#66,#65,#78,#66,#65,#78,#66 /
  9308.  
  9309.             INTEGER*1 oldstyle( 8 ) ! Placeholder for old style
  9310.             INTEGER loop
  9311.  
  9312.             dummy2 = setvideomode( $MRES4COLOR )
  9313.             CALL getfillmask( oldstyle )
  9314.       C
  9315.       C     Draw an ellipse under the middle few rectangles in a
  9316.       C     different color.
  9317.       C
  9318.  
  9319.             dummy2 = setcolor( 2 )
  9320.             dummy2 = ellipse( $GFILLINTERIOR, 120, 75, 200, 125 )
  9321.             dummy2 = setcolor( 3 )
  9322.             DO loop = 1,6
  9323.       C
  9324.       C     Make six rectangles.
  9325.       C
  9326.             CALL setfillmask( style( 1,loop ) )
  9327.             dummy2 = rectangle( $GFILLINTERIOR, loop*40+5, 90,
  9328.            +                  ( loop+1 )*40, 110 )
  9329.             END DO
  9330.  
  9331.             CALL setfillmask( oldstyle )   ! Restore old style
  9332.             READ (*,*)                     ! Wait for ENTER to be pressed
  9333.             dummy2 = setvideomode( $DEFAULTMODE )
  9334.             END
  9335.  
  9336.  This program draws an ellipse overlaid with six rectangles, each with a
  9337.  different fill mask.
  9338.  
  9339.  
  9340.  getfontinfo
  9341.  
  9342.  ■  Interface
  9343.  
  9344.       INTERFACE TO FUNCTION getfontinfo(font)
  9345.       INTEGER*2 getfontinfo
  9346.     + [FAR, C, ALIAS:"__f_getfontinfo"]
  9347.       STRUCTURE/fontinfo/
  9348.       INTEGER*2 type             ! Set=vector, clear=bit map
  9349.       INTEGER*2 ascent           ! Pixel distance from top to baseline
  9350.       INTEGER*2 pixwidth         ! Character width in pixels, 0=prop
  9351.       INTEGER*2 pixheight        ! Character height in pixels
  9352.       INTEGER*2 avegwidth        ! Average width in pixels
  9353.       CHARACTER*81 filename      ! File name including path
  9354.       CHARACTER*32 facename      ! Font name
  9355.       END STRUCTURE
  9356.       RECORD/fontinfo/font [FAR, REFERENCE]
  9357.       END
  9358.  
  9359.  ■  Description
  9360.  
  9361.  The getfontinfo function sets the current font characteristics in a fontinfo
  9362.  structure, defined in FGRAPH.FD.
  9363.  
  9364.  The fontinfo structure contains the following elements:
  9365.  
  9366.       Element                     Contents
  9367.  
  9368.       type                        Specifies vector (1) or bit-map
  9369.                                   (0) font
  9370.  
  9371.       ascent                      Specifies pixel distance from top
  9372.                                   to baseline
  9373.  
  9374.       pixwidth                    Specifies the character width in
  9375.                                   pixels; a 0 indicates a
  9376.                                   proportional font
  9377.  
  9378.       pixheight                   Specifies the character height in
  9379.                                   pixels
  9380.  
  9381.       avgwidth                    Specifies the average character
  9382.                                   width in pixels
  9383.  
  9384.       filename                    Specifies the file name including
  9385.                                   the path
  9386.  
  9387.       facename                    Specifies the font name
  9388.  
  9389.  
  9390.  ■  Return value
  9391.  
  9392.  Returns zero if font is returned successfully.
  9393.  
  9394.  ■  See also
  9395.  
  9396.       getgtextextent, outgtext, registerfonts, setfont, unregisterfonts
  9397.  
  9398.  
  9399.  getgtextextent
  9400.  
  9401.  ■  Interface
  9402.  
  9403.       INTERFACE TO FUNCTION getgtextextent(text)
  9404.       INTEGER*2 getgtextextent
  9405.     + [FAR, C, ALIAS:"__f_getgtextextent"]
  9406.       CHARACTER *(*)text [FAR, REFERENCE]        ! Text to be analyzed
  9407.       END
  9408.  
  9409.  ■  Description
  9410.  
  9411.  The getgtextextent function returns the width in pixels that would be
  9412.  required to print the text string, including any trailing blanks, with the
  9413.  current font using outgtext.
  9414.  
  9415.  This function is particularly useful for determining the size of text that
  9416.  uses proportional-spaced fonts.
  9417.  
  9418.  ■  Return value
  9419.  
  9420.  Returns the width of a text string in pixels.
  9421.  
  9422.  ■  See also
  9423.  
  9424.       getfontinfo, outgtext, registerfonts, setfont, unregisterfonts
  9425.  
  9426.  ■  Example
  9427.  
  9428.  See the example program for registerfonts.
  9429.  
  9430.  
  9431.  getimage, getimage_w
  9432.  
  9433.  ■  Interface
  9434.  
  9435.       INTERFACE TO SUBROUTINE
  9436.     + getimage[FAR, C, ALIAS:"__getimage"](x1, y1, x2, y2, image)
  9437.       INTEGER*2 x1, y1              ! Upper left corner of bounding rectangle
  9438.       INTEGER*2 x2, y2              ! Lower right corner of bounding rectangle
  9439.       INTEGER*1 image [FAR, REFERENCE](*)
  9440.       END
  9441.  
  9442.       INTERFACE TO SUBROUTINE
  9443.     + getimage_w[FAR, C, ALIAS:"__f_getimage_w"](wx1, wy1, wx2, wy2, image)
  9444.       DOUBLE PRECISION wx1, wy1     ! Upper left corner of bounding rectangle
  9445.       DOUBLE PRECISION wx2, wy2     ! Lower right corner of bounding rectangle
  9446.       INTEGER*1 image [FAR, REFERENCE](*)
  9447.       END
  9448.  
  9449.  ■  Description
  9450.  
  9451.  The getimage subroutines store the screen image defined by a specified
  9452.  bounding rectangle into the buffer that image points to.
  9453.  
  9454.  The getimage subroutine defines the bounding rectangle with the
  9455.  viewport-coordinate points (x1, y1) and (x2, y2).
  9456.  
  9457.  The getimage_w subroutine defines the bounding rectangle with the
  9458.  window-coordinate points (wx1, wy1) and (wx2, wy2).
  9459.  
  9460.  The buffer must be large enough to hold the image. Determine the size by
  9461.  calling the appropriate imagesize function at run time, or by using the
  9462.  formula described on the imagesize reference page.
  9463.  
  9464.  ■  Return value
  9465.  
  9466.  There is no return value.
  9467.  
  9468.  ■  See also
  9469.  
  9470.       imagesize, putimage
  9471.  
  9472.  ■  Example
  9473.  
  9474.  See the example program for imagesize.
  9475.  
  9476.  
  9477.  getlinestyle
  9478.  
  9479.  ■  Interface
  9480.  
  9481.       INTERFACE TO FUNCTION getlinestyle()
  9482.       INTEGER*2 getlinestyle[FAR, C, ALIAS:"__getlinestyle"]
  9483.       END
  9484.  
  9485.  ■  Description
  9486.  
  9487.  Some graphics routines (lineto, pie, and rectangle) output straight lines to
  9488.  the screen. The type of line can be controlled with the current line-style
  9489.  mask.
  9490.  
  9491.  The getlinestyle function returns the current line-style-mask number. The
  9492.  mask is a 16-bit array, where each bit represents a pixel in the line being
  9493.  drawn. If the bit is 1, then the corresponding pixel is set to the color of
  9494.  the line (the current color). If the bit is 0, the corresponding pixel is
  9495.  left unchanged. The mask is repeated over the length of the line. The
  9496.  default mask is #FFFF (a solid line).
  9497.  
  9498.  ■  Return value
  9499.  
  9500.  If a mask has been set, returns the current line-style mask number. If no
  9501.  mask has been set, getlinestyle returns the default mask.
  9502.  
  9503.  ■  See also
  9504.  
  9505.       lineto, pie, rectangle, setlinestyle
  9506.  
  9507.  ■  Example
  9508.  
  9509.  See the example program for setlinestyle.
  9510.  
  9511.  
  9512.  getphyscoord
  9513.  
  9514.  ■  Interface
  9515.  
  9516.       INTERFACE TO SUBROUTINE
  9517.     + getphyscoord[FAR, C, ALIAS:"__f_getphyscoord"](x, y, s)
  9518.       INTEGER*2 x, y
  9519.       STRUCTURE/xycoord/
  9520.          INTEGER*2 xcoord                         ! x-coordinate
  9521.          INTEGER*2 ycoord                         ! y-coordinate
  9522.       END STRUCTURE
  9523.       RECORD/xycoord/s [FAR, REFERENCE]           ! Returns the physical coord
  9524.       END
  9525.  
  9526.  ■  Description
  9527.  
  9528.  The getphyscoord subroutine translates the viewport-coordinate point (x, y)
  9529.  to physical coordinates, returning them in the xycoord structure s, defined
  9530.  in FGRAPH.FD.
  9531.  
  9532.  ■  Return value
  9533.  
  9534.  There is no return value.
  9535.  
  9536.  ■  See also
  9537.  
  9538.       getviewcoord
  9539.  
  9540.  ■  Example
  9541.  
  9542.  See the example program for setviewport.
  9543.  
  9544.  
  9545.  getpixel, getpixel_w
  9546.  
  9547.  ■  Interface
  9548.  
  9549.       INTERFACE TO FUNCTION getpixel(x, y)
  9550.       INTEGER*2 getpixel[FAR, C, ALIAS:"__getpixel"]
  9551.       INTEGER*2 x, y            ! Pixel position
  9552.       END
  9553.  
  9554.       INTERFACE TO FUNCTION getpixel_w(wx, wy)
  9555.       INTEGER*2 getpixel_w[FAR, C, ALIAS:"__f_getpixel_w"]
  9556.       DOUBLE PRECISION wx, wy   ! Pixel position in window coordinates
  9557.       END
  9558.  
  9559.  ■  Description
  9560.  
  9561.  The getpixel functions retrieve the pixel value at a specified location. The
  9562.  getpixel function uses the viewport coordinate (x, y). The getpixel_w
  9563.  function uses the window coordinate (wx, wy). The range of possible pixel
  9564.  values and their color translation is determined by the current video mode
  9565.  and palette, respectively.
  9566.  
  9567.  ■  Return value
  9568.  
  9569.  If successful, the getpixel and getpixel_w functions return the pixel value.
  9570.  If the function fails (for example, the point lies outside the clipping
  9571.  region, or the program is in a text mode), it returns -1.
  9572.  
  9573.  ■  See also
  9574.  
  9575.       remapallpalette, remappalette, selectpalette, setpixel, setvideomode
  9576.  
  9577.  ■  Example
  9578.  
  9579.             PROGRAM colors
  9580.  
  9581.             INCLUDE 'FGRAPH.FI'
  9582.             INCLUDE 'FGRAPH.FD'
  9583.  
  9584.             INTEGER*2 loop, dummy2
  9585.             REAL rnd1, rnd2
  9586.  
  9587.             dummy2 = setvideomode( $MRES16COLOR )
  9588.             dummy2 = rectangle( $GFILLINTERIOR, 80, 50, 240, 150 )
  9589.             DO loop = 1, 8000
  9590.                dummy2 = setcolor( MOD( getcolor()+1, 16 ) )  ! Set next
  9591.            +   color
  9592.       C
  9593.       C        Set a random pixel, but only if it is already on.
  9594.       C
  9595.                CALL RANDOM( rnd1 )
  9596.                CALL RANDOM( rnd2 )
  9597.                IF ( getpixel( INT2( rnd1*320 ), INT2( rnd2*200 ) )
  9598.            +   .NE. 0 ) THEN
  9599.                   dummy2 = setcolor( MOD( loop, 16 ) )
  9600.                   dummy2 = setpixel( INT2( rnd1*320 ), INT2( rnd2*200 ) )
  9601.                END IF
  9602.             END DO
  9603.  
  9604.             dummy2 = setvideomode( $DEFAULTMODE )
  9605.             END
  9606.  
  9607.  This program assigns different colors to randomly selected pixels.
  9608.  
  9609.  
  9610.  gettextcolor
  9611.  
  9612.  ■  Interface
  9613.  
  9614.       INTERFACE TO FUNCTION gettextcolor()
  9615.       INTEGER*2 gettextcolor[FAR, C, ALIAS:"__gettextcolor"]
  9616.       END
  9617.  
  9618.  ■  Description
  9619.  
  9620.  The gettextcolor function returns the color index of the current text color.
  9621.  The text color is set only by the settextcolor function and affects text
  9622.  output with the outtext function only. The setcolor function sets the color
  9623.  for text output using the outgtext function.
  9624.  
  9625.  The default is the highest legal color index of the current palette.
  9626.  
  9627.  This function is also available under OS/2.
  9628.  
  9629.  ■  Return value
  9630.  
  9631.  Returns the color index of the current text color.
  9632.  
  9633.  ■  See also
  9634.  
  9635.       selectpalette, setcolor, settextcolor
  9636.  
  9637.  ■  Example
  9638.  
  9639.       CC  TEXT.FOR - Illustrates text output functions including:
  9640.       CC             clearscreen      getbkcolor        gettextcolor
  9641.       CC             gettextposition  outtext           setbkcolor
  9642.       CC             settextcolor     settextposition
  9643.       CC
  9644.  
  9645.             INCLUDE  'FGRAPH.FI'
  9646.             INCLUDE  'FGRAPH.FD'
  9647.  
  9648.             INTEGER*2          dummy2, blink, fgd, oldfgd
  9649.             INTEGER*4          dummy4, bgd, oldbgd
  9650.             CHARACTER*4        str
  9651.             RECORD / rccoord / curpos
  9652.  
  9653.       C
  9654.       C     Save original foreground, background, and text position.
  9655.       C
  9656.             oldfgd = gettextcolor()
  9657.             oldbgd = getbkcolor()
  9658.             CALL clearscreen( $GCLEARSCREEN )
  9659.       C
  9660.       C     First time no blink, second time blinking.
  9661.       C
  9662.             DO blink = 0, 16, 16
  9663.       C
  9664.       C        Loop through 8 background colors.
  9665.       C
  9666.                DO bgd = 0, 7
  9667.                   dummy4 = setbkcolor( bgd )
  9668.                   CALL settextposition( INT2( bgd )
  9669.            +          ( ( blink / 16 ) * 9 )+ 3, 1, curpos )
  9670.                   dummy2 = settextcolor( 15 )
  9671.                   WRITE ( str, '( I4  )' ) bgd
  9672.                   CALL outtext( 'Back:' // str(3:4) // '  Fore:', 14 )
  9673.       C
  9674.       C           Loop through 16 foreground colors.
  9675.       C
  9676.                   DO fgd = 0, 15
  9677.                      dummy2 = settextcolor( fgd + blink )
  9678.                      WRITE ( str, '( I4 )' ) fgd + blink
  9679.                      CALL outtext( str )
  9680.                   END DO
  9681.                END DO
  9682.             END DO
  9683.  
  9684.             WRITE (*, '(///// A \)') ' Press ENTER to exit . . . '
  9685.             READ (*,*)
  9686.  
  9687.       C
  9688.       C     Restore original foreground and background.
  9689.       C
  9690.             dummy2 = settextcolor( oldfgd )
  9691.             dummy4 = setbkcolor( oldbgd )
  9692.             CALL clearscreen( $GCLEARSCREEN )
  9693.             END
  9694.  
  9695.  This program prints different text colors on a variety of colored
  9696.  backgrounds.
  9697.  
  9698.  
  9699.  gettextcursor
  9700.  
  9701.  ■  Interface
  9702.  
  9703.       INTERFACE TO FUNCTION gettextcursor()
  9704.       INTEGER*2 gettextcursor[FAR, C, ALIAS:"__gettextcursor"]
  9705.       END
  9706.  
  9707.  ■  Description
  9708.  
  9709.  The gettextcursor function returns the current cursor attribute (the shape).
  9710.  Note that this function works in text video modes only.
  9711.  
  9712.  This function is also available under OS/2.
  9713.  
  9714.  ■  Return value
  9715.  
  9716.  Returns the current cursor attribute or -1 if an error occurs (such as
  9717.  calling the function in a non-text video mode).
  9718.  
  9719.  ■  See also
  9720.  
  9721.       displaycursor, settextcursor
  9722.  
  9723.  ■  Example
  9724.  
  9725.  See the example program for settextcursor.
  9726.  
  9727.  
  9728.  gettextposition
  9729.  
  9730.  ■  Interface
  9731.  
  9732.       INTERFACE TO SUBROUTINE
  9733.     + gettextposition[FAR, C, ALIAS:"__f_gettextposition"](s)
  9734.       STRUCTURE/rccoord/
  9735.          INTEGER*2 row                          ! Row coordinate
  9736.          INTEGER*2 col                          ! Column coordinate
  9737.       END STRUCTURE
  9738.       RECORD/rccoord/s [FAR, REFERENCE]         ! Returns the current text pos
  9739.       END
  9740.  
  9741.  ■  Description
  9742.  
  9743.  The gettextposition function returns the current text position in s, an
  9744.  rccoord structure defined in FGRAPH.FD.
  9745.  
  9746.  The text position given by the coordinates (1, 1) is defined as the upper
  9747.  left corner of the text window.
  9748.  
  9749.  Text output from the outtext function begins at the current text position.
  9750.  Font text is not affected by the current text position. Graphics output
  9751.  begins at the current graphics output position, which is a separate
  9752.  position.
  9753.  
  9754.  This function is also available under OS/2.
  9755.  
  9756.  ■  Return value
  9757.  
  9758.  There is no return value.
  9759.  
  9760.  ■  See also
  9761.  
  9762.       settextposition
  9763.  
  9764.  ■  Example
  9765.  
  9766.  See the example program for gettextcolor.
  9767.  
  9768.  
  9769.  getviewcoord, getviewcoord_w
  9770.  
  9771.  ■  Interface
  9772.  
  9773.       INTERFACE TO SUBROUTINE
  9774.     + getviewcoord[FAR, C, ALIAS:"__f_getviewcoord"](x, y, s)
  9775.       INTEGER*2 x, y
  9776.       STRUCTURE/xycoord/
  9777.          INTEGER*2 xcoord                                ! x-coordinate
  9778.          INTEGER*2 ycoord                                ! y-coordinate
  9779.       END STRUCTURE
  9780.       RECORD/xycoord/s [FAR, REFERENCE]                  ! Returns the viewpor
  9781.       END
  9782.  
  9783.       INTERFACE TO SUBROUTINE
  9784.     + getviewcoord_w[FAR, C, ALIAS:"__f_getviewcoord_w"](wx, wy, s)
  9785.       DOUBLE PRECISION wx, wy
  9786.       STRUCTURE/xycoord/
  9787.          INTEGER*2 xcoord                                ! x-coordinate
  9788.          INTEGER*2 ycoord                                ! y-coordinate
  9789.       END STRUCTURE
  9790.       RECORD/xycoord/s [FAR, REFERENCE]                  ! Returns the viewpor
  9791.       END
  9792.  
  9793.  ■  Description
  9794.  
  9795.  The getviewcoord subroutines translate the specified coordinates (x, y) from
  9796.  one coordinate system to viewport coordinates and returns them in the
  9797.  xycoord structure s, defined in FGRAPH.FD.
  9798.  
  9799.  The getviewcoord subroutines translate in the following manner:
  9800.  
  9801.       Routine                     Translation
  9802.  
  9803.       getviewcoord                Physical coordinates (x, y) to
  9804.                                   viewport coordinates
  9805.  
  9806.       getviewcoord_w              Window coordinates (wx, wy) to
  9807.                                   viewport coordinates
  9808.  
  9809.  ■  Return value
  9810.  
  9811.  There is no return value.
  9812.  
  9813.  ■  See also
  9814.  
  9815.       getphyscoord, getwindowcoord
  9816.  
  9817.  ■  Example
  9818.  
  9819.  See the example program for setviewport.
  9820.  
  9821.  
  9822.  getvideoconfig
  9823.  
  9824.  ■  Interface
  9825.  
  9826.       INTERFACE TO SUBROUTINE
  9827.     + getvideoconfig[FAR, C, ALIAS:"__getvideoconfig"](s)
  9828.       STRUCTURE/videoconfig/
  9829.          INTEGER*2 numxpixels    ! Number of pixels on x-axis
  9830.          INTEGER*2 numypixels    ! Number of pixels on y-axis
  9831.          INTEGER*2 numtextcols   ! Number of text columns available
  9832.          INTEGER*2 numtextrows   ! Number of text rows available
  9833.          INTEGER*2 numcolors     ! Number of actual colors
  9834.          INTEGER*2 bitsperpixel  ! Number of bits per pixel
  9835.          INTEGER*2 numvideopages ! Number of available video pages
  9836.          INTEGER*2 mode          ! Current video mode
  9837.          INTEGER*2 adapter       ! Active display adapter
  9838.          INTEGER*2 monitor       ! Active display monitor
  9839.          INTEGER*2 memory        ! Video adapter memory in K bytes
  9840.       END STRUCTURE
  9841.       RECORD/videoconfig/s [FAR, REFERENCE]
  9842.       END
  9843.  
  9844.  ■  Description
  9845.  
  9846.  The getvideoconfig function returns the current graphics environment
  9847.  configuration in s, a videoconfig structure defined above and in FGRAPH.FD.
  9848.  
  9849.  The values returned reflect the currently active monitor as well as the
  9850.  currently specified video mode.
  9851.  
  9852.  The videoconfig structure contains the following elements:
  9853.  
  9854.       Element                          Contents
  9855.  
  9856.       numxpixels                       Number of pixels on the x-axis
  9857.  
  9858.       numypixels                       Number of pixels on the y-axis
  9859.  
  9860.       numtextcols                      Number of text columns available
  9861.  
  9862.       numtextrows                      Number of text rows available
  9863.  
  9864.       numcolors                        Number of actual colors available
  9865.  
  9866.       bitsperpixel                     Number of bits per pixel
  9867.  
  9868.       numvideopages                    Number of available video pages
  9869.  
  9870.       mode                             Current video mode
  9871.  
  9872.       adapter                          Active display adapter
  9873.  
  9874.       monitor                          Active display monitor
  9875.  
  9876.       memory                           Video adapter memory (in
  9877.                                        kilobytes)
  9878.  
  9879.  The values for the adapter element of the videoconfig structure are given by
  9880.  the symbolic constants shown in the list below. For any applicable adapter
  9881.  ($CGA, $EGA, or $VGA), the corresponding Olivetti adapter ($OCGA, $OEGA, or
  9882.  $OVGA) represents a superset of graphics capabilities.
  9883.  
  9884.       Adapter Constant                 Meaning
  9885.  
  9886.       $MDPA                            Monochrome Display Adapter
  9887.  
  9888.       $CGA                             Color Graphics Adapter
  9889.  
  9890.       $OCGA                            Olivetti(R) (AT&T) Color Graphics
  9891.                                        Adapter
  9892.  
  9893.       $EGA                             Enhanced Graphics Adapter
  9894.  
  9895.       $OEGA                            Olivetti (AT&T) Enhanced Graphics
  9896.                                        Adapter
  9897.  
  9898.       $VGA                             Video Graphics Array
  9899.  
  9900.       $OVGA                            Olivetti (AT&T) Video Graphics
  9901.                                        Array
  9902.  
  9903.       $MCGA                            Multicolor Graphics Array
  9904.  
  9905.       $HGC                             Hercules Graphics Card
  9906.  
  9907.  The values for the monitor element of the videoconfig structure are given by
  9908.  the symbolic constants listed below:
  9909.  
  9910.       Monitor Constant            Meaning
  9911.  
  9912.       $MONO                       Monochrome monitor
  9913.  
  9914.       $COLOR                      Color (or
  9915.                                   enhanced-monitor-emulating color)
  9916.  
  9917.       $ENHCOLOR                   Enhanced color
  9918.  
  9919.       $ANALOG                     Analog
  9920.  
  9921.  In every text mode, including monochrome, getvideoconfig returns the value
  9922.  32 for the number of available colors. The value 32 indicates the range of
  9923.  values (0-31) accepted by the settextcolor function. This includes 16 normal
  9924.  colors (0-15) and 16 blinking colors (16-31). Blinking is selected by adding
  9925.  16 to the normal color value. Monochrome text mode has fewer unique display
  9926.  attributes, so some color values are redundant. However, because blinking is
  9927.  selected in the same manner, monochrome text mode has the same range (0-31)
  9928.  as other text modes.
  9929.  
  9930.  This subroutine is also available under OS/2.
  9931.  
  9932.  ■  Return value
  9933.  
  9934.  Returns the current graphics environment configuration.
  9935.  
  9936.  ■  Example
  9937.  
  9938.  See the example program for setvideomoderows.
  9939.  
  9940.  
  9941.  getvisualpage
  9942.  
  9943.  ■  Interface
  9944.  
  9945.       INTERFACE TO FUNCTION getvisualpage()
  9946.       INTEGER*2 getvisualpage[FAR, C, ALIAS:"__getvisualpage"]
  9947.       END
  9948.  
  9949.  ■  Description
  9950.  
  9951.  The getvisualpage function returns the current visual page number.
  9952.  
  9953.  ■  Return value
  9954.  
  9955.  Returns the page number of the current visual page. All hardware
  9956.  combinations support at least one page (page number 0).
  9957.  
  9958.  This function is also available under OS/2.
  9959.  
  9960.  ■  See also
  9961.  
  9962.       getactivepage, gettextcolor, gettextposition, outtext, settextcolor,
  9963.       settextposition, settextwindow, setvideomode, setvisualpage, wrapon
  9964.  
  9965.  ■  Example
  9966.  
  9967.  See the example program for getactivepage
  9968.  
  9969.  
  9970.  getwindowcoord
  9971.  
  9972.  ■  Interface
  9973.  
  9974.       INTERFACE TO SUBROUTINE
  9975.     + getwindowcoord[FAR, C, ALIAS:"__getwindowcoord"](x, y, s)
  9976.       INTEGER*2 x, y                             ! Physical point to translate
  9977.       STRUCTURE/wxycoord/
  9978.          DOUBLE PRECISION wx                     ! x-coordinate
  9979.          DOUBLE PRECISION wy                     ! y-coordinate
  9980.       END STRUCTURE
  9981.       RECORD/wxycoord/s [FAR, REFERENCE]         ! Returns the window coordina
  9982.       END
  9983.  
  9984.  ■  Description
  9985.  
  9986.  The getwindowcoord subroutine translates the viewport coordinates (x, y) to
  9987.  window coordinates and returns them in the wxycoord structure variable s,
  9988.  defined in FGRAPH.FD.
  9989.  
  9990.  ■  Return value
  9991.  
  9992.  There is no return value.
  9993.  
  9994.  ■  See also
  9995.  
  9996.       getphyscoord, getviewcoord, getviewcoordw, getviewcoordwxy, moveto
  9997.  
  9998.  ■  Example
  9999.  
  10000.  See the example program for setviewport.
  10001.  
  10002.  
  10003.  imagesize, imagesize_w
  10004.  
  10005.  ■  Interface
  10006.  
  10007.       INTERFACE TO FUNCTION imagesize(x1, y1, x2, y2)
  10008.       INTEGER*4 imagesize[FAR, C, ALIAS:"__imagesize"]
  10009.       INTEGER*2 x1, y1            ! Upper left corner of image
  10010.       INTEGER*2 x2, y2            ! Lower right corner of image
  10011.       END
  10012.  
  10013.       INTERFACE TO FUNCTION imagesize_w(wx1, wy1, wx2, wy2)
  10014.       INTEGER*4 imagesize[FAR, C, ALIAS:"__f_imagesize_w"]
  10015.       DOUBLE PRECISION wx1, wy1   ! Upper left corner of image
  10016.       DOUBLE PRECISION wx2, wy2   ! Lower right corner of image
  10017.       END
  10018.  
  10019.  
  10020.  ■  Description
  10021.  
  10022.  The imagesize functions return the number of bytes needed to store the image
  10023.  defined by the bounding rectangle, which is specified by the coordinates
  10024.  given in the function call. The imagesize function defines the bounding
  10025.  rectangle in terms of viewport-coordinate points (x1, y1) and (x2, y2). This
  10026.  size is determined by the following formula:
  10027.  
  10028.       xwid = abs( x1-x2 )+1
  10029.       ywid = abs( y1-y2 )+1
  10030.       size = 4 + INT( ( xwid*bits_per_pixel+7 )/8 )*INT( ywid ) )
  10031.  
  10032.  The bits_per_pixel value returns from a call to getvideoconfig as
  10033.  bitsperpixel.
  10034.  
  10035.  The imagesize_w function defines the bounding rectangle in terms of
  10036.  window-coordinate points (x1, y1) and (x2, y2).
  10037.  
  10038.  
  10039.  ■  Return value
  10040.  
  10041.  The imagesize and imagesize_w functions return the storage size of an image
  10042.  in bytes.
  10043.  
  10044.  
  10045.  ■  See also
  10046.  
  10047.       getvideoconfig
  10048.  
  10049.  
  10050.  ■  Example
  10051.  
  10052.       CC  ANIMATE.FOR - Illustrates animation functions including:
  10053.       CC                imagesize     getimage     putimage
  10054.  
  10055.             INCLUDE  'FGRAPH.FI'
  10056.             INCLUDE  'FGRAPH.FD'
  10057.  
  10058.             INTEGER*1        buffer[ALLOCATABLE] (:)
  10059.             INTEGER*2        dummy, x, y, error, action(5)
  10060.             INTEGER*4        imsize
  10061.             CHARACTER*6      descrip(5)
  10062.             RECORD /rccoord/ curpos
  10063.  
  10064.             DATA action  / $GPSET, $GPRESET, $GXOR, $GOR, $GAND  /
  10065.             DATA descrip / 'PSET  ', 'PRESET', 'XOR  ', 'OR  ', 'AND  ' /
  10066.  
  10067.       C
  10068.       C     Find graphics mode.
  10069.       C
  10070.             IF( setvideomode( $MAXRESMODE ) .EQ. 0 )
  10071.            +    STOP 'Error:  cannot set graphics mode'
  10072.  
  10073.             dummy = setcolor( 3 )
  10074.             y     = 30
  10075.             DO i = 1, 5
  10076.                x = 50
  10077.                y = y + 40
  10078.       C
  10079.       C        Display action type.
  10080.       C
  10081.                CALL settextposition( 1, 1, curpos )
  10082.                CALL outtext( descrip(i) )
  10083.       C
  10084.       C        Draw and measure ellipse, allocate memory for image.
  10085.       C
  10086.                dummy  = ellipse( $GFILLINTERIOR, x - 15, y - 15, x + 15,
  10087.            +                     y + 15 )
  10088.                imsize = imagesize( x - 16, y - 16, x + 16, y + 16 )
  10089.                ALLOCATE( buffer( imsize ), STAT = error )
  10090.                IF( error .NE. 0 ) THEN
  10091.                   dummy = setvideomode( $DEFAULTMODE )
  10092.                   STOP 'Error:  insufficient memory'
  10093.                END IF
  10094.       C
  10095.       C        Get master copy of ellipse.
  10096.       C
  10097.                CALL getimage( x - 16, y - 16, x + 16, y + 16, buffer )
  10098.       C
  10099.       C        Copy row of ellipses with specified action.
  10100.       C
  10101.                DO x = 55, 255, 5
  10102.                   CALL putimage( x - 16, y - 16, buffer, action(i) )
  10103.                END DO
  10104.  
  10105.       C
  10106.       C        Free memory, wait for ENTER key to continue.
  10107.       C
  10108.                DEALLOCATE( buffer )
  10109.                READ (*,*)
  10110.             END DO
  10111.  
  10112.             dummy = setvideomode( $DEFAULTMODE )
  10113.             END
  10114.  
  10115.  This program shows different methods of animating an image on the screen.
  10116.  
  10117.  
  10118.  lineto, lineto_w
  10119.  
  10120.  ■  Interface
  10121.  
  10122.       INTERFACE TO FUNCTION lineto(x, y)
  10123.       INTEGER*2 lineto[FAR, C, ALIAS:"__lineto"]
  10124.       INTEGER*2 x, y             ! End point
  10125.       END
  10126.  
  10127.       INTERFACE TO FUNCTION lineto_w(wx, wy)
  10128.       INTEGER*2 lineto[FAR, C, ALIAS:"__f_lineto_w"]
  10129.       DOUBLE PRECISION wx, wy    ! End point
  10130.       END
  10131.  
  10132.  ■  Description
  10133.  
  10134.  The lineto functions draw a line from the current position up to and
  10135.  including the destination point. The destination point for lineto is given
  10136.  by the viewport-coordinate point (x, y). The destination point for the
  10137.  lineto_w function is given by the window-coordinate point (wx, wy).
  10138.  
  10139.  The line is drawn using the current color and line style. If no error
  10140.  occurs, lineto sets the current position to the view point (x, y) and
  10141.  lineto_w sets the current position to the window point (wx, wy).
  10142.  
  10143.  ───────────────────────────────────────────────────────────────────────────
  10144.  NOTE
  10145.     If you use floodfill to fill in a closed figure drawn with lineto calls,
  10146.     the figure must be drawn with a solid line-style pattern.
  10147.  ───────────────────────────────────────────────────────────────────────────
  10148.  
  10149.  ■  Return value
  10150.  
  10151.  The lineto and lineto_w routines return a nonzero value if the line is drawn
  10152.  successfully; otherwise, they return 0.
  10153.  
  10154.  ■  See also
  10155.  
  10156.       getcurrentposition, setlinestyle
  10157.  
  10158.  ■  Example
  10159.  
  10160.             INCLUDE          'FGRAPH.FI'
  10161.             INCLUDE          'FGRAPH.FD'
  10162.             INTEGER*2        dummy
  10163.             RECORD /xycoord/ xy
  10164.  
  10165.             dummy = setvideomode( $MRES16COLOR )
  10166.             CALL    moveto(  80,  50, xy  )
  10167.             dummy = lineto( 240, 150 )
  10168.             dummy = lineto( 240,  50 )
  10169.             READ (*,*)          ! Press ENTER to exit
  10170.             dummy = setvideomode( $DEFAULTMODE )
  10171.             END
  10172.  
  10173.  This program draws the figure shown in Figure R.3.
  10174.  
  10175.  See also the example program for setpixel and setviewport.
  10176.  
  10177.  
  10178.  moveto, moveto_w
  10179.  
  10180.  ■  Interface
  10181.  
  10182.       INTERFACE TO SUBROUTINE moveto[FAR, C, ALIAS:"__f_moveto"](x, y, s)
  10183.       INTEGER*2 x, y
  10184.       STRUCTURE/xycoord/
  10185.          INTEGER*2 xcoord                  ! x-coordinate
  10186.          INTEGER*2 ycoord                  ! y-coordinate
  10187.       END STRUCTURE
  10188.       RECORD/xycoord/s [FAR, REFERENCE]    ! Returns the previous position
  10189.       END
  10190.  
  10191.       INTERFACE TO SUBROUTINE
  10192.      + moveto_w[FAR, C, ALIAS:"__f_moveto_w"](wx, wy, s)
  10193.       INTEGER*2 wx, wy
  10194.       STRUCTURE/wxycoord/
  10195.          DOUBLE PRECISION wx                ! x-window coordinate
  10196.          DOUBLE PRECISION wy                ! y-window coordinate
  10197.       END STRUCTURE
  10198.       RECORD/wxycoord/s [FAR, REFERENCE]    ! Returns the previous position
  10199.       END
  10200.  
  10201.  ■  Description
  10202.  
  10203.  The moveto functions move the current position to the specified point. The
  10204.  moveto function uses the view-coordinate point (x, y) as the current
  10205.  position. The moveto_w function use the window-coordinate point (wx, wy) as
  10206.  the current position. No drawing takes place.
  10207.  
  10208.  The function assigns the coordinates of the previous position to s. The
  10209.  moveto function assigns the coordinates in s, an xycoord structure defined
  10210.  in FGRAPH.FD. The function moveto_w assigns the coordinates in s, a wxycoord
  10211.  structure defined in FGRAPH.FD.
  10212.  
  10213.  ■  Return value
  10214.  
  10215.  There is no return value.
  10216.  
  10217.  ■  See also
  10218.  
  10219.  lineto
  10220.  
  10221.  ■  Example
  10222.  
  10223.  See the example program for setpixel and setviewport.
  10224.  
  10225.  
  10226.  outgtext
  10227.  
  10228.  ■  Interface
  10229.  
  10230.       INTERFACE TO SUBROUTINE
  10231.     + outgtext[FAR, C, ALIAS:"__f_outgtext"](text)
  10232.       CHARACTER*(*) text [FAR, REFERENCE]
  10233.       END
  10234.  
  10235.  ■  Description
  10236.  
  10237.  The outgtext function sends the string text to the screen, including any
  10238.  trailing blanks. The text is output using the current font at the current
  10239.  graphics position and in the current color.
  10240.  
  10241.  No formatting is provided.
  10242.  
  10243.  After it outputs the text, outgtext updates the current graphics position.
  10244.  
  10245.  ───────────────────────────────────────────────────────────────────────────
  10246.  NOTE
  10247.     This function operates only in graphics video modes (such as
  10248.     $MRES4COLOR). Because it is a graphics function, the color of text is set
  10249.     by the setcolor function, not by settextcolor.
  10250.  ───────────────────────────────────────────────────────────────────────────
  10251.  
  10252.  ■  Return value
  10253.  
  10254.  There is no return value.
  10255.  
  10256.  ■  See also
  10257.  
  10258.       moveto, setcolor, setfont
  10259.  
  10260.  ■  Example
  10261.  
  10262.  See the example program for registerfonts.
  10263.  
  10264.  
  10265.  outtext
  10266.  
  10267.  ■  Interface
  10268.  
  10269.       INTERFACE TO SUBROUTINE outtext[FAR, C, ALIAS:"__f_outtext"](text)
  10270.       CHARACTER*(*) text [FAR, REFERENCE]
  10271.       END
  10272.  
  10273.  ■  Description
  10274.  
  10275.  The outtext function sends the string text to the screen, including any
  10276.  trailing blanks. No formatting is provided. This function will work in any
  10277.  screen mode. Text output begins at the current text position.
  10278.  
  10279.  ───────────────────────────────────────────────────────────────────────────
  10280.  NOTE
  10281.     To output text using special fonts, you must use the outgtext function.
  10282.  ───────────────────────────────────────────────────────────────────────────
  10283.  
  10284.  This function is also available under OS/2.
  10285.  
  10286.  ■  Return value
  10287.  
  10288.  There is no return value.
  10289.  
  10290.  ■  See also
  10291.  
  10292.       setactivepage, settextposition
  10293.  
  10294.  ■  Example
  10295.  
  10296.  See the example program for gettextcolor and setvideomoderows.
  10297.  
  10298.  
  10299.  pie, pie_w
  10300.  
  10301.  ■  Interface
  10302.  
  10303.       INTERFACE TO FUNCTION pie(i, x1, y1, x2, y2, x3, y3, x4, y4)
  10304.       INTEGER*2 pie[FAR, C, ALIAS:"__f_pie"]
  10305.       INTEGER*2 i                   ! Fill flag
  10306.       INTEGER*2 x1, y1              ! Upper left corner of bounding rectangle
  10307.       INTEGER*2 x2, y2              ! Lower right corner of bounding rectangle
  10308.       INTEGER*2 x3, y3              ! Start vector
  10309.       INTEGER*2 x4, y4              ! End vector
  10310.       END
  10311.  
  10312.       INTERFACE TO FUNCTION pie_w(i, wx1, wy1, wx2, wy2, wx3, wy3, wx4, wy4)
  10313.       INTEGER*2 pie[FAR, C, ALIAS:"__f_pie_w"]
  10314.       INTEGER*2 i                   ! Fill flag
  10315.       DOUBLE PRECISION wx1, wy1     ! Upper left corner of bounding rectangle
  10316.       DOUBLE PRECISION wx2, wy2     ! Lower right corner of bounding rectangle
  10317.       DOUBLE PRECISION wx3, wy3     ! Start vector
  10318.       DOUBLE PRECISION wx4, wy4     ! End vector
  10319.       END
  10320.  
  10321.  ■  Description
  10322.  
  10323.  The pie functions draw a pie-shaped wedge by drawing an elliptical arc whose
  10324.  center and two endpoints are joined by lines.
  10325.  
  10326.  The pie function uses the viewport-coordinate system. The center of the arc
  10327.  is the center of the bounding rectangle, which is specified by the
  10328.  viewport-coordinate points (x1, y1) and (x2, y2). The arc starts where it
  10329.  intersects the vector defined by (x3, y3) and ends where it intersects the
  10330.  vector (x4, y4).
  10331.  
  10332.  The pie_w function uses the window-coordinate system. The center of the arc
  10333.  is the center of the bounding rectangle specified by the window-coordinate
  10334.  pairs (wx1, wy1) and (wx2, wy2). The arc starts where it intersects the
  10335.  vector defined by (wx3, wy3) and ends where it intersects the vector defined
  10336.  by (wx4, wy4).
  10337.  
  10338.  The wedge is drawn using the current color moving in a counterclockwise
  10339.  direction. The control parameter can be one of the following symbolic
  10340.  constants:
  10341.  
  10342.       Constant                         Action
  10343.  
  10344.       $GFILLINTERIOR                   Fills the figure using the
  10345.                                        current color and fill mask
  10346.  
  10347.       $GBORDER                         Does not fill the figure
  10348.  
  10349.  The control option given by $GFILLINTERIOR is equivalent to a subsequent
  10350.  call to the floodfill function using the center of the ellipse as the
  10351.  starting point and the current color (set by setcolor) as the boundary
  10352.  color.
  10353.  
  10354.  ■  Return value
  10355.  
  10356.  The pie and pie_w functions return a nonzero value if the pie is drawn
  10357.  successfully; otherwise, they return 0.
  10358.  
  10359.  ■  See also
  10360.  
  10361.       arc, ellipse, floodfill, getcolor, lineto, rectangle, setcolor,
  10362.       setfillmask
  10363.  
  10364.  ■  Example
  10365.  
  10366.             INCLUDE   'FGRAPH.FI'
  10367.             INCLUDE   'FGRAPH.FD'
  10368.             INTEGER*2 dummy
  10369.  
  10370.             dummy = setvideomode( $MRES16COLOR )
  10371.             dummy = pie( $GBORDER, 80, 50, 240, 150, 240, 12, 0, 150 )
  10372.             READ (*,*)          ! Press ENTER to exit
  10373.             dummy = setvideomode( $DEFAULTMODE )
  10374.             END
  10375.  
  10376.  This program draws the "pie" wedge shown in Figure R.4.
  10377.  
  10378.  See also the example program for setpixel.
  10379.  
  10380.  
  10381.  putimage, putimage_w
  10382.  
  10383.  ■  Interface
  10384.  
  10385.       INTERFACE TO SUBROUTINE
  10386.       + putimage[FAR, C, ALIAS:"__putimage"](x, y, image, action)
  10387.       INTEGER*2 x, y                            ! Position of upper left corne
  10388.       INTEGER*2 action                          ! Interaction with existing sc
  10389.       INTEGER*1 image [FAR, REFERENCE](*)       ! Stored image buffer
  10390.       END
  10391.  
  10392.       INTERFACE TO SUBROUTINE
  10393.       + putimage_w[FAR, C, ALIAS:"__f_putimage_w"](wx, wy, image, action)
  10394.       INTEGER*2 wx, wy                          ! Position of upper left corne
  10395.       INTEGER*2 action                          ! Interaction with existing sc
  10396.       INTEGER*1 image [FAR, REFERENCE](*)       ! Stored image buffer
  10397.       END
  10398.  
  10399.  ■  Description
  10400.  
  10401.  The putimage function transfers to the screen the image stored in image. In
  10402.  the putimage function, the upper left corner of the image is placed at the
  10403.  viewport-coordinate point (x, y).
  10404.  
  10405.  In the putimage_w function, the upper left corner of the image is placed at
  10406.  the window-coordinate point (wx, wy).
  10407.  
  10408.  The action argument defines the interaction between the stored image and the
  10409.  one that is already on the screen. It may be any one of the following
  10410.  symbolic constants (defined in FGRAPH.FD):
  10411.  
  10412.          Constant                    Meaning
  10413.  
  10414.          $GAND                       Transfers the image over an
  10415.                                      existing image on the screen. The
  10416.                                      resulting image is the logical
  10417.                                      AND of the two images: points
  10418.                                      that have the same color in both
  10419.                                      the existing image and the new
  10420.                                      one will remain the same color,
  10421.                                      while points that have different
  10422.                                      colors are joined by logical AND.
  10423.  
  10424.          $GOR                        Superimposes the image onto an
  10425.                                      existing image. The new image
  10426.                                      does not erase the previous
  10427.                                      screen contents.
  10428.  
  10429.          $GPRESET                    Transfers the data point by point
  10430.                                      onto the screen. Each point has
  10431.                                      the inverse of the color
  10432.                                      attribute it had when it was
  10433.                                      taken from the screen by
  10434.                                      getimage, producing a negative
  10435.                                      image.
  10436.  
  10437.          $GPSET                      Transfers the data point by point
  10438.                                      onto the screen. Each point has
  10439.                                      the exact color attribute it had
  10440.                                      when it was taken from the screen
  10441.                                      by getimage.
  10442.  
  10443.          $GXOR                       Causes the points on the screen
  10444.                                      to be inverted where a point
  10445.                                      exists in the image buffer. This
  10446.                                      behavior is exactly like that of
  10447.                                      the cursor: when an image is put
  10448.                                      against a complex background
  10449.                                      twice, the background is restored
  10450.                                      unchanged. This allows you to
  10451.                                      move an object around without
  10452.                                      erasing the background. The $GXOR
  10453.                                      constant is a special mode often
  10454.                                      used for animation.
  10455.  
  10456.  ■  Return value
  10457.  
  10458.  There is no return value.
  10459.  
  10460.  ■  See also
  10461.  
  10462.       getimage, imagesize
  10463.  
  10464.  ■  Example
  10465.  
  10466.  See the example program for imagesize.
  10467.  
  10468.  
  10469.  rectangle, rectangle_w
  10470.  
  10471.  ■  Interface
  10472.  
  10473.       INTERFACE TO FUNCTION rectangle(control, x1, y1, x2, y2)
  10474.       INTEGER*2 rectangle[FAR, C, ALIAS:"__rectangle"]
  10475.       INTEGER*2 control                       ! Fill flag
  10476.       INTEGER*2 x1, y1                      ! Upper left corner
  10477.       INTEGER*2 x2, y2                      ! Lower right corner
  10478.       END
  10479.  
  10480.       INTERFACE TO FUNCTION rectangle_w(control, wx1, wy1, wx2, wy2)
  10481.       INTEGER*2 rectangle[FAR, C, ALIAS:"__f_rectangle_w"]
  10482.       INTEGER*2 control                      ! Fill flag
  10483.       DOUBLE PRECISION wx1, wy1              ! Upper left corner
  10484.       DOUBLE PRECISION wx2, wy2              ! Lower right corner
  10485.       END
  10486.  
  10487.  ■  Description
  10488.  
  10489.  The rectangle functions draw a rectangle with the current line style.
  10490.  
  10491.  The rectangle function uses the viewport-coordinate system. The
  10492.  viewport-coordinate points (x1, y1) and (x2, y2) are the diagonally opposed
  10493.  corners of the rectangle.
  10494.  
  10495.  The rectangle_w function uses the window-coordinate system. The
  10496.  window-coordinate points (wx1, wy1) and (wx2, wy2) are the diagonally
  10497.  opposed corners of the rectangle.
  10498.  
  10499.  The control parameter can be one of the following symbolic constants defined
  10500.  in the include file FGRAPH.FD:
  10501.  
  10502.       Constant                    Action
  10503.  
  10504.       $GFILLINTERIOR              Fills the figure with the current
  10505.                                   color using the current fill mask
  10506.  
  10507.       $GBORDER                    Does not fill the rectangle
  10508.  
  10509.  If the current fill mask is all zeros, no mask is used. Instead, the
  10510.  rectangle is filled with the current color.
  10511.  
  10512.  ───────────────────────────────────────────────────────────────────────────
  10513.  NOTE
  10514.     If you try to fill the rectangle with the floodfill function, the
  10515.     rectangle must be bordered by a solid line-style pattern.
  10516.  ───────────────────────────────────────────────────────────────────────────
  10517.  
  10518.  ■  Return value
  10519.  
  10520.  The rectangle and rectangle_w functions return a nonzero value if the
  10521.  rectangle is drawn successfully, 0 if not.
  10522.  
  10523.  ■  See also
  10524.  
  10525.       floodfill, getcolor, getlinestyle, setcolor, setlinestyle
  10526.  
  10527.  ■  Example
  10528.  
  10529.             INCLUDE   'FGRAPH.FI'
  10530.             INCLUDE   'FGRAPH.FD'
  10531.             INTEGER*2 dummy
  10532.  
  10533.             dummy = setvideomode( $MRES16COLOR )
  10534.             dummy = rectangle( $GBORDER, 80, 50, 240, 150 )
  10535.             READ (*,*)          ! Press ENTER to exit
  10536.             dummy = setvideomode( $DEFAULTMODE )
  10537.             END
  10538.  
  10539.  This program draws the rectangle shown in Figure R.5.
  10540.  
  10541.  See also the example program for setpixel, setvieworg, and setviewport.
  10542.  
  10543.  
  10544.  registerfonts
  10545.  
  10546.  ■  Interface
  10547.  
  10548.       INTERFACE TO FUNCTION registerfonts(filename)
  10549.       INTEGER*2 registerfonts
  10550.     + [FAR, C, ALIAS:"__f_registerfonts"]
  10551.       CHARACTER*(*) filename
  10552.     + [FAR, REFERENCE]            ! File name of .FON files to register
  10553.       END
  10554.  
  10555.  ■  Description
  10556.  
  10557.  The registerfonts function initializes the fonts graphics system. Font files
  10558.  must be registered with the registerfonts function before any other
  10559.  font-related library functions (getgtextextent, setfont, outgtext,
  10560.  unregisterfonts) can be used.
  10561.  
  10562.  The registerfonts function reads the specified files and loads font header
  10563.  information into memory. Each font header takes up about 140 bytes of
  10564.  memory.
  10565.  
  10566.  The filename argument is the path specification and file name of valid .FON
  10567.  files. The filename can contain standard DOS wild-card characters.
  10568.  
  10569.  ───────────────────────────────────────────────────────────────────────────
  10570.  NOTE
  10571.     The font functions affect only the output from the font output function
  10572.     outgtext; no other FORTRAN run-time output functions are affected by font
  10573.     usage.
  10574.  ───────────────────────────────────────────────────────────────────────────
  10575.  
  10576.  ■  Return value
  10577.  
  10578.  Returns a positive value that indicates the number of fonts successfully
  10579.  registered. A negative return value indicates failure. The following
  10580.  negative values may be returned:
  10581.  
  10582.       Value                  Meaning
  10583.  
  10584.       -1                     No such file or directory
  10585.  
  10586.       -2                     One or more of the .FON files was
  10587.                              not a valid, binary .FON file
  10588.  
  10589.       -3                     One or more of the .FON files is
  10590.                              damaged
  10591.  
  10592.  ■  See also
  10593.  
  10594.       getfontinfo, getgtextextent, outgtext, setfont, unregisterfonts
  10595.  
  10596.  ■  Example
  10597.  
  10598.       CC  FONTS.FOR - Illustrates fonts functions including:
  10599.       CC              getfontinfo     outgtext        setfont
  10600.       CC              getgtextextent  registerfonts   unregisterfonts
  10601.  
  10602.             INCLUDE  'FGRAPH.FI'
  10603.             INCLUDE  'FGRAPH.FD'
  10604.  
  10605.       PARAMETER            ( NFONTS = 6 )
  10606.  
  10607.             INTEGER*2            dummy, x, y, iend
  10608.             INTEGER*4            ifont
  10609.             CHARACTER*11         face(NFONTS)
  10610.             CHARACTER*10         options(NFONTS)
  10611.             CHARACTER*20         list
  10612.             CHARACTER*64         fontpath
  10613.             RECORD /videoconfig/ vc
  10614.             RECORD /xycoord/     xy
  10615.             RECORD /fontinfo/    fi
  10616.  
  10617.             DATA face    / "Courier"   , "Helvetica"  , "Times Roman",
  10618.            +               "Modern"    , "Script"     , "Roman"      /
  10619.             DATA options / "t'courier'", "t'helv'"    , "t'tms rmn'" ,
  10620.            +               "t'modern'" , "t'script'"  , "t'roman'"   /
  10621.  
  10622.             CALL clearscreen( $GCLEARSCREEN )
  10623.             WRITE (*,*) 'Enter file specification for .FON files'
  10624.             WRITE (*,*) '[pathname\*.FON]:'
  10625.             WRITE (*,*)
  10626.             READ  (*, '(A)') fondir
  10627.       C
  10628.       C     Locate .FON files, then register fonts by reading header
  10629.       C     information from all files.
  10630.       C
  10631.             IF( registerfonts( '*.FON' ). LT. 0 ) THEN
  10632.                WRITE (*, '(A/)') ' Enter directory for .FON files:'
  10633.                READ (*, '(A )') fontpath
  10634.                iend = INDEX( fontpath, ' ' )
  10635.                fontpath( iend:iend + 5 ) = '\*.FON'
  10636.                IF( registerfonts( fontpath ). LT. 0 )
  10637.            +       STOP 'Error: cannot find font files'
  10638.             ENDIF
  10639.  
  10640.       C
  10641.       C     Find graphics mode.
  10642.       C
  10643.             IF( setvideomode( $MAXRESMODE ) .EQ. 0 )
  10644.            +    STOP 'Error:  cannot set graphics mode'
  10645.             CALL getvideoconfig( vc )
  10646.  
  10647.       C
  10648.       C     Display each font name centered on screen.
  10649.       C
  10650.             DO ifont = 1, NFONTS
  10651.  
  10652.       C
  10653.       C        Build options string.
  10654.       C
  10655.                list = options( ifont ) // 'h30w24b'
  10656.  
  10657.                CALL clearscreen( $GCLEARSCREEN )
  10658.                IF( setfont( list ) .EQ. 0 ) THEN
  10659.       C
  10660.       C           Use length of text and height of font to center text.
  10661.       C
  10662.                   x = ( vc.numxpixels - getgtextextent
  10663.            +           ( face( ifont ) ) ) / 2
  10664.                   IF( getfontinfo( fi ) .NE. 0 ) THEN
  10665.                      CALL outtext( 'Error:  cannot get font info' )
  10666.                      READ (*,*)
  10667.                   END IF
  10668.                   y = ( vc.numypixels - fi.ascent ) / 2
  10669.                   CALL moveto( x, y, xy )
  10670.                   IF( vc.numcolors .GT. 2 ) dummy = setcolor( ifont )
  10671.                   CALL outgtext( face( ifont ) )
  10672.                ELSE
  10673.                   CALL outtext( 'Error:  cannot set font' )
  10674.                END IF
  10675.                READ (*,*)
  10676.             END DO
  10677.             CALL unregisterfonts()
  10678.             dummy = setvideomode( $DEFAULTMODE )
  10679.             END
  10680.  
  10681.  The program FONTS.FOR displays the fonts provided with the FORTRAN Graphics
  10682.  Library
  10683.  
  10684.  
  10685.  remapallpalette, remappalette
  10686.  
  10687.  ■  Interface
  10688.  
  10689.       INTERFACE TO FUNCTION remapallpalette(colors)
  10690.       INTEGER*2 remapallpalette[FAR, C, ALIAS:"__remapallpalette"]
  10691.       INTEGER*4 colors [FAR, REFERENCE](*)     ! Color value array
  10692.       END
  10693.  
  10694.       INTERFACE TO FUNCTION remappalette(index, color)
  10695.       INTEGER*4 remappalette[FAR, C, ALIAS:"__remappalette"]
  10696.       INTEGER*4 color                           ! Color value to assign color
  10697.       INTEGER*2 index                           ! Color index to reassign
  10698.       END
  10699.  
  10700.  ■  Description
  10701.  
  10702.  The remapallpalette function remaps all of the available color indexes
  10703.  simultaneously. The colors argument points to an array of color values. The
  10704.  default array of color indexes is shown below.
  10705.  
  10706.  
  10707.       Index      Color       Index     Color
  10708.  
  10709.       0          Black       8         Dark gray
  10710.       1          Blue        9         Light blue
  10711.       2          Green       10        Light green
  10712.       3          Cyan        11        Light cyan
  10713.       4          Red         12        Light red
  10714.       5          Magenta     13        Light magenta
  10715.       6          Brown       14        Yellow
  10716.       7          White       15        Bright white
  10717.  
  10718.  The number of colors mapped depends on the number of colors supported by the
  10719.  current video mode. A 16-color mode will map all the colors shown, from 0 to
  10720.  15. An eight-color mode will map only the colors from 0 to 7. A four-color
  10721.  mode will use one of the standard palettes supported by the EGA (see
  10722.  selectpalette). A two-color mode will support the colors 0 and 7 (black and
  10723.  white).
  10724.  
  10725.  If colors is an eight-element array whose members are 1, 3, 5, 7, 2, 4, 6,
  10726.  and 8, these color indexes would be mapped to actual colors in an
  10727.  eight-color video mode, as shown below.
  10728.  
  10729.  
  10730.       Index      Color     Index     Color
  10731.  
  10732.       1          Blue      5         Magenta
  10733.       2          Green     6         Brown
  10734.       3          Cyan      7         White
  10735.       4          Red       8         Dark gray
  10736.  
  10737.  You are simply mapping a set of color values to the ordinal numbers
  10738.  recognized by the hardware; colors can be larger than the number of colors
  10739.  supported by the current video mode. Only the first n colors are available,
  10740.  where n is the number of colors supported by the current video mode. The
  10741.  remappalette function remaps one color index to color, a color value
  10742.  supported by the current video mode. Both functions immediately affect the
  10743.  current display.
  10744.  
  10745.  The VGA color graphics modes support a palette of 262,144 colors (256K).
  10746.  Three bytes of data represent the intensities of red, blue, and green. In
  10747.  each byte, the two high-order bits must be 0. The remaining six bits
  10748.  represent the intensity of blue, green, and red (reading from high-order
  10749.  byte to low-order byte). For example, to make a low-intensity white color,
  10750.  equal values of red, green, and blue are used. Thus the three-byte color
  10751.  value is
  10752.  
  10753.       blue byte            green byte        red byte
  10754.       00011111             00011111          00011111
  10755.       high order ------------------------>   low order
  10756.  
  10757.  Because of the splitting of colors between bytes, the color values are not
  10758.  continuous. Symbolic constants for the default color values are supplied to
  10759.  provide compatibility with EGA practice. The names of these constants are
  10760.  listed below.
  10761.  
  10762.  
  10763.       Index      Constant     Index     Constant
  10764.  
  10765.       0          $BLACK        8        $GRAY
  10766.       1          $BLUE         9        $LIGHTBLUE
  10767.       2          $GREEN       10        $LIGHTGREEN
  10768.       3          $CYAN        11        $LIGHTCYAN
  10769.       4          $RED         12        $LIGHTRED
  10770.       5          $MAGENTA     13        $LIGHTMAGENTA
  10771.       6          $BROWN       14        $LIGHTYELLOW
  10772.       7          $WHITE       15        $BRIGHTWHITE
  10773.  
  10774.  Both the remappalette and remapallpalette functions work in all video modes,
  10775.  but only with an EGA or VGA.
  10776.  
  10777.  
  10778.  ■  Return value
  10779.  
  10780.  If successful, remapallpalette returns a nonzero value. If the function is
  10781.  inoperative (that is, running under a configuration other than an EGA or
  10782.  VGA), it returns 0.
  10783.  
  10784.  If successful, remappalette returns the previous color value for the given
  10785.  color index. If unsuccessful, it returns -1.
  10786.  
  10787.  
  10788.  ■  See also
  10789.  
  10790.       selectpalette, setbkcolor, setvideomode
  10791.  
  10792.  
  10793.  ■  Example
  10794.  
  10795.       CC  PALETTE.FOR - Illustrates functions for assigning color values
  10796.       CC                to color indexes.  Functions include:
  10797.       CC                remapallpalette    remappalette
  10798.  
  10799.             INCLUDE  'FGRAPH.FI'
  10800.             INCLUDE  'FGRAPH.FD'
  10801.  
  10802.             INTEGER*2            dummy2, mode, cells, x, y, xinc, yinc, i
  10803.             INTEGER*4            dummy4, pal( 256 ), iblue, ired, igreen
  10804.             INTEGER*4            RGB, tmp, inc
  10805.             CHARACTER*3          str1, str2
  10806.             RECORD /videoconfig/ vc
  10807.  
  10808.       C
  10809.       C     Make sure all palette numbers are valid.
  10810.       C
  10811.             DO i = 1, 256
  10812.                pal( i ) = $BLACK
  10813.             END DO
  10814.       C
  10815.       C     Loop through each graphics mode that supports palettes.
  10816.       C
  10817.  
  10818.             DO mode = $MRES4COLOR, $MRES256COLOR
  10819.                IF( mode .EQ. $ERESNOCOLOR ) CYCLE
  10820.                IF( setvideomode( mode ) .EQ. 0 ) CYCLE
  10821.  
  10822.       C
  10823.       C        Get configuration variables for current mode.
  10824.       C
  10825.                CALL getvideoconfig( vc )
  10826.                SELECT CASE( vc.numcolors )
  10827.  
  10828.                   CASE( 256 )
  10829.       C
  10830.       C              Active bits in this order:
  10831.       C              ???????? ??bbbbbb ??gggggg ??rrrrrr
  10832.       C
  10833.                      cells = 13
  10834.                      inc   = 12
  10835.  
  10836.                   CASE( 16 )
  10837.       C
  10838.       C              If $ERES or $VRES16, active bits in this order:
  10839.       C              ???????? ??????bb ??????gg ??????rr
  10840.       C
  10841.       C              Else in this order:
  10842.       C              ???????? ??????Bb ??????Gg ??????Rr
  10843.       C
  10844.                      cells = 4
  10845.                      inc   = 32
  10846.                      IF( ( vc.mode .EQ. $ERESCOLOR )  .OR.
  10847.            +             ( vc.mode .EQ. $VRES16COLOR ) ) inc = 16
  10848.  
  10849.                   CASE( 4 )
  10850.       C
  10851.       C              Active bits in this order:
  10852.       C              ???????? ??????Bb ??????Gg ??????Rr
  10853.       C
  10854.                      cells = 2
  10855.                      inc   = 32
  10856.  
  10857.                   CASE DEFAULT
  10858.                      CYCLE
  10859.  
  10860.                END SELECT
  10861.  
  10862.                xinc = vc.numxpixels / cells
  10863.                yinc = vc.numypixels / cells
  10864.  
  10865.       C
  10866.       C        Fill palette arrays in BGR order.
  10867.       C
  10868.                i = 1
  10869.                DO iblue = 0, 63, inc
  10870.                   DO igreen = 0, 63, inc
  10871.                      DO ired = 0, 63, inc
  10872.                         pal( i ) = RGB( ired, igreen, iblue )
  10873.       C
  10874.       C                 Special case: using 6 bits to represent 16 colors
  10875.       C                 If both bits are on for a color, intensity is set
  10876.       C                 If one bit is set for a color, the color is on.
  10877.       C
  10878.                         IF( inc .EQ. 32 )
  10879.            +                pal( i + 8 ) = pal( i ) .OR. ( pal( i ) / 2 )
  10880.                         i = i + 1
  10881.                      END DO
  10882.                   END DO
  10883.                END DO
  10884.       C
  10885.       C        If palettes available, remap all palettes at once.
  10886.       C        Otherwise, quit.
  10887.       C
  10888.                IF( remapallpalette( pal ) .EQ. 0 ) THEN
  10889.                   dummy2 = setvideomode( $DEFAULTMODE )
  10890.                   STOP 'Palettes not available with this adapter'
  10891.                END IF
  10892.       C
  10893.       C        Draw colored squares.
  10894.       C
  10895.                i = 0
  10896.                DO x = 0, ( xinc * cells ) - 1, xinc
  10897.                   DO y = 0, ( yinc * cells ) - 1, yinc
  10898.                      dummy2 = setcolor( INT4( i ) )
  10899.                      dummy2 = rectangle( $GFILLINTERIOR, x, y, x + xinc,
  10900.            +                             y + yinc )
  10901.                      i      = i + 1
  10902.                   END DO
  10903.                END DO
  10904.  
  10905.                dummy2 = setcolor( INT4( vc.numcolors / 2 ) )
  10906.                WRITE (str1, '(I3)') vc.mode
  10907.                WRITE (str2, '(I3)') vc.numcolors
  10908.                CALL outtext( 'Mode' // str1 // ' has' //
  10909.            +                  str2 // ' colors' )
  10910.                READ (*,*)
  10911.  
  10912.       C
  10913.       C        Change each palette entry separately in GRB order.
  10914.       C
  10915.                i = 0
  10916.                DO igreen = 0, 63, inc
  10917.                   DO ired = 0, 63, inc
  10918.                      DO iblue = 0, 63, inc
  10919.                         tmp    = RGB( ired, igreen, iblue )
  10920.                         dummy4 = remappalette( i, tmp )
  10921.                         IF( inc .EQ. 32 )
  10922.            +               dummy4 = remappalette(i + 8, tmp.OR.(tmp / 2))
  10923.                         i = i + 1
  10924.                      END DO
  10925.                   END DO
  10926.                END DO
  10927.  
  10928.       READ (*,*)      ! Wait for ENTER to be pressed
  10929.             END DO
  10930.  
  10931.             dummy2 = setvideomode( $DEFAULTMODE )
  10932.             END
  10933.  
  10934.  
  10935.  
  10936.       CC  RGB - Function for mixing red, green, and blue color elements.
  10937.       CC
  10938.       CC  Params: r, g, b - Values for red, green, and blue, respectively
  10939.       CC
  10940.       CC  Return: Mixed color value
  10941.  
  10942.             INTEGER*4 FUNCTION RGB( r, g, b )
  10943.             INTEGER*4 r, g, b
  10944.  
  10945.             RGB = ISHL( ISHL( b, 8 ) .OR. g, 8 ) .OR. r
  10946.             RETURN
  10947.             END
  10948.  
  10949.  The program PALETTE.FOR shows the effects of using and remapping palettes.
  10950.  
  10951.  
  10952.  selectpalette
  10953.  
  10954.  ■  Interface
  10955.  
  10956.       INTERFACE TO FUNCTION selectpalette(number)
  10957.       INTEGER*2 selectpalette[FAR, C, ALIAS:"__selectpalette"]
  10958.       INTEGER*2 number               ! Palette number
  10959.       END
  10960.  
  10961.  ■  Description
  10962.  
  10963.  The selectpalette function works only under the video modes $MRES4COLOR and
  10964.  $MRESNOCOLOR. A palette consists of a selectable background color (Color 0)
  10965.  and three set colors. Under the $MRES4COLOR mode the number argument selects
  10966.  one of the four predefined palettes shown in Table R.2.
  10967.  
  10968.  Table R.2  $MRES4COLOR Mode Palette Colors
  10969.  
  10970.                                  Color Index
  10971.       Palette
  10972.       Number        Color 1         Color 2           Color 3
  10973.  
  10974.       0             Green           Red               Brown
  10975.       1             Cyan            Magenta           Light gray
  10976.       2             Light green     Light red         Yellow
  10977.       3             Light cyan      Light magenta     White
  10978.  
  10979.  The $MRESNOCOLOR video mode is used with black-and-white displays, producing
  10980.  palettes consisting of various shades of gray. It will also produce color
  10981.  when used with a color display. The number of palettes available depends
  10982.  upon whether a CGA or EGA hardware package is employed. Under a CGA
  10983.  configuration, only the two palettes shown in Table R.3 are available.
  10984.  
  10985.  Table R.3  $MRESNOCOLOR Mode CGA Palette Colors
  10986.  
  10987.                                  Color Index
  10988.       Palette
  10989.       Number        Color 1         Color 2       Color 3
  10990.  
  10991.       0             Blue            Red           Light gray
  10992.       1             Light blue      Light red     White
  10993.  
  10994.  Under the EGA configuration, the three palettes shown in Table R.4 are
  10995.  available in the $MRESNOCOLOR video mode.
  10996.  
  10997.  Table R.4  $MRESNOCOLOR Mode EGA Palette Colors
  10998.  
  10999.                                Color Index
  11000.       Palette
  11001.       Number        Color 1         Color 2       Color 3
  11002.  
  11003.       0             Green           Red           Brown
  11004.       1             Light green     Light red     Yellow
  11005.       2             Light cyan      Light red     Yellow
  11006.  
  11007.  ───────────────────────────────────────────────────────────────────────────
  11008.  NOTE
  11009.     With an EGA in $MRESNOCOLOR video mode, Palette 3 is identical to
  11010.     Palette 1.
  11011.  ───────────────────────────────────────────────────────────────────────────
  11012.  
  11013.  ■  Return value
  11014.  
  11015.  Returns the value of the previous palette.
  11016.  
  11017.  ■  See also
  11018.  
  11019.       getvideoconfig, setvideomode
  11020.  
  11021.  ■  Example
  11022.  
  11023.       CC  CGAPAL.FOR - Illustrates CGA palettes using:
  11024.       CC               selectpalette
  11025.  
  11026.             INCLUDE  'FGRAPH.FI'
  11027.             INCLUDE  'FGRAPH.FD'
  11028.  
  11029.             INTEGER*2        dummy2
  11030.             INTEGER*4        dummy4, bkcolor( 8 )
  11031.             CHARACTER*7      bkname( 8 )
  11032.             CHARACTER*40     str
  11033.             RECORD /rccoord/ curpos
  11034.  
  11035.             DATA bkcolor / $BLACK , $BLUE    , $GREEN , $CYAN   ,
  11036.            +               $RED   , $MAGENTA , $BROWN , $WHITE  /
  11037.             DATA bkname  / 'BLACK', 'BLUE'   , 'GREEN', 'CYAN'  ,
  11038.            +               'RED'  , 'MAGENTA', 'BROWN', 'WHITE' /
  11039.  
  11040.       C
  11041.       C     Set video mode.
  11042.       C
  11043.             IF( setvideomode( $MRES4COLOR ) .EQ. 0 )
  11044.            +    STOP 'Error:  cannot set CGA color mode'
  11045.       C
  11046.       C     Palette loop
  11047.       C%
  11048.             DO i = 0, 3
  11049.                dummy2 = selectpalette( i )
  11050.       C
  11051.       C        Background color loop
  11052.       C
  11053.                DO k = 1, 8
  11054.                   CALL clearscreen( $GCLEARSCREEN )
  11055.                   dummy4 = setbkcolor( bkcolor(k) )
  11056.                   CALL settextposition( 1, 1, curpos )
  11057.                   WRITE ( str, 9000 ) bkname( k ), i
  11058.                   CALL outtext( str )
  11059.       C
  11060.       C           Foreground color loop
  11061.       C
  11062.                   DO j = 1, 3
  11063.                      dummy2 = setcolor( INT4( j ) )
  11064.                      dummy2 = ellipse( $GFILLINTERIOR, 100, j * 30, 220,
  11065.            +                           80 + ( j * 30 ) )
  11066.                   END DO
  11067.                   READ (*,*)    ! Wait for ENTER to be pressed
  11068.                END DO
  11069.             END DO
  11070.  
  11071.             dummy2 = setvideomode( $DEFAULTMODE )
  11072.  
  11073.        9000 FORMAT ('Background: ', A, 10x, 'Palette: ', I2)
  11074.  
  11075.             END
  11076.  
  11077.  The program CGAPAL.FOR draws a series of line segments while continuously
  11078.  changing the current palette.
  11079.  
  11080.  
  11081.  setactivepage
  11082.  
  11083.  ■  Interface
  11084.  
  11085.       INTERFACE TO FUNCTION setactivepage(page)
  11086.       INTEGER*2 setactivepage[FAR, C, ALIAS:"__setactivepage"]
  11087.       INTEGER*2 page        ! Memory page number
  11088.       END
  11089.  
  11090.  ■  Description
  11091.  
  11092.  For hardware and mode configurations with enough memory to support
  11093.  multiple-screen pages, setactivepage specifies where in memory graphics
  11094.  output is written. The page argument selects the current active page. The
  11095.  default page number is 0.
  11096.  
  11097.  Objects on the screen can be animated by alternating the graphics pages
  11098.  displayed. Use the setvisualpage function to display a completed graphics
  11099.  page while executing graphics statements in another active page.
  11100.  
  11101.  These functions can also be used to control text output if you use text
  11102.  functions, such as gettextcolor, gettextcursor, gettextposition, outtext,
  11103.  settextcolor, settextcursor, settextposition, settextwindow, and wrapon,
  11104.  instead of the standard FORTRAN I/O functions.
  11105.  
  11106.  This function is also available under OS/2.
  11107.  
  11108.  ───────────────────────────────────────────────────────────────────────────
  11109.  NOTE
  11110.     The CGA hardware configuration has only 16K of RAM available to support
  11111.     multiple-video pages, and only in the text mode. The EGA and VGA
  11112.     configurations may be equipped with up to 256K of RAM for multiple-video
  11113.     pages in graphics mode.
  11114.  ───────────────────────────────────────────────────────────────────────────
  11115.  
  11116.  ■  Return value
  11117.  
  11118.  If successful, returns the page number of the previous active page. If the
  11119.  function fails, it returns -1.
  11120.  
  11121.  ■  See also
  11122.  
  11123.       getactivepage, getvisualpage, gettextcolor, gettextposition, outtext,
  11124.       settextcolor, settextposition, settextwindow, setvideomode,
  11125.       setvisualpage, wrapon
  11126.  
  11127.  ■  Example
  11128.  
  11129.  See the example program for getactivepage.
  11130.  
  11131.  
  11132.  setbkcolor
  11133.  
  11134.  ■  Interface
  11135.  
  11136.       INTERFACE TO FUNCTION setbkcolor(color)
  11137.       INTEGER*4 setbkcolor[FAR, C, ALIAS:"__setbkcolor"]
  11138.       INTEGER*4 color                ! Desired color
  11139.       END
  11140.  
  11141.  ■  Description
  11142.  
  11143.  The setbkcolor function sets the current background color to the color value
  11144.  color.
  11145.  
  11146.  In a color text mode (such as $TEXTC80), setbkcolor accepts a color index.
  11147.  The value for the default colors is listed in the description of the
  11148.  settextcolor function. For example, setbkcolor(2)  sets the background color
  11149.  to color index 2. The actual color displayed depends on the palette mapping
  11150.  for pixel value 2. The default is green in a color text mode.
  11151.  
  11152.  In a color graphics mode (such as $ERESCOLOR), setbkcolor accepts a color
  11153.  value. The value for the background color is given by the symbolic constants
  11154.  defined in the include file FGRAPH.FD. For example, setbkcolor($GREEN) sets
  11155.  the background color in a graphics mode to green. These symbolic constants
  11156.  are provided as a convenience in defining and manipulating the most common
  11157.  colors. The actual range of colors is much greater.
  11158.  
  11159.  The function setcolor accepts an INTEGER*4 value as an argument. It is a
  11160.  color index.
  11161.  
  11162.  Whenever an argument is INTEGER*4, it refers to a color value, and whenever
  11163.  it is INTEGER*2, it refers to a color index. The two exceptions are the
  11164.  functions setbkcolor and getbkcolor.
  11165.  
  11166.  Since the background color is color index 0, the remappalette function will
  11167.  do the same thing that setbkcolor does. Unlike remappalette, however,
  11168.  setbkcolor does not require an EGA or VGA environment.
  11169.  
  11170.  In a text mode, the setbkcolor function does not affect anything already
  11171.  appearing on the display; stebkcolor affects only the subsequent output. In
  11172.  a graphics mode, it immediately changes all background pixels.
  11173.  
  11174.  This function is also available under OS/2.
  11175.  
  11176.  ■  Return value
  11177.  
  11178.  Returns the pixel color value of the old background color.
  11179.  
  11180.  ■  See also
  11181.  
  11182.       getbkcolor, remappalette, selectpalette
  11183.  
  11184.  ■  Example
  11185.  
  11186.  See the example program for gettextcolor.
  11187.  
  11188.  
  11189.  setcliprgn
  11190.  
  11191.  ■  Interface
  11192.  
  11193.       INTERFACE TO SUBROUTINE
  11194.     + setcliprgn[FAR, C, ALIAS:"__setcliprgn"](x1, y1, x2, x2)
  11195.       INTEGER*2 x1, y1           ! Upper left corner of clip region
  11196.       INTEGER*2 x2, y2           ! Lower right corner of clip region
  11197.       END
  11198.  
  11199.  ■  Description
  11200.  
  11201.  The setcliprgn function limits the display of subsequent graphics output and
  11202.  font text output to the part that fits within a particular area of the
  11203.  screen (the "clipping region"). The physical points (x1, y1) and (x2, y2)
  11204.  are the upper left and lower right corners of the rectangle that defines the
  11205.  clipping region. The setcliprgn function does not change the
  11206.  viewport-coordinate system; it merely masks the screen.
  11207.  
  11208.  ───────────────────────────────────────────────────────────────────────────
  11209.  NOTE
  11210.     The setcliprgn function affects graphics and font text output only. To
  11211.     mask the screen for text output, use the settextwindow function.
  11212.  ───────────────────────────────────────────────────────────────────────────
  11213.  
  11214.  ■  Return value
  11215.  
  11216.  There is no return value.
  11217.  
  11218.  ■  See also
  11219.  
  11220.       settextwindow, setvieworg, setviewport, setwindow
  11221.  
  11222.  ■  Example
  11223.  
  11224.             INCLUDE   'FGRAPH.FI'
  11225.             INCLUDE   'FGRAPH.FD'
  11226.             INTEGER*2 dummy
  11227.  
  11228.             dummy = setvideomode( $MRES16COLOR )
  11229.             CALL    setcliprgn( 0, 0, 200, 125 )
  11230.             dummy = ellipse( $GBORDER, 80, 50, 240, 200 )
  11231.             READ (*,*)          ! Press ENTER to exit
  11232.             dummy = setvideomode( $DEFAULTMODE )
  11233.             END
  11234.  
  11235.  This program draws an ellipse lying partly within a clipping region, as
  11236.  shown in Figure R.6.
  11237.  
  11238.  See also the example program for setvieworg.
  11239.  
  11240.  
  11241.  setcolor
  11242.  
  11243.  ■  Interface
  11244.  
  11245.       INTERFACE TO FUNCTION setcolor(color)
  11246.       INTEGER*2 setcolor[FAR, C, ALIAS:"__setcolor"]
  11247.       INTEGER*2 color               ! Desired color index
  11248.       END
  11249.  
  11250.  ■  Description
  11251.  
  11252.  The setcolor function sets the current color index to color. The color
  11253.  parameter is masked but always within range. The following graphics
  11254.  functions use the current color: arc, ellipse, floodfill, lineto, outgtext,
  11255.  pie, rectangle, and setpixel.
  11256.  
  11257.  The setcolor function accepts an INTEGER*2 value as an argument. It is a
  11258.  color index.
  11259.  
  11260.  The default color index is the highest numbered color index in the current
  11261.  palette.
  11262.  
  11263.  ■  Return value
  11264.  
  11265.  Returns the previous color. If setcolor fails (if used in a text mode), it
  11266.  returns -1.
  11267.  
  11268.  ■  See also
  11269.  
  11270.       arc, ellipse, floodfill, getcolor, lineto, outgtext, pie, rectangle,
  11271.       selectpalette, setpixel
  11272.  
  11273.  ■  Example
  11274.  
  11275.  See the example program for setlinestyle.
  11276.  
  11277.  
  11278.  setfillmask
  11279.  
  11280.  ■  Interface
  11281.  
  11282.       INTERFACE TO SUBROUTINE
  11283.       + setfillmask[FAR, C, ALIAS:"__setfillmask"](mask)
  11284.       INTEGER*1 mask[FAR, REFERENCE](8)     ! Mask array
  11285.       END
  11286.  
  11287.  ■  Description
  11288.  
  11289.  The setfillmask function sets the current fill mask. The mask is an
  11290.  8-by-8-bit array, where each bit represents a pixel. A 1 bit sets the
  11291.  corresponding pixel to the current color, while a 0 bit leaves the pixel
  11292.  unchanged. The mask is repeated over the entire fill area.
  11293.  
  11294.  If no fill mask is set (mask is all zeros──the default), only the current
  11295.  color is used in fill operations.
  11296.  
  11297.  ■  Return value
  11298.  
  11299.  There is no return value.
  11300.  
  11301.  ■  See also
  11302.  
  11303.       ellipse, floodfill, getfillmask, pie, rectangle
  11304.  
  11305.  ■  Example
  11306.  
  11307.             PROGRAM Fill
  11308.             INCLUDE 'FGRAPH.FD'
  11309.             INCLUDE 'FGRAPH.FI'
  11310.  
  11311.             INTEGER*1 style(8,6)/ #18, #18, #18, #18, #18, #18, #18, #18,
  11312.            +                      #08, #08, #08, #08, #08, #08, #08, #08,
  11313.            +                      #18, #00, #18, #18, #18, #00, #18, #18,
  11314.            +                      #00, #08, #00, #08, #08, #08, #08, #08,
  11315.            +                      #18, #18, #00, #18, #18, #00, #18, #18,
  11316.            +                     #08, #00, #08, #00, #08, #00, #08, #00 /
  11317.  
  11318.             INTEGER*1 oldstyle(8)  ! Placeholder for old style
  11319.             INTEGER loop
  11320.  
  11321.             dummy2 = setvideomode( $MRES4COLOR )
  11322.             CALL getfillmask( oldstyle )
  11323.       C
  11324.       C     Draw an ellipse under the middle few rectangles in a
  11325.       C     different color.
  11326.       C
  11327.             dummy2 = setcolor( 2 )
  11328.             dummy2 = ellipse( $GFILLINTERIOR, 120, 75, 200, 125 )
  11329.             dummy2 = setcolor( 3 )
  11330.             DO loop = 1, 6
  11331.  
  11332.       C
  11333.       C     Make 6 rectangles.
  11334.       C
  11335.                CALL setfillmask( style(1,loop) )
  11336.                dummy2 = rectangle( $GFILLINTERIOR, loop*40+5,90
  11337.            +                                      (loop+1)*40, 110 )
  11338.             END DO
  11339.  
  11340.             CALL setfillmask( oldstyle )   ! Restore old style
  11341.             READ (*,*)                     ! Wait for ENTER to be pressed
  11342.             dummy2 = setvode( $DEFAULTMODE )
  11343.             END
  11344.  
  11345.  This program draws an ellipse overlaid with six rectangles, each with a
  11346.  different fill mask, as shown in Figure R.7.
  11347.  
  11348.  See also the example program for setlinestyle.
  11349.  
  11350.  
  11351.  setfont
  11352.  
  11353.  ■  Interface
  11354.  
  11355.       INTERFACE TO FUNCTION setfont(options)
  11356.       CHARACTER *(*) options
  11357.     + [FAR, REFERENCE]                     ! String describing font characteri
  11358.       INTEGER*2 setfont[FAR, C, ALIAS: "__f_setfont"]
  11359.       END
  11360.  
  11361.  ■  Description
  11362.  
  11363.  The setfont finds a single font, from the set of registered fonts, that has
  11364.  the characteristics specified by the options parameter.
  11365.  
  11366.  If a font is found, it is set to the current font. The current font is used
  11367.  in all subsequent calls to the outgtext function. There can be only one
  11368.  active font.
  11369.  
  11370.  The setfont function searches the list of registered fonts for a font
  11371.  matching the specified characteristics.
  11372.  
  11373.  The function's argument consists of letter codes that describe the desired
  11374.  font. The option code specified in the options parameter are not case or
  11375.  position sensitive.
  11376.  
  11377.       Option                      Description
  11378.  
  11379.       t'fontname'                 Name the desired typeface
  11380.  
  11381.       hy                          Select character height, where y
  11382.                                   is the number of pixels
  11383.  
  11384.       wx                           Select character width, where x
  11385.                                    is the number of pixels
  11386.  
  11387.       f                            Select only a fixed-space font
  11388.                                    (should not be used with the p
  11389.                                    characteristic)
  11390.  
  11391.       p                            Select only a proportional-space
  11392.                                    font (should not be used with the
  11393.                                    f characteristic)
  11394.  
  11395.       v                            Select only a vector-mapped font
  11396.                                    (should not be used with the r
  11397.                                    characteristic)
  11398.  
  11399.       r                            Select only a raster-mapped
  11400.                                    ("bit-mapped") font (should not
  11401.                                    be used with the v
  11402.                                    characteristic)
  11403.  
  11404.       b                            Select the font that best fits
  11405.                                    the other parameters specified
  11406.  
  11407.       nx                           Select font number x, where x is
  11408.                                    less than or equal to the value
  11409.                                    returned by the registerfonts
  11410.                                    function
  11411.  
  11412.  You can request as many options as desired, except with nx, which should be
  11413.  used alone. If mutually exclusive options are requested (such as the pair
  11414.  f/p or r/v), the setfont function ignores them. There is no error detection
  11415.  for incompatible parameters used with nx.
  11416.  
  11417.  The t typeface specification option is specified as a "t" followed by the
  11418.  name of the font in apostrophes. The fontname may be any of the following
  11419.  valid fonts:
  11420.  
  11421.       Font Name                   Description
  11422.  
  11423.       Courier                     Fixed-width bit-mapped font with
  11424.                                   serifs
  11425.  
  11426.       Helv                        Sans serif proportional
  11427.                                   bit-mapped font
  11428.  
  11429.       Tms Rmn                     Proportional bit-mapped font with
  11430.                                   serifs
  11431.  
  11432.       Script                      Proportional vector-mapped font
  11433.                                   of slanted characters formed from
  11434.                                   nearly continuous lines
  11435.  
  11436.       Modern                      Proportional vector-mapped font
  11437.                                   without serifs
  11438.  
  11439.       Roman                       Proportional vector-mapped font
  11440.                                   with serifs
  11441.  
  11442.  A "b" in the options field causes the setfont routine to automatically
  11443.  select the "best fit" font that matches the other characteristics you have
  11444.  specified.
  11445.  
  11446.  If the b option is specified and at least one font is registered, setfont
  11447.  will always be able to set a font and will return 0 to indicate success.
  11448.  
  11449.  In selecting a font, the setfont routine uses the following precedence,
  11450.  rated from highest precedence to lowest:
  11451.  
  11452.    1. Pixel height
  11453.    2. Typeface
  11454.    3. Pixel width
  11455.    4. Fixed or proportional font
  11456.  
  11457.  You can also specify a pixel width and height for fonts. If a nonexistent
  11458.  value is chosen for either, and the b option is specified, the setfont
  11459.  function will choose the closest match.
  11460.  
  11461.  A smaller font size has precedence over a larger size. If setfont requests
  11462.  Helv 12 with best fit, and only Helv 10 and Helv 14 are available, setfont
  11463.  will select Helv 10.
  11464.  
  11465.  If you specify the nx parameter, setfont will ignore any other specified
  11466.  options and supply only the font number corresponding to x.
  11467.  
  11468.  If a nonexistent value is chosen for pixel height and width, the setfont
  11469.  function will apply a magnification factor to a vector-mapped font to obtain
  11470.  a suitable font size. This automatic magnification does not apply if the r
  11471.  (raster-mapped font) option is specified, or if a specific typeface is
  11472.  requested and there is no best-fit (b) option specified.
  11473.  
  11474.  ───────────────────────────────────────────────────────────────────────────
  11475.  NOTE
  11476.     The font functions affect only the output from the font-output function
  11477.     outgtext; no other FORTRAN Graphics Library run-time output functions are
  11478.     affected by font usage.
  11479.  ───────────────────────────────────────────────────────────────────────────
  11480.  
  11481.  ■  Return value
  11482.  
  11483.  Returns 0 to indicate success and -1 to indicate an error.
  11484.  
  11485.  An error occurs if a request for a specific font fails and the b option was
  11486.  not specified, or if fonts have not yet been registered.
  11487.  
  11488.  ■  See also
  11489.  
  11490.       getfontinfo, getgtextextent, outgtext, registerfonts, unregisterfonts
  11491.  
  11492.  ■  Example
  11493.  
  11494.  See the example program for registerfonts.
  11495.  
  11496.  
  11497.  setlinestyle
  11498.  
  11499.  ■  Interface
  11500.  
  11501.       INTERFACE TO SUBROUTINE
  11502.     + setlinestyle[FAR, C, ALIAS:"__setlinestyle"](mask)
  11503.       INTEGER*2 mask        ! Desired line-style mask
  11504.       END
  11505.  
  11506.  ■  Description
  11507.  
  11508.  The setlinestyle function selects the mask (line style) used for line
  11509.  drawing. The mask is a 16-bit number, where each bit represents a pixel in
  11510.  the line being drawn. If a bit is 1, the corresponding pixel is set to the
  11511.  color of the line (the current color). If a bit is 0, the corresponding
  11512.  pixel is left unchanged. The template is repeated for the entire length of
  11513.  the line. The default mask is #FFFF (a solid line). The setlinestyle
  11514.  function does not alter the styles for arcs, ellipses, or "pie-slice"
  11515.  wedges.
  11516.  
  11517.  ■  Return value
  11518.  
  11519.  There is no return value.
  11520.  
  11521.  ■  See also
  11522.  
  11523.       getlinestyle, lineto, rectangle
  11524.  
  11525.  ■  Example
  11526.  
  11527.       CC  FILL.FOR - Illustrates color, filling, and linestyle functions
  11528.       CC             including:         floodfill            setfillmask
  11529.       CC                                getlinestyle         setlinestyle
  11530.       CC                                setcolor
  11531.       CC
  11532.       CC  The getfillmask function is not shown, but its use is similar
  11533.       CC  to getlinestyle.
  11534.  
  11535.             INCLUDE  'FGRAPH.FI'
  11536.             INCLUDE  'FGRAPH.FD'
  11537.  
  11538.             INTEGER*1            fill(8)
  11539.             INTEGER*2            dummy, xinc, yinc, i,
  11540.            +                     irand, xwid, ywid, rseed
  11541.             INTEGER*4            ncolor
  11542.             REAL*4               rand
  11543.             RECORD /xycoord/     xy
  11544.             RECORD /videoconfig/ vc
  11545.  
  11546.       C
  11547.       C     Find graphics mode.
  11548.       C
  11549.             IF( setvideomode( $MAXRESMODE ) .EQ. 0 )
  11550.            +   STOP 'Error:  cannot set graphics mode'
  11551.             CALL getvideoconfig( vc )
  11552.  
  11553.       C
  11554.       C     Size variables to mode.
  11555.       C
  11556.             xinc = vc.numxpixels / 8.0
  11557.             yinc = vc.numypixels / 8.0
  11558.             xwid = ( xinc / 2.0 ) - 4.0
  11559.             ywid = ( yinc / 2.0 ) - 4.0
  11560.  
  11561.       C
  11562.       C     Seed random-number generator.
  11563.       C
  11564.             CALL GETTIM( dummy, dummy, dummy, rseed)
  11565.             CALL SEED( rseed )
  11566.  
  11567.       C
  11568.       C     Draw ellipses and lines with different patterns.
  11569.       C
  11570.             DO x = xinc, ( vc.numxpixels - xinc ), xinc
  11571.                DO y = yinc, ( vc.numypixels - yinc ), yinc
  11572.       C
  11573.       C           Randomize fill and color.  Array FILL holds
  11574.       C           random numbers between 0 and 255.
  11575.       C
  11576.                   DO i = 1, 8
  11577.                      CALL RANDOM( rand )
  11578.                      fill(i) = INT1( rand * 256.0 )
  11579.                   END DO
  11580.  
  11581.                   CALL setfillmask( fill )
  11582.                   irand  = rand * 256.0
  11583.                   ncolor = MOD( irand, vc.numcolors ) + 1
  11584.                   dummy  = setcolor( ncolor )
  11585.  
  11586.       C
  11587.       C           Draw ellipse and fill with random color.
  11588.       C
  11589.                   dummy  = ellipse( $GBORDER, x - xwid, y - ywid,
  11590.            +                         x + xwid, y + ywid )
  11591.                   CALL RANDOM( rand )
  11592.                   irand  = rand * 256.0
  11593.                   i      = ncolor
  11594.                   ncolor = MOD( irand, vc.numcolors ) + 1
  11595.                   dummy  = setcolor( ncolor )
  11596.                   dummy  = floodfill( x, y, i )
  11597.       C
  11598.       C           Draw vertical and horizontal lines. Vertical line style
  11599.       C           is anything other than horizontal style. Since lines
  11600.       C           are overdrawn with several line styles, this has the
  11601.       C           effect of combining colors and styles.
  11602.       C
  11603.                   CALL RANDOM( rand )
  11604.                   irand = rand * 256.0
  11605.                   CALL setlinestyle( irand )
  11606.                   CALL moveto( 0, y + ywid + 4, xy )
  11607.                   dummy = lineto( vc.numxpixels - 1, y + ywid + 4 )
  11608.       C
  11609.       C           Get linestyle, invert bits, and reset linestyle.
  11610.       C
  11611.                   CALL setlinestyle( 255 - getlinestyle() )
  11612.                   CALL moveto( x + xwid + 4, 0, xy )
  11613.                   dummy = lineto( x + xwid + 4, vc.numypixels - 1 )
  11614.                END DO
  11615.             END DO
  11616.  
  11617.             READ (*,*)       ! Wait for ENTER to be pressed
  11618.             dummy = setvideomode( $DEFAULTMODE )
  11619.             END
  11620.  
  11621.  This program draws filled ovals and lines on the screen. It uses a variety
  11622.  of fill patterns and line styles in different colors.
  11623.  
  11624.  
  11625.  setpixel, setpixel_w
  11626.  
  11627.  ■  Interface
  11628.  
  11629.       INTERFACE TO FUNCTION setpixel(x, y)
  11630.       INTEGER*2 setpixel[FAR, C, ALIAS:"__setpixel"]
  11631.       INTEGER*2 x, y                                    ! Target pixel
  11632.       END
  11633.  
  11634.       INTERFACE TO FUNCTION setpixel_w(wx, wy)
  11635.       INTEGER*2 setpixel[FAR, C, ALIAS:"__f_setpixel_w"]
  11636.       DOUBLE PRECISION wx, wy                           ! Target pixel
  11637.       END
  11638.  
  11639.  ■  Description
  11640.  
  11641.  The setpixel  and the setpixel_w functions set a pixel at a specified
  11642.  location to the current color.
  11643.  
  11644.  The function setpixel sets the pixel at the viewport-coordinate point (x, y)
  11645.  to the current color.
  11646.  
  11647.  The function setpixel_w sets the pixel at the window-coordinate point (wx,
  11648.  wy) to the current color.
  11649.  
  11650.  ■  Return value
  11651.  
  11652.  The setpixel and setpixel_w functions return the previous value of the
  11653.  target pixel. If the function fails (for example, the point lies outside of
  11654.  the clipping region), it returns -1.
  11655.  
  11656.  ■  See also
  11657.  
  11658.       getpixel, setcolor
  11659.  
  11660.  ■  Example
  11661.  
  11662.       CC  FIGURE.FOR - Illustrates graphics drawing functions including:
  11663.       CC               arc      ineto     pie         setpixel
  11664.       CC               ellipse  moveto    rectangle
  11665.  
  11666.             INCLUDE  'FGRAPH.FI'
  11667.             INCLUDE  'FGRAPH.FD'
  11668.  
  11669.             INTEGER*2        dummy, x, y
  11670.             INTEGER*4        ncolor
  11671.             RECORD /xycoord/ xy
  11672.  
  11673.       C
  11674.       C     Find graphics mode.
  11675.       C
  11676.             IF ( setvideomode( $MAXRESMODE ) .EQ. 0 )
  11677.            +     STOP 'Error:  cannot set graphics mode'
  11678.  
  11679.             WRITE (*,*) ' Press ENTER to continue'
  11680.       C
  11681.       C     Draw pixels.
  11682.       C
  11683.             ncolor = 2
  11684.             dummy  = setcolor( ncolor )
  11685.             x      = 10
  11686.             DO y = 50, 89, 3
  11687.                dummy = setpixel( x, y )
  11688.                x     = x + 2
  11689.             END DO
  11690.             READ (*,*) ! Wait for ENTER to be pressed
  11691.       C
  11692.       C     Draw lines.
  11693.       C
  11694.             ncolor = ncolor + 1
  11695.             dummy  = setcolor( ncolor )
  11696.             x      = 60
  11697.             DO y = 50, 89, 3
  11698.                CALL moveto( x, y, xy )
  11699.                dummy = lineto( x + 20, y )
  11700.             END DO
  11701.             READ (*,*) ! Wait for ENTER to be pressed
  11702.       C
  11703.       C     Draw rectangles.
  11704.       C
  11705.             ncolor = ncolor + 1
  11706.             dummy  = setcolor( ncolor )
  11707.             x      = 110
  11708.             y      = 70
  11709.             dummy  = rectangle( $GBORDER,       x - 20, y - 20, x, y )
  11710.             dummy  = rectangle( $GFILLINTERIOR, x + 20, y + 20, x, y )
  11711.             READ (*,*) ! Wait for ENTER to be pressed
  11712.       C
  11713.       C     Draw ellipses.
  11714.       C
  11715.             ncolor = ncolor + 1
  11716.             dummy  = setcolor( ncolor )
  11717.             x      = 160
  11718.             dummy  = ellipse( $GBORDER,       x - 20, y - 20, x, y )
  11719.             dummy  = ellipse( $GFILLINTERIOR, x + 20, y + 20, x, y )
  11720.             READ (*,*) ! Wait for ENTER to be pressed
  11721.  
  11722.       C
  11723.       C     Draw arcs.
  11724.       C
  11725.             ncolor = ncolor + 1
  11726.             dummy  = setcolor( ncolor )
  11727.             x      = 210
  11728.             dummy  = arc( x - 20, y - 20, x, y, x, y - 10, x - 10, y )
  11729.             dummy  = arc( x + 20, y + 20, x, y, x + 10, y + 20, x + 20,
  11730.            +              y + 10 )
  11731.             READ (*,*) ! Wait for ENTER to be pressed
  11732.       C
  11733.       C     Draw pies.
  11734.       C
  11735.             ncolor = ncolor + 1
  11736.             dummy  = setcolor( ncolor )
  11737.             x      = 260
  11738.             dummy  = pie( $GBORDER,   x - 20, y - 20, x, y, x,
  11739.            +              y - 10, x - 10, y )
  11740.             dummy  = pie( $GFILLINTERIOR, x + 20, y + 20, x, y, x + 10,
  11741.            +              y + 20, x + 20, y + 10 )
  11742.             READ (*,*) ! Wait for ENTER to be pressed
  11743.             dummy = setvideomode( $DEFAULTMODE )
  11744.             END
  11745.  
  11746.  The program FIGURE.FOR draws a series of small shapes in a variety of
  11747.  colors.
  11748.  
  11749.  
  11750.  settextcolor
  11751.  
  11752.  ■  Interface
  11753.  
  11754.       INTERFACE TO FUNCTION settextcolor(index)
  11755.       INTEGER*2 settextcolor[FAR, C, ALIAS:"__settextcolor"]
  11756.       INTEGER*2 index               ! Desired color index
  11757.       END
  11758.  
  11759.  ■  Description
  11760.  
  11761.  The settextcolor function sets the current text color. The value of index
  11762.  specifies the new color index; the default value is the same as the maximum
  11763.  color index. The settextcolor routine sets the color for the outtext
  11764.  function. It does not affect the color of the WRITE statement or the color
  11765.  of text output with the outgtext font routine. Use the setcolor function to
  11766.  change the color of font output.
  11767.  
  11768.  In text color mode, you can specify a color index in the range 0-31. The
  11769.  colors in the range 0-15 are interpreted to be normal; colors in the range
  11770.  16-31 are the same as those in the range 0-15, except that the text blinks.
  11771.  The normal color range is defined below.
  11772.  
  11773.       Index      Color       Index     Color
  11774.  
  11775.       0          Black       8         Dark gray
  11776.       1          Blue        9         Light blue
  11777.       2          Green       10        Light green
  11778.       3          Cyan        11        Light cyan
  11779.       4          Red         12        Light red
  11780.       5          Magenta     13        Light magenta
  11781.       6          Brown       14        Yellow
  11782.       7          White       15        Bright white
  11783.  
  11784.  In every text mode, including monochrome, the getvideoconfig function
  11785.  returns the value 32 for the number of available colors. The value 32
  11786.  indicates the range of values (0-31) accepted by the settextcolor function.
  11787.  This includes 16 normal colors (0-15) and 16 blinking colors (16-31). To
  11788.  select blinking text, add 16 to the normal color value. Some color values
  11789.  appear the same on monochrome monitors. However, because blinking is
  11790.  selected in the same manner, the text mode for monochrome monitors uses the
  11791.  same range (0-31) as the color text mode.
  11792.  
  11793.  This function is also available under OS/2.
  11794.  
  11795.  ■  Return value
  11796.  
  11797.  Returns the color index of the previous text color.
  11798.  
  11799.  ■  See also
  11800.  
  11801.       gettextcolor, outtext
  11802.  
  11803.  ■  Example
  11804.  
  11805.  See the example program for gettextcolor.
  11806.  
  11807.  
  11808.  settextcursor
  11809.  
  11810.  ■  Interface
  11811.  
  11812.       INTERFACE TO FUNCTION settextcursor(attr)
  11813.       INTEGER*2 settextcursor[FAR, C, ALIAS:"__settextcursor"]
  11814.       INTEGER*2 attr         ! Cursor attribute
  11815.       END
  11816.  
  11817.  ■  Description
  11818.  
  11819.  The settextcursor function sets the cursor shape based on the attribute
  11820.  specified by attr. The high-order byte of attr determines the start line of
  11821.  the cursor. The low-order byte of attr determines the stop line of the
  11822.  cursor. The settextcursor function uses the same format as the BIOS routines
  11823.  in setting the cursor. Values for the cursor attribute are shown below.
  11824.  
  11825.       Attribute              Cursor Shape
  11826.  
  11827.       #0707                  Underline
  11828.  
  11829.       #0007                  Full block cursor
  11830.  
  11831.       #0607                  Double underline
  11832.  
  11833.       #2000                  No cursor
  11834.  
  11835.  This function is also available under OS/2. Note that this function works
  11836.  only in text video modes.
  11837.  
  11838.  ■  Return value
  11839.  
  11840.  Returns the previous cursor attribute or -1 if an error occurs, such as
  11841.  calling the function in a graphics screen mode.
  11842.  
  11843.  ■  See also
  11844.  
  11845.       displaycursor, gettextcursor
  11846.  
  11847.  ■  Example
  11848.  
  11849.       CC  CURSOR.FOR - Illustrates cursor functions including:
  11850.       CC               displaycursor  gettextcursor  settextcursor
  11851.  
  11852.             INCLUDE  'FGRAPH.FI'
  11853.             INCLUDE  'FGRAPH.FD'
  11854.  
  11855.             INTEGER*2            dummy, oldcursor, newcursor,
  11856.            +                     curs_start, curs_end, block
  11857.             CHARACTER*40         str
  11858.             RECORD /rccoord/     curpos
  11859.             RECORD /videoconfig/ vc
  11860.  
  11861.       C
  11862.       C     Save old cursor shape and make sure cursor is on.
  11863.       C
  11864.  
  11865.             CALL clearscreen( $GCLEARSCREEN )
  11866.             oldcursor = gettextcursor()
  11867.             dummy     = displaycursor( $GCURSORON )
  11868.             CALL settextposition( 1, 1, curpos )
  11869.             CALL outtext( 'Press ENTER to continue . . .' )
  11870.       C
  11871.       C     Change cursor shape.
  11872.       C     Color cursor uses scan lines 0-7, monochrome uses 0-13.
  11873.       C
  11874.             CALL getvideoconfig( vc )
  11875.             block = 7
  11876.             IF( vc.mode .EQ. $TEXTMONO ) block = 13
  11877.             curs_start = 0
  11878.             DO curs_end = block, 0, -1
  11879.                CALL settextposition( 10, 1, curpos )
  11880.                WRITE (str, 9000) curs_start, curs_end
  11881.                CALL outtext( str )
  11882.                newcursor = (curs_start * 256) + curs_end
  11883.                dummy     = settextcursor( newcursor )
  11884.                READ (*,*)  ! Wait for ENTER to be pressed
  11885.                curs_start = curs_start + 1
  11886.             END DO
  11887.  
  11888.             WRITE (str, '(A13)') 'Cursor off:  '
  11889.             CALL settextposition( 12, 1, curpos )
  11890.             CALL outtext( str, 13 )
  11891.             dummy = displaycursor( $GCURSOROFF )
  11892.             READ (*,*)  ! Wait for ENTER to be pressed
  11893.             WRITE (str, '(A13)') 'Cursor on :  '
  11894.             CALL settextposition( 13, 1, curpos )
  11895.             CALL outtext( str )
  11896.             dummy = settextcursor( block )
  11897.             dummy = displaycursor( $GCURSORON )
  11898.             READ (*,*)  ! Wait for ENTER to be pressed
  11899.       C
  11900.       C     Restore original cursor shape.
  11901.       C
  11902.             dummy = settextcursor( oldcursor )
  11903.             CALL clearscreen( $GCLEARSCREEN )
  11904.  
  11905.        9000 FORMAT ( 'Start line:', I4, 8x, 'Endline:', I4, 3x )
  11906.  
  11907.             END
  11908.  
  11909.  The program CURSOR.FOR shows the effect of changing the start and stop lines
  11910.  for the cursor, and the effect of turning the cursor off and on.
  11911.  
  11912.  
  11913.  settextposition
  11914.  
  11915.  ■  Interface
  11916.  
  11917.       INTERFACE TO SUBROUTINE
  11918.     + settextposition[FAR, C, ALIAS:"__f_settextposition"](row, column, s)
  11919.       INTEGER*2 row, column              ! New output start position
  11920.       STRUCTURE/rccoord/
  11921.             INTEGER*2 row                ! Row coordinate
  11922.             INTEGER*2 col                ! Column coordinate
  11923.       END STRUCTURE
  11924.       RECORD/rccoord/s                   ! Returns the previous text position
  11925.       END
  11926.  
  11927.  ■  Description
  11928.  
  11929.  This function relocates the current text position to the display point (row,
  11930.  column). Subsequent text produced with the outtext function (as well as
  11931.  standard console I/O routines, such as PRINT) begins at that point.
  11932.  
  11933.  The previous text position is returned in the rccoord structure variable s,
  11934.  defined in FGRAPH.FD.
  11935.  
  11936.  This subroutine is also available under OS/2.
  11937.  
  11938.  ───────────────────────────────────────────────────────────────────────────
  11939.  WARNING
  11940.     The WRITE statement sent its carriage-return (CR) and line-feed (LF)
  11941.     characters to the screen at the beginning of the first I/O statement
  11942.     following the WRITE statement. This can cause unpredictable text
  11943.     positioning if you mix the graphics routines settextposition and outtext
  11944.     with the WRITE statement. You can minimize the effect by using the
  11945.     backslash (\) format descriptor (suppress the CR-LF characters) in the
  11946.     associated FORMAT statement.
  11947.  ───────────────────────────────────────────────────────────────────────────
  11948.  
  11949.  ■  Return value
  11950.  
  11951.  There is no return value.
  11952.  
  11953.  ■  See also
  11954.  
  11955.       gettextposition, outtext, settextwindow
  11956.  
  11957.  ■  Example
  11958.  
  11959.  See the example program for setviewport.
  11960.  
  11961.  
  11962.  settextrows
  11963.  
  11964.  ■  Interface
  11965.  
  11966.       INTERFACE TO FUNCTION settextrows(rows)
  11967.       INTEGER*2 settextrows[FAR, C, ALIAS:"__settextrows"]
  11968.       INTEGER*2 rows         ! Number of text rows
  11969.       END
  11970.  
  11971.  ■  Description
  11972.  
  11973.  The settextrows function specifies the number of text rows used in text
  11974.  modes, requiring hardware that supports 43- or 50-line modes, such as VGA or
  11975.  EGA. In the rows argument, $MAXTEXTROWS chooses the number of rows
  11976.  available: in text mode, 50 rows (VGA); 43 (EGA); and 25 on all others. In
  11977.  graphics modes supporting 30 or 60 rows, it chooses  60. This function is
  11978.  also available under OS/2.
  11979.  
  11980.  ■  Return value
  11981.  
  11982.  Returns the numbers of rows set, or returns 0 if an error occurred.
  11983.  
  11984.  ■  See also
  11985.  
  11986.       getvideoconfig, setvideomode, setvideomoderows
  11987.  
  11988.  ■  Example
  11989.  
  11990.       CC  SETROWS.FOR - Illustrates: settextrows
  11991.  
  11992.             INCLUDE  'FGRAPH.FI'
  11993.             INCLUDE  'FGRAPH.FD'
  11994.  
  11995.             INTEGER*2    rows
  11996.             CHARACTER*2  arg
  11997.       C
  11998.       C     Get command line argument: 25, 43, or 50.
  11999.       C
  12000.             CALL GETARG( 1, arg, 2 )
  12001.             rows = 0
  12002.             IF( arg .EQ. '25' ) rows = 25
  12003.             IF( arg .EQ. '43' ) rows = 43
  12004.             IF( arg .EQ. '50' ) rows = 50
  12005.       C
  12006.       C     Make sure new rows are valid and the same as requested rows.
  12007.       C
  12008.             IF( (rows .EQ. 0) .OR. (settextrows( rows ) .NE. rows) ) THEN
  12009.                WRITE (*,*) 'Syntax: SETROWS [ 25 | 43 | 50 ]'
  12010.                STOP 01
  12011.             END IF
  12012.       C
  12013.       C     Return 0 if successful
  12014.       C
  12015.             STOP 00
  12016.             END
  12017.  
  12018.  This program accepts a command-line argument, checking for a valid number of
  12019.  rows for the current display.
  12020.  
  12021.  
  12022.  settextwindow
  12023.  
  12024.  ■  Interface
  12025.  
  12026.       INTERFACE TO SUBROUTINE
  12027.       + settextwindow[FAR, C, ALIAS:"__settextwindow"](r1, c1, r2, c2)
  12028.       INTEGER*2 r1, c1           ! Upper left corner of window
  12029.       INTEGER*2 r2, c2           ! Lower right corner of window
  12030.       END
  12031.  
  12032.  ■  Description
  12033.  
  12034.  The settextwindow function specifies a window in row and column coordinates
  12035.  where all the text output to the screen is displayed. The arguments (r1, c1)
  12036.  specify the upper left corner of the text window, and the arguments (r2, c2)
  12037.  specify the lower right corner of the text window.
  12038.  
  12039.  Text is output from the top of the text window down. When the text window is
  12040.  full, the lines begin to scroll off the top of the window.
  12041.  
  12042.  ───────────────────────────────────────────────────────────────────────────
  12043.  NOTE
  12044.     This function does not affect the output of the font display routine
  12045.     outgtext. Use the setviewport function to control the display area for
  12046.     fonts.
  12047.  ───────────────────────────────────────────────────────────────────────────
  12048.  
  12049.  This subroutine is also available under OS/2.
  12050.  
  12051.  ■  Return value
  12052.  
  12053.  There is no return value.
  12054.  
  12055.  ■  See also
  12056.  
  12057.       gettextposition, outtext, settextposition
  12058.  
  12059.  ■  Example
  12060.  
  12061.  See the example program for setvideomoderows.
  12062.  
  12063.  
  12064.  setvideomode
  12065.  
  12066.  
  12067.  ■  Interface
  12068.  
  12069.       INTERFACE TO FUNCTION setvideomode(mode)
  12070.       INTEGER*2 setvideomode[FAR, C, ALIAS:"__setvideomode"]
  12071.       INTEGER*2 mode         ! Desired mode
  12072.       END
  12073.  
  12074.  ■  Description
  12075.  
  12076.  The setvideomode function selects a screen mode appropriate for a particular
  12077.  hardware/ display configuration. The mode argument can be one of the
  12078.  symbolic constants shown in Table R.5 below and defined in FGRAPH.FD.
  12079.  
  12080.  $MAXCOLORMODE and $MAXRESMODE in the mode argument choose the graphics mode
  12081.  with the most colors or the highest resolution, respectively. They fail for
  12082.  adapters that have no graphics modes. Table R.6 below shows the specific
  12083.  modes selected by the constants $MAXCOLORMODE and $MAXRESMODE for different
  12084.  adapter/monitor combinations.
  12085.  
  12086.  In $HERCMONO mode, only monochrome (two-color) text and graphics are
  12087.  supported. The screen resolution is 720 by 348 pixels. The text dimensions
  12088.  are 80 columns by 25 rows, with a 9-by-14-character box. The bottom two scan
  12089.  lines of row 25 are not visible.
  12090.  
  12091.  You must install the Hercules driver MSHERC.COM before running your program.
  12092.  Type MSHERC  to load the driver. This can be done from an AUTOEXEC.BAT file.
  12093.  
  12094.  If you use both a Hercules monochrome and a color video card, install
  12095.  MSHERC.COM with the /H (/HALF) option. The /H option causes the driver to
  12096.  use one instead of two graphics pages. This prevents the two video cards
  12097.  from attempting to use the same memory. You do not have to use the /H option
  12098.  if you have only a Hercules card. See your Hercules hardware manual for more
  12099.  details on compatibility.
  12100.  
  12101.  This function is also available under OS/2.
  12102.  
  12103.  ■  Return value
  12104.  
  12105.  Returns the number of text rows if the function is successful. If an error
  12106.  occurs (that is, if the mode selected is not supported by the current
  12107.  hardware configuration), the function returns 0.
  12108.  
  12109.  ■  See also
  12110.  
  12111.       getvideoconfig
  12112.  
  12113.  ■  Example
  12114.  
  12115.  See the example program for setvideomoderows.
  12116.  
  12117.  Table R.5  Symbolic Constants for Screen Mode
  12118.  
  12119.  Mode             Type                 Size        Colors       Adapter
  12120.  $DEFAULTMODE     Hardware              Hardware     Hardware      Hardware
  12121.                   default               default      default       default
  12122.  $TEXTBW40        M/T                   40 x 25      16            CGA
  12123.  $TEXTC40         C/T                   40 x 25      16            CGA
  12124.  $TEXTBW80        M/T                   80 x 25      16            CGA
  12125.  $TEXTC80         C/T                   80 x 25       6            CGA
  12126.  $MRES4COLOR      C/G                   320 x 200     4            CGA
  12127.  $MRESNOCOLOR     M/G                   320 x 200     4            CGA
  12128.  $HRESBW          M/G                   640 x 200     2            CGA
  12129.  $TEXTMONO        M/T                   80 x 25       1            MDPA
  12130.  $HERCMONO        Hercules graphics     ---          ---           HGC
  12131.  $MRES16COLOR     C/G                   320 x 200    16            EGA
  12132.  $HRES16COLOR     C/G                   640 x 200    16            EGA
  12133.  $ERESNOCOLOR     M/T                   640 x 350     1            EGA
  12134.  $ERESCOLOR       C/G                   640 x 350    64            EGA
  12135.  $VRES2COLOR      C/G                   640  480      2            VGA
  12136.  $VRES16COLOR     C/G                   640  480     16            VGA
  12137.  $MRES256COLOR    C/G                   320  200    256            VGA
  12138.  $ORESCOLOR       C/G                   640  400    1 of 16        Olivetti co
  12139.                                                                    graphics
  12140.  $MAXCOLORMODE    C/G                See Table R.6  Maximum        CGA
  12141.  $MAXRESMODE      C/G                   Maximum     See Table R.6  CGA
  12142.  
  12143.  
  12144.  Table R.6  Modes Selected by $MAXCOLORMODE and $MAXRESMODE
  12145.  
  12146.  Adapter/Monitor      $MAXCOLORMODE     $MAXRESMODE
  12147.  
  12148.  MDPA                 Fail              Fail
  12149.  HGC                  $HERCMONO         $HERCMONO
  12150.  CGA Color           $MRES4COLOR       $HRESBW
  12151.  CGA Noncolor        $MRESNOCOLOR      $HRESBW
  12152.  OCGA                 $MRES4COLOR       $ORESCOLOR
  12153.  OEGA Color           $ERESCOLOR        $ORESCOLOR
  12154.  EGA Color 256K       $HRES16COLOR      $HRES16COLOR
  12155.  EGA Color 64K        $HRES16COLOR      $HRES16COLOR
  12156.  EGA > 256K           $ERESCOLOR        $ERESCOLOR
  12157.  EGA > 64K            $HRES16COLOR      $ERESCOLOR
  12158.  EGA Mono             $ERESNOCOLOR      $ERESNOCOLOR
  12159.  MCGA                 $MRES256COLOR     $VRES2COLOR
  12160.  VGA/OVGA             $MRES256COLOR     $VRES16COLOR
  12161.  
  12162.  ───────────────────────────────────────────────────────────────────────────
  12163.  NOTE
  12164.     Only standard hardware is described here, but display hardware that is
  12165.     strictly compatible with IBM, Hercules, or Olivetti hardware should also
  12166.     work as described.
  12167.  ───────────────────────────────────────────────────────────────────────────
  12168.  
  12169.  
  12170.  setvideomoderows
  12171.  
  12172.  ■  Interface
  12173.  
  12174.       INTERFACE TO FUNCTION setvideomoderows(mode, rows)
  12175.       INTEGER*2 setvideomoderows[FAR, C, ALIAS:"__setvideomoderows"]
  12176.       INTEGER*2 mode                  ! Desired mode
  12177.       INTEGER*2 rows                  ! Number of text rows
  12178.       END
  12179.  
  12180.  ■  Description
  12181.  
  12182.  The setvideomoderows function selects a screen mode for a particular
  12183.  hardware/display combination. The options for the symbolic constant mode
  12184.  (the screen mode) are given in the reference pages for setvideomode.
  12185.  
  12186.  The setvideomoderows argument rows specifies the number of text rows to be
  12187.  used in a text mode. Optionally, placing the constant $MAXTEXTROWS in the
  12188.  rows argument chooses the maximum number of rows available. In text mode
  12189.  this is 50 rows for a VGA, 43 for an EGA, and 25 on all others. In graphics
  12190.  modes that support 30 or 60 rows,  $MAXTEXTROWS  chooses 60 rows.
  12191.  
  12192.  ■  Return value
  12193.  
  12194.  Returns the numbers of rows set. The function returns 0 if an error occurred
  12195.  (for example, if the mode is not supported).
  12196.  
  12197.  ■  See also
  12198.  
  12199.       getvideoconfig, settextrows, setvideomode
  12200.  
  12201.  ■  Example
  12202.  
  12203.       CC  MODES.FOR - Illustrates configuration and text window
  12204.       CC              functions including:
  12205.       CC              getvideoconfig     outtext         settextwindow
  12206.       CC              setvideomoderows   setvideomode
  12207.  
  12208.             INCLUDE  'FGRAPH.FI'
  12209.             INCLUDE  'FGRAPH.FD'
  12210.  
  12211.             PARAMETER            ( NUM_ROWS =  5 )
  12212.             PARAMETER            ( NUM_MODE = 17 )
  12213.  
  12214.             INTEGER*2              dummy, irow, x, y
  12215.             INTEGER*2              modes( NUM_MODE ), rows( NUM_ROWS )
  12216.             CHARACTER*12           names( NUM_MODE ), str
  12217.             RECORD / videoconfig / vc
  12218.  
  12219.             DATA modes / $TEXTBW40     ,  $TEXTC40     ,  $TEXTBW80    ,
  12220.            +             $TEXTC80      ,  $MRES4COLOR  ,  $MRESNOCOLOR ,
  12221.            +             $HRESBW       ,  $TEXTMONO    ,  $HERCMONO    ,
  12222.            +             $MRES16COLOR  ,  $HRES16COLOR ,  $ERESNOCOLOR ,
  12223.            +             $ERESCOLOR    ,  $VRES2COLOR  ,  $VRES16COLOR ,
  12224.            +             $MRES256COLOR ,  $ORESCOLOR   /
  12225.  
  12226.  
  12227.             DATA names / '    $TEXTBW40', '    $TEXTC40', '   $TEXTBW80',
  12228.            +             '     $TEXTC80', ' $MRES4COLOR', '$MRESNOCOLOR',
  12229.            +             '      $HRESBW', '   $TEXTMONO', '   $HERCMONO',
  12230.            +             ' $MRES16COLOR', '$HRES16COLOR', '$ERESNOCOLOR',
  12231.            +             '   $ERESCOLOR', ' $VRES2COLOR', '$VRES16COLOR',
  12232.            +             '$MRES256COLOR', '  $ORESCOLOR' /
  12233.  
  12234.             DATA rows  / 60, 50, 43, 30, 25 /
  12235.  
  12236.             dummy = displaycursor( $GCURSOROFF )
  12237.       C
  12238.       C     Try each mode.
  12239.       C
  12240.             DO i = 1, NUM_MODE
  12241.                DO j = 1, NUM_ROWS
  12242.       C
  12243.       C           Try each possible number of rows.
  12244.       C
  12245.                   irow = setvideomoderows( modes(i), rows(j) )
  12246.                   IF( ( irow .EQ. 0 )  .OR.  (rows(j) .NE. irow) ) THEN
  12247.                      GOTO 100
  12248.                   ELSE
  12249.                      CALL getvideoconfig( vc )
  12250.                      y = ( vc.numtextrows - 12 ) / 2
  12251.                      x = ( vc.numtextcols - 25 ) / 2
  12252.                   END IF
  12253.       C
  12254.       C           Use text window to place output in middle of screen.
  12255.       C
  12256.                   CALL settextwindow( y, x, vc.numtextrows - y,
  12257.            +                          vc.numtextcols - x - 2 )
  12258.       C
  12259.       C           Display all information on the screen.
  12260.       C
  12261.                   CALL outtext( 'Video mode:  ' // names(i) )
  12262.                   WRITE (str, '(I12)') vc.numxpixels
  12263.                   CALL outtext( 'X pixels:    ' // str )
  12264.                   WRITE (str, '(I12)') vc.numypixels
  12265.                   CALL outtext( 'Y pixels:    ' // str )
  12266.                   WRITE (str, '(I12)') vc.numtextcols
  12267.                   CALL outtext( 'Text columns:' // str )
  12268.                   WRITE (str, '(I12)') vc.numtextrows
  12269.                   CALL outtext( 'Text rows:   ' // str )
  12270.                   WRITE (str, '(I12)') vc.numcolors
  12271.                   CALL outtext( 'Colors:      ' // str )
  12272.                   WRITE (str, '(I12)') vc.bitsperpixel
  12273.                   CALL outtext( 'Bits/pixel:  ' // str )
  12274.  
  12275.                   WRITE (str, '(I12)') vc.numvideopages
  12276.                   CALL outtext( 'Video pages: ' // str )
  12277.                   WRITE (str, '(I12)') vc.mode
  12278.                   CALL outtext( 'Mode:        ' // str )
  12279.                   WRITE (str, '(I12)') vc.adapter
  12280.                   CALL outtext( 'Adapter:     ' // str )
  12281.                   WRITE (str, '(I12)') vc.monitor
  12282.                   CALL outtext( 'Monitor:     ' // str )
  12283.                   WRITE (str, '(I12)') vc.memory
  12284.                   CALL outtext( 'Memory:      ' // str )
  12285.  
  12286.                   READ (*,*)  ! Wait for ENTER to be pressed
  12287.         100    END DO
  12288.             END DO
  12289.  
  12290.             dummy = displaycursor( $GCURSORON )
  12291.             dummy = setvideomode( $DEFAULTMODE )
  12292.             END
  12293.  
  12294.  The program MODES.FOR demonstrates each of the possible mode and row
  12295.  combinations.
  12296.  
  12297.  
  12298.  setvieworg
  12299.  
  12300.  ■  Interface
  12301.  
  12302.       INTERFACE TO SUBROUTINE
  12303.       + setvieworg[FAR, C, ALIAS:"__f_setvieworg"](x, y, s)
  12304.       INTEGER*2 x, y                      ! New origin point
  12305.       STRUCTURE/xycoord/
  12306.             INTEGER*2 xcoord                          ! x-coordinate
  12307.             INTEGER*2 ycoord                          ! y-coordinate
  12308.       END STRUCTURE
  12309.       RECORD/xycoord/s[FAR, REFERENCE]                ! Returns the previous v
  12310.       END
  12311.  
  12312.  ■  Description
  12313.  
  12314.  The setvieworg function moves the view-coordinate origin (0, 0) to the
  12315.  physical point (x, y). All other view-coordinate points move the same
  12316.  direction and distance.
  12317.  
  12318.  The xycoord structure variable s, defined in FGRAPH.FD, returns the physical
  12319.  coordinates of the previous view origin.
  12320.  
  12321.  ■  Return value
  12322.  
  12323.  There is no return value.
  12324.  
  12325.  ■  See also
  12326.  
  12327.       getphyscoord, getviewcoord, getwindowcoord, setcliprgn, setviewport
  12328.  
  12329.  ■  Example
  12330.  
  12331.       CC  WINDOW.FOR - Illustrates windows and coordinate systems using
  12332.       CC               the following functions:
  12333.       CC               clearscreen    ellipse        ellipse_w
  12334.       CC               rectangle      rectangle_w    setcliprgn
  12335.       CC               setvieworg     setviewport    setwindow
  12336.       CC
  12337.       CC  Although not all illustrated here, functions ending in _w
  12338.       CC  are similar to rectangle_w and ellipse_w.
  12339.  
  12340.             INCLUDE  'FGRAPH.FI'
  12341.             INCLUDE  'FGRAPH.FD'
  12342.  
  12343.             INTEGER*2  dummy, xhalf, yhalf, xquar, yquar
  12344.             DOUBLE PRECISION  x_upleft, y_upleft, x_botrght, y_botrght
  12345.             RECORD / xycoord /     xy
  12346.             RECORD / videoconfig / vc
  12347.  
  12348.       C
  12349.       C     Find graphics mode.
  12350.       C
  12351.             IF( setvideomode( $MAXRESMODE ) .EQ. 0 )
  12352.            +    STOP 'Error:  cannot set graphics mode'
  12353.             CALL getvideoconfig( vc )
  12354.  
  12355.             xhalf = vc.numxpixels / 2
  12356.             yhalf = vc.numypixels / 2
  12357.             xquar = xhalf / 2
  12358.             yquar = yhalf / 2
  12359.  
  12360.       C
  12361.       C     First window - integer physical coordinates
  12362.       C
  12363.             CALL setviewport( 0, 0, xhalf - 1, yhalf - 1 )
  12364.             dummy = setcolor( 2 )
  12365.             dummy = rectangle( $GBORDER, 0, 0, xhalf - 1, yhalf - 1 )
  12366.             dummy = setcolor( 1 )
  12367.             dummy = ellipse( $GFILLINTERIOR, xquar / 4, yquar / 4,
  12368.            +                 xhalf - (xquar / 4), yhalf - (yquar / 4) )
  12369.             READ (*,*) ! Wait for ENTER to be pressed
  12370.             CALL clearscreen( $GVIEWPORT )
  12371.             dummy = rectangle( $GBORDER, 0, 0, xhalf - 1, yhalf - 1 )
  12372.  
  12373.       C
  12374.       C     Second window - integer world coordinates with clip region
  12375.       C
  12376.             CALL setcliprgn( xhalf, 0, vc.numxpixels, yhalf )
  12377.             CALL setvieworg( xhalf + xquar - 1, yquar - 1, xy )
  12378.             dummy = setcolor( 3 )
  12379.             dummy = rectangle( $GBORDER, -xquar + 1, -yquar + 1, xquar,
  12380.            +                   yquar )
  12381.             dummy = setcolor( 2 )
  12382.             dummy = ellipse( $GFILLINTERIOR, (-xquar * 3) / 4,
  12383.            +                 (-yquar * 3) / 4, (xquar * 3) / 4,
  12384.            +                 (yquar * 3) / 4 )
  12385.             READ (*,*) ! Wait for ENTER to be pressed
  12386.             CALL clearscreen( $GVIEWPORT )
  12387.             dummy = rectangle( $GBORDER, -xquar + 1, -yquar + 1, xquar,
  12388.            +                   yquar )
  12389.  
  12390.       C
  12391.       C     Third window
  12392.       C
  12393.             CALL setviewport( xhalf, yhalf, vc.numxpixels - 1,
  12394.            +                  vc.numypixels - 1 )
  12395.             dummy = setwindow( .FALSE., -4.0, -5.0, 4.0, 5.0 )
  12396.             dummy = setcolor( 4 )
  12397.             dummy = rectangle_w( $GBORDER, -4.0, -5.0, 4.0, 5.0 )
  12398.             dummy = setcolor( 3 )
  12399.             dummy = ellipse_w( $GFILLINTERIOR, -3.0, -3.5, 3.0, 3.5 )
  12400.             READ (*,*) ! Wait for ENTER to be pressed
  12401.             CALL clearscreen( $GVIEWPORT )
  12402.             dummy = rectangle_w( $GBORDER, -4.0, -5.0, 4.0, 5.0 )
  12403.  
  12404.       C
  12405.       C     Fourth window
  12406.       C
  12407.             CALL setviewport( 0, yhalf, xhalf - 1, vc.numypixels - 1 )
  12408.             dummy = setwindow( .FALSE., -4.0, -5.0, 4.0, 5.0 )
  12409.             x_upleft  = -4.0
  12410.             y_upleft  = -5.0
  12411.             x_botrght =  4.0
  12412.             y_botrght =  5.0
  12413.             dummy = setcolor( 5 )
  12414.             dummy = rectangle_w( $GBORDER, x_upleft, y_upleft,
  12415.            +                     x_botrght, y_botrght )
  12416.             x_upleft  = -3.0
  12417.             y_upleft  = -3.5
  12418.             x_botrght =  3.0
  12419.             y_botrght =  3.5
  12420.             dummy = setcolor( 4 )
  12421.             dummy = ellipse_w( $GFILLINTERIOR, x_upleft, y_upleft,
  12422.            +                   x_botrght, y_botrght )
  12423.  
  12424.             READ (*,*) ! Wait for ENTER to be pressed
  12425.             dummy = setvideomode( $DEFAULTMODE )
  12426.             END
  12427.  
  12428.  The program WINDOW.FOR draws several windows, using different methods and
  12429.  options for each window.
  12430.  
  12431.  
  12432.  setviewport
  12433.  
  12434.  ■  Interface
  12435.  
  12436.       INTERFACE TO SUBROUTINE
  12437.     + setviewport[FAR, C, ALIAS:"__setviewport"](x1, y1, x2, y2)
  12438.       INTEGER*2 x1, y1          ! Upper left corner of viewport
  12439.       INTEGER*2 x2, y2          ! Lower right corner of viewport
  12440.       END
  12441.  
  12442.  ■  Description
  12443.  
  12444.  The setviewport function redefines the graphics viewport. The setviewport
  12445.  function defines a clipping region in the same manner as setcliprgn, and
  12446.  then sets the viewport-coordinate origin to the upper left corner of the
  12447.  region. The physical points (x1, y1) and (x2, y2) are the upper left and
  12448.  lower right corners of the rectangular clipping region. Any window
  12449.  transformation done with the setwindow function applies only to the viewport
  12450.  and not to the entire screen.
  12451.  
  12452.  ■  Return value
  12453.  
  12454.  There is no return value.
  12455.  
  12456.  ■  See also
  12457.  
  12458.       setcliprgn, setvieworg, setwindow
  12459.  
  12460.  ■  Example
  12461.  
  12462.       CC  MAGNIFY.FOR - Illustrates translation between window and view
  12463.       CC                coordinate systems using the following functions:
  12464.       CC                getphyscoord     getviewcoord   getviewcoord_w
  12465.       CC                getwindowcoord   lineto         moveto
  12466.       CC                rectangle        rectangle_w    settextposition
  12467.       CC                setwindow        setviewport
  12468.       CC
  12469.       CC  Although not all illustrated here, functions ending in _w
  12470.       CC  are similar to rectangle_w.
  12471.  
  12472.             INCLUDE  'FGRAPH.FI'
  12473.             INCLUDE  'FGRAPH.FD'
  12474.  
  12475.             INTEGER*2              dummy, rseed, j, k, m, n
  12476.             INTEGER*2              coord(3,2,2), fill(2)
  12477.             INTEGER*4              i
  12478.             REAL*4                 rand
  12479.             DOUBLE PRECISION       x(2), y(2)
  12480.             CHARACTER*18           text
  12481.             RECORD / xycoord  /    xy, xy1
  12482.             RECORD / wxycoord /    wxy
  12483.             RECORD / rccoord  /    curpos
  12484.             RECORD / videoconfig / vc
  12485.  
  12486.             DATA text / 'magnification:  1x' /
  12487.             DATA fill / $GFILLINTERIOR, $GBORDER /
  12488.  
  12489.       C
  12490.       C     Find graphics mode.
  12491.       C
  12492.             IF( setvideomode( $MAXRESMODE ) .EQ. 0 )
  12493.            +    STOP 'Error:  cannot set graphics mode'
  12494.             CALL getvideoconfig( vc )
  12495.  
  12496.       C
  12497.       C     Find physical (pixel) coordinates for windows 1, 2, and 3.
  12498.       C
  12499.             coord(1,1,1) = vc.numxpixels * 3 / 16
  12500.             coord(1,1,2) = vc.numypixels * 7 / 32
  12501.             coord(1,2,1) = coord(1,1,1) + vc.numxpixels / 8
  12502.             coord(1,2,2) = coord(1,1,2) + vc.numypixels / 16
  12503.             coord(2,1,1) = vc.numxpixels * 9 / 16
  12504.             coord(2,1,2) = vc.numypixels * 5 / 32
  12505.             coord(2,2,1) = coord(2,1,1) + vc.numxpixels * 3 / 8
  12506.             coord(2,2,2) = coord(2,1,2) + vc.numypixels * 3 / 16
  12507.             coord(3,1,1) = 0
  12508.             coord(3,1,2) = vc.numypixels / 2
  12509.             coord(3,2,1) = vc.numxpixels - 1
  12510.             coord(3,2,2) = vc.numypixels - 1
  12511.  
  12512.       C
  12513.       C     Connect windows with lines.
  12514.       C
  12515.             dummy = setcolor( 4 )
  12516.             DO i = 1, 2
  12517.                DO j = 1, 2
  12518.                   DO k = 1, 2
  12519.                      CALL moveto( coord(i,j,1), coord(i,k,2), xy )
  12520.                      dummy = lineto( coord(i + 1,j,1), coord(i + 1,k,2) )
  12521.                   END DO
  12522.                END DO
  12523.             END DO
  12524.  
  12525.       C
  12526.       C     Label windows and frame with rectangles.
  12527.       C
  12528.             DO i = 1, 3
  12529.                dummy  = setcolor( i )
  12530.                row    = ( coord(i,1,2) * 25 ) / vc.numypixels
  12531.                column = ( coord(i,1,1) * 80 ) / vc.numxpixels
  12532.                CALL settextposition( row, column, curpos )
  12533.                CALL outtext( text )
  12534.                text(17:17) = '3'
  12535.  
  12536.  
  12537.                IF( i .EQ. 2 ) text(17:17) = '8'
  12538.                CALL setviewport(  coord(i,1,1), coord(i,1,2) ,
  12539.            +                      coord(i,2,1), coord(i,2,2) )
  12540.                CALL getviewcoord( coord(i,1,1), coord(i,1,2), xy  )
  12541.                CALL getviewcoord( coord(i,2,1), coord(i,2,2), xy1 )
  12542.                dummy = rectangle( $GBORDER, xy.xcoord, xy.ycoord,
  12543.            +                      xy1.xcoord, xy1.ycoord )
  12544.             END DO
  12545.  
  12546.       C
  12547.       C     Seed random number generator.
  12548.       C
  12549.             CALL GETTIM( dummy, dummy, dummy, rseed )
  12550.             CALL SEED( rseed )
  12551.       C
  12552.       C     Get random window coordinates (x, y) for rectangles,
  12553.       C     where x and y are between 0 and 1000.
  12554.       C
  12555.             DO i = 8, 15
  12556.                dummy = setcolor( i )
  12557.                CALL RANDOM( rand )
  12558.                x(1)  = rand * 980.0
  12559.                x(2)  = rand * ( 999.0 - x(1) ) + x(1)
  12560.                CALL RANDOM( rand )
  12561.                y(1)  = rand * 980.0
  12562.                y(2)  = rand * ( 999.0 - y(1) ) + y(1)
  12563.                k     = rand + 1.5
  12564.  
  12565.       C
  12566.       C        Display rectangles in normal and magnified views.
  12567.       C
  12568.                DO j = 1, 3
  12569.                   CALL setviewport( coord(j,1,1), coord(j,1,2) ,
  12570.            +                        coord(j,2,1), coord(j,2,2) )
  12571.                   dummy = setwindow( .TRUE., 0.0, 0.0, 1000.0, 1000.0 )
  12572.                   dummy = rectangle_w( fill(k), x(1), y(1), x(2), y(2) )
  12573.  
  12574.       C
  12575.       C           In last window, make rectangle sides 2 pixels wide by
  12576.       C           encasing unfilled rectangles with another rectangle.
  12577.       C           Convert window coords (x, y) to physical coords,
  12578.       C           adjust, and translate back into window coords.
  12579.       C
  12580.                   IF( (j .EQ. 3)  .AND.  (k .EQ. 2) ) THEN
  12581.                      m = -1
  12582.                      DO n = 1, 2
  12583.                         CALL getviewcoord_w( x(n), y(n), xy )
  12584.                         CALL getphyscoord( xy.xcoord, xy.ycoord, xy )
  12585.                         CALL getviewcoord( xy.xcoord+m, xy.ycoord+m, xy )
  12586.                         CALL getwindowcoord( xy.xcoord, xy.ycoord, wxy )
  12587.                         x(n) = wxy.wx
  12588.                         y(n) = wxy.wy
  12589.                         m    = 1
  12590.                      END DO
  12591.                   dummy = rectangle_w( fill(k), x(1), y(1), x(2), y(2) )
  12592.                   END IF
  12593.                END DO
  12594.             END DO
  12595.  
  12596.             READ (*,*)  ! Wait for ENTER to be pressed
  12597.             dummy = setvideomode( $DEFAULTMODE )
  12598.             END
  12599.  
  12600.  By translating a drawing between window and viewport coordinates, the
  12601.  program MAGNIFY.FOR enlarges the window's contents.
  12602.  
  12603.  See also the example program for setvieworg.
  12604.  
  12605.  
  12606.  setvisualpage
  12607.  
  12608.  ■  Interface
  12609.  
  12610.       INTERFACE TO FUNCTION setvisualpage(page)
  12611.       INTEGER*2 setvisualpage[FAR, C, ALIAS:"__setvisualpage"]
  12612.       INTEGER*2 page         ! Visual page number
  12613.       END
  12614.  
  12615.  ■  Description
  12616.  
  12617.  The setvisualpage function selects the current visual page on hardware that
  12618.  has an EGA or VGA adapter and enough memory to support multiple-screen
  12619.  pages. The page argument specifies the current visual page. The default page
  12620.  number is 0.
  12621.  
  12622.  This function is also available under OS/2.
  12623.  
  12624.  ■  Return value
  12625.  
  12626.  Returns the page number of the previous visual page. If the function fails,
  12627.  it returns a negative value.
  12628.  
  12629.  ■  See also
  12630.  
  12631.       getactivepage, getvisualpage, setactivepage, setvideomode
  12632.  
  12633.  ■  Example
  12634.  
  12635.  See the example program for getactivepage.
  12636.  
  12637.  
  12638.  setwindow
  12639.  
  12640.  ■  Interface
  12641.  
  12642.       INTERFACE TO FUNCTION setwindow(finvert, wx1, wy1, wx2, wy2)
  12643.       INTEGER*2 setwindow[FAR, C, ALIAS:"__setwindow"]
  12644.       LOGICAL*2 finvert
  12645.       DOUBLE PRECISION wx1, wy1          ! Upper left corner of window
  12646.       DOUBLE PRECISION wx2, wy2          ! Lower right corner of window
  12647.       END
  12648.  
  12649.  ■  Description
  12650.  
  12651.  The setwindow function defines a window bound by the specified coordinates.
  12652.  The arguments (wx1, wy1) specify the upper left corner of the window, and
  12653.  the arguments (wx2, wy2) specify the lower right corner of the window.
  12654.  
  12655.  The finvert argument specifies the direction of the coordinates. If finvert
  12656.  is .TRUE., the y-axis increases from the screen bottom to the screen top
  12657.  (Cartesian coordinates). If finvert is .FALSE., the y-axis increases from
  12658.  the screen top to the screen bottom (screen coordinates).
  12659.  
  12660.  Any window transformation done with the setwindow function applies only to
  12661.  the viewport and not to the entire screen.
  12662.  
  12663.  If wx1 equals wx2 or wy1 equals wy2, the function will fail.
  12664.  
  12665.  ───────────────────────────────────────────────────────────────────────────
  12666.  NOTE
  12667.     This function does not affect the output of the font display routine
  12668.     outgtext.
  12669.  ───────────────────────────────────────────────────────────────────────────
  12670.  
  12671.  ■  Return value
  12672.  
  12673.  Returns a nonzero value if successful. If the function fails (for example,
  12674.  if it is not in a graphics mode), it returns 0.
  12675.  
  12676.  ■  See also
  12677.  
  12678.       setviewport
  12679.  
  12680.  ■  Example
  12681.  
  12682.  See the example program for setviweorg and setviewport.
  12683.  
  12684.  
  12685.  unregisterfonts
  12686.  
  12687.  ■  Interface
  12688.  
  12689.       INTERFACE TO SUBROUTINE
  12690.       + unregisterfonts[FAR, C, ALIAS:"__unregisterfonts"]( )
  12691.       END
  12692.  
  12693.  ■  Description
  12694.  
  12695.  The unregisterfonts subroutine frees memory previously allocated and used by
  12696.  the registerfonts function. The unregisterfonts subroutine removes the
  12697.  header information for all fonts and unloads the currently selected font
  12698.  data from memory.
  12699.  
  12700.  Any attempt to use the setfont or outgtext function after calling
  12701.  unregisterfonts causes an error.
  12702.  
  12703.  ■  Return value
  12704.  
  12705.  There is no return value.
  12706.  
  12707.  ■  See also
  12708.  
  12709.       getfontinfo, getgtextextent, setfont, outgtext, registerfonts
  12710.  
  12711.  ■  Example
  12712.  
  12713.  See the example program for registerfonts.
  12714.  
  12715.  
  12716.  wrapon
  12717.  
  12718.  ■  Interface
  12719.  
  12720.       INTERFACE TO FUNCTION wrapon(option)
  12721.       INTEGER*2 wrapon[FAR, C, ALIAS:"__wrapon"]
  12722.       INTEGER*2 option               ! Wrap condition
  12723.       END
  12724.  
  12725.  ■  Description
  12726.  
  12727.  The wrapon function controls whether text output with the outtext function
  12728.  wraps to a new line or is simply clipped when the text output reaches the
  12729.  edge of the defined text window. The option argument can be one of the
  12730.  following symbolic constants:
  12731.  
  12732.       Constant                    Meaning
  12733.  
  12734.       $GWRAPOFF                   Truncates lines at window border
  12735.  
  12736.       $GWRAPON                    Wraps lines at window border
  12737.  
  12738.  ───────────────────────────────────────────────────────────────────────────
  12739.  NOTE
  12740.     This function does not affect the output of font routines.
  12741.  ───────────────────────────────────────────────────────────────────────────
  12742.  
  12743.  This function is also available under OS/2.
  12744.  
  12745.  ■  Return value
  12746.  
  12747.  Returns the previous value of option. There is no error return.
  12748.  
  12749.  ■  See also
  12750.  
  12751.       settextwindow
  12752.  
  12753.  ■  Example
  12754.  
  12755.       CC  WRAP.FOR - Illustrates:
  12756.       CC             wrapon
  12757.  
  12758.             INCLUDE  'FGRAPH.FI'
  12759.             INCLUDE  'FGRAPH.FD'
  12760.  
  12761.             INTEGER*2              dummy2, old_color, old_mode, row, col
  12762.             INTEGER*4              dummy4, old_bk
  12763.             CHARACTER*22           text
  12764.             CHARACTER*80           border
  12765.             RECORD / rccoord /     curpos
  12766.             RECORD / videoconfig / vc
  12767.  
  12768.             DATA text / 'Here text DOES wrap.  ' /
  12769.  
  12770.             CALL getvideoconfig( vc )
  12771.             old_mode  = vc.mode
  12772.             old_color = gettextcolor()
  12773.             old_bk    = getbkcolor()
  12774.             IF( vc.numtextcols .NE. 80 ) THEN
  12775.                IF( setvideomode( $TEXTC80 ) .EQ. 0 )
  12776.            +       dummy2 = setvideomode( $TEXTMONO )
  12777.             END IF
  12778.             dummy2    = settextcolor( 14 )
  12779.             dummy4    = setbkcolor( 1 )
  12780.             CALL clearscreen( $GCLEARSCREEN )
  12781.       C
  12782.       C     Draw window borders.
  12783.       C
  12784.             DO i = 1, 80
  12785.                border(i:i) = CHAR( 219 )
  12786.             END DO
  12787.             CALL settextposition( 13, 1, curpos )
  12788.             CALL outtext( border )
  12789.             col = 60
  12790.             DO row = 1, 25
  12791.                IF( row .EQ. 13 ) col = 20
  12792.                CALL settextposition( row, col, curpos )
  12793.                CALL outtext( border(1:1) )
  12794.             END DO
  12795.       C
  12796.       C     Display wrapped and unwrapped text in windows.
  12797.       C
  12798.             dummy4 = setbkcolor( 0 )
  12799.             CALL settextwindow( 1, 1, 13, 59 )
  12800.             CALL settextposition( 1, 1, curpos )
  12801.             dummy2 = wrapon( $GWRAPON )
  12802.             dummy2 = settextcolor( 10 )
  12803.             DO i = 1, 32
  12804.                CALL outtext( text )
  12805.             END DO
  12806.             CALL outtext( text )
  12807.  
  12808.             CALL settextwindow( 14, 21, 25, 80 )
  12809.             CALL settextposition( 1, 1, curpos )
  12810.             dummy2 = wrapon( $GWRAPOFF )
  12811.             dummy2 = settextcolor( 12 )
  12812.             DO row = 1, 12
  12813.                CALL settextposition( row, 1, curpos )
  12814.                DO i = 1, 3
  12815.                   CALL outtext( text(1:15) // 'NOT ' // text(16:22) )
  12816.                END DO
  12817.             END DO
  12818.  
  12819.             READ (*,*)  ! Wait for ENTER to be pressed
  12820.             dummy2 = setvideomode( old_mode )
  12821.             dummy2 = settextcolor( old_color )
  12822.             dummy4 = setbkcolor( old_bk )
  12823.             END
  12824.  
  12825.  The program WRAP.FOR demonstrates the effect of wrapping and not wrapping
  12826.  text within a text window.
  12827.  
  12828.  
  12829.  Index
  12830.  ───────────────────────────────────────────────────────────────────────────
  12831.  
  12832.  /4I2 and /4I4 options (FL)
  12833.  /4Yb and /4Nb options (FL)
  12834.  /4Yb option (FL)
  12835.  I8087/287/387 coprocessor
  12836.     math package
  12837.     suppressing use of
  12838.  
  12839.  A
  12840.  ───────────────────────────────────────────────────────────────────────────
  12841.  Address sizes
  12842.     code
  12843.     data
  12844.  Address variables
  12845.  Addresses
  12846.     far
  12847.     code
  12848.        defined
  12849.        large and huge models
  12850.        subprogram calls
  12851.     huge
  12852.        defined
  12853.        huge arrays
  12854.        huge model
  12855.     near
  12856.     default data segment
  12857.     defined
  12858.     medium model
  12859.     subprograms
  12860.  ADR
  12861.     address variable
  12862.     keyword
  12863.  ADS, address variable
  12864.  Affine mode
  12865.  /AH option (FL)
  12866.  ALIAS keyword
  12867.     FORTRAN, use in
  12868.  Alternate math library
  12869.  /AM option (FL)
  12870.  API
  12871.     calls, low level
  12872.        DosCreateThread
  12873.        DosExit
  12874.  Apostrophes, use
  12875.  arc, arcwxy
  12876.  arc, arc_w
  12877.  Arguments
  12878.     passing
  12879.        by value
  12880.        medium model
  12881.  Array descriptors
  12882.  Arrays
  12883.     addressing
  12884.     adjustable size
  12885.     assumed size
  12886.     constant use, minimizing in declarations
  12887.     declaring for efficient compilation
  12888.     EQUIVALENCE statements, used in
  12889.     formal arguments, used as
  12890.     huge
  12891.        addressing
  12892.  Assembly interfaces; writing
  12893.  Assembly
  12894.     calling from
  12895.        FORTRAN
  12896.     interfaces
  12897.        address parameters, used with
  12898.        FORTRAN
  12899.     passing by
  12900.        far reference
  12901.        near reference
  12902.     procedures
  12903.  Attributes
  12904.  Attributes, FORTRAN
  12905.  Attributes
  12906.     FAR
  12907.        adjustable-size arrays
  12908.        arguments in medium model
  12909.        assumed-size arrays
  12910.        default data segment
  12911.        effects
  12912.        huge model
  12913.        library routines, used with
  12914.        medium model
  12915.        using
  12916.     HUGE
  12917.        alternative to huge model
  12918.        common blocks
  12919.        default data segment
  12920.        effects
  12921.        large model
  12922.        library routines, used with
  12923.        medium model
  12924.        using
  12925.     lack of portability
  12926.     NEAR
  12927.        adjustable-size arrays
  12928.        alternative to medium model
  12929.        assumed-size arrays
  12930.        common blocks
  12931.        declaring subprograms with
  12932.        effects
  12933.        huge model
  12934.        large and huge models
  12935.        library routines, used with
  12936.        subprograms
  12937.     VALUE
  12938.  Axes
  12939.     screen
  12940.  
  12941.  B
  12942.  ───────────────────────────────────────────────────────────────────────────
  12943.  BASIC
  12944.     arrays
  12945.     BYVAL keyword
  12946.     calling convention
  12947.     calling from
  12948.        FORTRAN
  12949.     CALLS statement
  12950.     common blocks
  12951.     compiling
  12952.     naming convention
  12953.     parameter-passing
  12954.        defaults
  12955.        methods
  12956.     passing by
  12957.        far reference
  12958.        near reference
  12959.        value
  12960.     procedures
  12961.     string format
  12962.     types, user-defined
  12963.     VARPTR keyword
  12964.     VARSEG keyword
  12965.  BEGINTHREAD run-time-library function
  12966.  _BEGINTHREAD run-time-library function
  12967.  BLOCKSIZE option
  12968.  Bold type, use
  12969.  BOOLEAN data type
  12970.  Bounding rectangle
  12971.  Brackets, double, use
  12972.  BYVAL keyword
  12973.  
  12974.  C
  12975.  ───────────────────────────────────────────────────────────────────────────
  12976.  C attribute
  12977.     FORTRAN, used in
  12978.     Pascal, used in
  12979.  C language
  12980.     calling convention
  12981.     calling from
  12982.        FORTRAN
  12983.     compiling
  12984.     FORTRAN, linking with
  12985.     functions
  12986.     memory models
  12987.     naming convention
  12988.     parameter-passing
  12989.        defaults
  12990.        methods
  12991.     passing by
  12992.        far reference
  12993.        near reference
  12994.        value
  12995.     pointers
  12996.     string format
  12997.     structures
  12998.  C-string feature, FORTRAN
  12999.  Calling conventions
  13000.  CALLS statement
  13001.  CDECL keyword
  13002.  ICGA (Color Graphics Adapter)
  13003.  Character types
  13004.     variables as format specifiers
  13005.  Classes
  13006.     defined
  13007.  clearscreen, library routine
  13008.  clearscreen
  13009.  Clipping region
  13010.  Clipping regions
  13011.  Code size
  13012.     limits
  13013.  Color Graphics Adapter see CGA
  13014.  Color indexes
  13015.  Color text modes see Video modes, text
  13016.  Color values
  13017.  Column-major order
  13018.  Common blocks
  13019.     formal arguments, used as
  13020.     large and huge models, used in
  13021.     medium model, used in
  13022.     memory allocation
  13023.     restrictions
  13024.  Compact memory model
  13025.  Compatibility
  13026.     8087/287/387 library
  13027.     emulator library
  13028.     floating-point options
  13029.  Compiler options
  13030.     /AT
  13031.     /Lp
  13032.     /Zl
  13033.  COMPLEX data type, FORTRAN
  13034.  CONST keyword
  13035.  CONSTS keyword
  13036.  Conventions, document
  13037.  Coordinates
  13038.     physical
  13039.     text
  13040.     view
  13041.     viewport
  13042.     window
  13043.  Coprocessor
  13044.     8087/287/387
  13045.     suppressing use of
  13046.  Courier, use of typeface
  13047.  CS register
  13048.  
  13049.  D
  13050.  ───────────────────────────────────────────────────────────────────────────
  13051.  Data address size
  13052.  Data segments
  13053.     data threshold
  13054.     default
  13055.        contents
  13056.        limits
  13057.        naming
  13058.        near addresses
  13059.        threshold, setting
  13060.     naming
  13061.  Data threshold, setting
  13062.  _DATA segment
  13063.  $DEBUG metacommand
  13064.  .DEF files
  13065.     introduced
  13066.  Default
  13067.     data segment
  13068.        contents
  13069.        data threshold
  13070.        defined
  13071.        limits
  13072.        object file
  13073.  Denormal
  13074.     numbers
  13075.     propagating
  13076.  Display attributes
  13077.  displaycursor
  13078.  DLL symbolic constant
  13079.  Document conventions
  13080.  DOSCALLS.LIB library
  13081.  DosCreateThread API call
  13082.  DosExit API call
  13083.  Double-precision reals
  13084.  Drawing see graphics
  13085.  DS register
  13086.     near addresses
  13087.     near, far, and huge addresses
  13088.  Dynamic linking
  13089.  Dynamic-link library
  13090.     creating
  13091.     defined
  13092.     multithread
  13093.        creating
  13094.        described
  13095.        using
  13096.     run time
  13097.        creating
  13098.        global data
  13099.        shared strings
  13100.        thread identification
  13101.     summary of components
  13102.  
  13103.  E
  13104.  ───────────────────────────────────────────────────────────────────────────
  13105.  Edit descriptors
  13106.     Tc
  13107.     TLc
  13108.  Edit lists
  13109.  EGA (Enhanced Graphics Adapter)
  13110.  ellipse, ellipsew, ellipsewxy
  13111.  ellipse, ellipse_w
  13112.  Ellipses, use
  13113.  EMOEM.ASM
  13114.  Emulator
  13115.     described
  13116.     function calls
  13117.     in-line instructions
  13118.     library
  13119.  ENDTHREAD run-time-library function
  13120.  Environment variables
  13121.     NO87
  13122.  EQUIVALENCE statement
  13123.  ERESCOLOR video mode
  13124.  Error messages
  13125.     removing text during SETUP
  13126.  ES register
  13127.  Exception handling
  13128.     control word
  13129.     dividing by zero
  13130.     invalid operation
  13131.     overflow and underflow
  13132.     precision
  13133.     status byte
  13134.  EXEMOD
  13135.     stack size, setting
  13136.  External data
  13137.  
  13138.  F
  13139.  ───────────────────────────────────────────────────────────────────────────
  13140.  Far addresses
  13141.     code
  13142.     data threshold
  13143.     defined
  13144.     large and huge models
  13145.     subprogram calls
  13146.  FAR attribute
  13147.     adjustable-size arrays
  13148.     assumed-size arrays
  13149.     default data segment
  13150.     effects
  13151.     huge model
  13152.     library routines, used with
  13153.     medium model, arguments in
  13154.     using
  13155.  Far reference parameters
  13156.     BASIC
  13157.     C
  13158.     FORTRAN
  13159.  FDLLOBJS.LIB library
  13160.  FGRAPH.FI
  13161.     constants in
  13162.  File-control blocks (FCBs)
  13163.  Files
  13164.     FORTRAN
  13165.        access modes
  13166.        binary direct
  13167.        binary sequential
  13168.        data formats
  13169.        formatted direct
  13170.        formatted sequential
  13171.        record structure
  13172.        unformatted direct
  13173.        unformatted sequential
  13174.  Fill flag
  13175.  Fill flags
  13176.  FL options
  13177.     /4I2 and /4I4
  13178.     /4Yb and 4Nb
  13179.     /AH
  13180.     /AL
  13181.     /AM
  13182.     /F
  13183.     /FPa
  13184.     /FPc87
  13185.        8087/80287 coprocessor
  13186.        described
  13187.        floating-point operations
  13188.     /FPc
  13189.        described
  13190.        flexibility
  13191.        floating-point operations
  13192.     /FPi
  13193.     /FPi87
  13194.     /Gt
  13195.        described
  13196.        FAR attribute, compared with
  13197.        medium memory model
  13198.        standard memory models
  13199.     /NM
  13200.     /NT
  13201.     /Zl
  13202.     data threshold
  13203.        /Gt option
  13204.        default value, setting
  13205.        moving data items
  13206.     debug
  13207.     default integer size
  13208.     memory model
  13209.        huge
  13210.        large
  13211.        medium
  13212.     naming
  13213.        modules
  13214.        text segments
  13215.     stack size, setting
  13216.     suppressing
  13217.        library selection
  13218.  $FLOATCALLS metacommand
  13219.  Floating point
  13220.     exceptions
  13221.        disabling
  13222.        listed
  13223.     options
  13224.        compatibility
  13225.        default
  13226.        default libraries
  13227.        function calls
  13228.        in-line instructions
  13229.        maximum efficiency with coprocessor
  13230.        maximum efficiency without coprocessor
  13231.        maximum flexibility
  13232.        maximum precision with coprocessor
  13233.  floodfill, floodfillw
  13234.  .FNT files
  13235.  .FON files
  13236.  Fonts
  13237.     .FNT files
  13238.     .FON files
  13239.     bit-mapped
  13240.     data structure
  13241.     displaying
  13242.     example program
  13243.     functions, listed
  13244.     memory allocation
  13245.     option list
  13246.     spacing
  13247.     table
  13248.     type sizes
  13249.     typefaces
  13250.     vector-mapped
  13251.  Foreground colors
  13252.  Formatted I/O
  13253.  FORTRAN
  13254.     C, linking with
  13255.  fortran keyword
  13256.  FORTRAN.LIB
  13257.  FORTRAN
  13258.     ALIAS keyword
  13259.     arrays
  13260.     C attribute
  13261.     calling convention
  13262.     calls to
  13263.        BASIC
  13264.        C
  13265.        other languages
  13266.        Pascal
  13267.     common blocks
  13268.     compiling
  13269.     COMPLEX data type
  13270.     functions and subroutines
  13271.     INTERFACE statement
  13272.     LOC function
  13273.     LOCFAR function
  13274.     LOCNEAR function
  13275.     LOGICAL data type
  13276.     naming convention
  13277.     parameter-passing
  13278.        defaults
  13279.        keywords
  13280.        methods
  13281.     PASCAL attribute
  13282.     passing by
  13283.        far reference
  13284.        near reference
  13285.        value
  13286.     string formats
  13287.  /FPa option (FL)
  13288.  /FPc option (FL)
  13289.     described
  13290.     floating-point operations
  13291.  /FPc87 option (FL)
  13292.  /FPi option (FL)
  13293.  /FPi87 option (FL)
  13294.  FUNCTION procedures
  13295.  functions
  13296.  Functions
  13297.     listed
  13298.  
  13299.  G
  13300.  ───────────────────────────────────────────────────────────────────────────
  13301.  getactivepage
  13302.  getbkcolor, library routine
  13303.  getbkcolor
  13304.  getcolor
  13305.  getcurrentposition, getcurrentpositionw
  13306.  getcurrentposition, getcurrentposition_w
  13307.  getfillmask
  13308.  getfontinfo
  13309.  getgtextextent
  13310.  getimage, getimage_w
  13311.  getlinestyle
  13312.  getphyscoord
  13313.  getpixel, getpixelw
  13314.  getpixel, getpixel_w
  13315.  gettextcolor, library routine
  13316.  gettextcolor
  13317.  gettextcursor
  13318.  gettextposition
  13319.  getvideoconfig
  13320.  getviewcoord, getviewcoordw, getviewcoordwxy
  13321.  getviewcoord, getviewcoord_w
  13322.  getvisualpage
  13323.  getwindowcoord
  13324.  GFILLINTERIOR, fill flag
  13325.  Ggraphics
  13326.     color selection
  13327.  Ggraphics
  13328.     palettes
  13329.  Global data, sharing
  13330.  GRAPH.H
  13331.     described
  13332.  Graphics
  13333.     attributes
  13334.     color selection
  13335.     configuration
  13336.     coordinates
  13337.     display characteristics
  13338.     see also drawing
  13339.     font functions. See Fonts
  13340.     font functions
  13341.        described
  13342.        use
  13343.     fonts
  13344.     image transfer
  13345.     output
  13346.        arc, arcwxy
  13347.        arc, arc_w
  13348.        ellipse, ellipsew, ellipsewxy
  13349.        ellipse, ellipse_w
  13350.        lineto, linetow
  13351.        pie, piewxy
  13352.        pie, pie_w
  13353.        rectangle, rectanglew, rectanglewxy
  13354.        rectangle, rectangle_w
  13355.     palettes
  13356.     parameters
  13357.     physical coordinates
  13358.     text output
  13359.     text support, listed
  13360.     text support
  13361.        settextrows
  13362.        settextwindow
  13363.        setvideomoderows
  13364.        setwindow
  13365.     view coordinates
  13366.     viewport coordinates
  13367.     window coordinates
  13368.  /Gt option (FL)
  13369.     described
  13370.     FAR attribute, compared with
  13371.     medium memory model
  13372.     standard memory models
  13373.  
  13374.  H
  13375.  ───────────────────────────────────────────────────────────────────────────
  13376.  Header files see GPROC.FI
  13377.  Hercules Graphics Card
  13378.  HRES16COLOR video mode
  13379.  HUGE attribute
  13380.     alternative to huge model
  13381.     common blocks
  13382.     default data segment
  13383.     effects
  13384.     large model
  13385.     library routines, used with
  13386.     medium model, arguments in
  13387.     using
  13388.  Huge memory model, use with C
  13389.  Huge
  13390.     addresses
  13391.        arrays
  13392.        defined
  13393.        huge model
  13394.     memory model. See also Memory models
  13395.        /AH option (FL)
  13396.        adjustable-size arrays
  13397.        assumed-size arrays
  13398.        described
  13399.  
  13400.  I
  13401.  ───────────────────────────────────────────────────────────────────────────
  13402.  I/O
  13403.     buffers
  13404.     formatted
  13405.     list-directed
  13406.  imagesize, imagesize_w
  13407.  IMPLIB (Microsoft Import Library Manager)
  13408.  Imports library
  13409.  In-line instructions
  13410.  Include files
  13411.     FGRAPH.FI
  13412.  Include files see GRAPH.H
  13413.  Infinities
  13414.  Infinity arithmetic modes
  13415.  INTERFACE statement
  13416.  INTERFACE statement, FORTRAN
  13417.  Italics, use
  13418.  
  13419.  L
  13420.  ───────────────────────────────────────────────────────────────────────────
  13421.  Large memory model
  13422.  Large memory model
  13423.     /AL option (FL)
  13424.     adjustable-size, assumed-size arrays
  13425.     described
  13426.     see Memory models
  13427.  $LARGE metacommand
  13428.  LCWRQQ routine
  13429.     masking denormals
  13430.  LES instruction
  13431.  LIB (Microsoft Library Manager)
  13432.  LIBPATH variable
  13433.  Libraries
  13434.     8087/287/387
  13435.     8087/80287
  13436.     alternate math
  13437.     controlling use
  13438.     DOSCALLS.LIB
  13439.     emulator
  13440.     FORTRAN.LIB
  13441.     huge model
  13442.     imports
  13443.     large model
  13444.     LLIBFMT.LIB
  13445.     LLIBFOR7.LIB
  13446.     LLIBFORA.LIB
  13447.     LLIBFORE.LIB
  13448.     medium model
  13449.     memory models
  13450.     MLIBFOR7.LIB
  13451.     MLIBFORA.LIB
  13452.     MLIBFORE.LIB
  13453.     multithread programs
  13454.     standard memory models, support for
  13455.  Library functions see Routines
  13456.  Line styles
  13457.     see also Presentation Graphics, palettes
  13458.  linetow
  13459.  lineto
  13460.  lineto_w
  13461.  LINK options
  13462.     /NODEFAULTLIBRARYSEARCH (/NOD)
  13463.        standard libraries
  13464.     /STACK (/ST)
  13465.     stack size, setting
  13466.  Linker options
  13467.     /NODEFAULTLIBRARYSEARCH (/NOD)
  13468.  List-directed I/O
  13469.  Listing files
  13470.     map
  13471.  LLIBFMT.LIB library
  13472.  LLIBFOR7.LIB
  13473.  LLIBFORA.LIB
  13474.  LLIBFORE.LIB
  13475.  LOC, FORTRAN function
  13476.  LOCFAR, FORTRAN function
  13477.  LOCNEAR, FORTRAN function
  13478.  LOGICAL data type, FORTRAN
  13479.  Low-level graphics
  13480.     output
  13481.        lineto, lineto_w
  13482.  Lower bounds, arrays
  13483.  /Lp compiler option
  13484.     multithread programs
  13485.  LSTRING
  13486.  
  13487.  M
  13488.  ───────────────────────────────────────────────────────────────────────────
  13489.  Macro Assembler
  13490.     assembly interfaces, writing
  13491.     simplified segment directives
  13492.  Map file, code size
  13493.  Medium memory model
  13494.     /AM option (FL)
  13495.     adjustable-size, assumed-size arrays
  13496.     argument passing
  13497.     common blocks
  13498.     described
  13499.     NEAR and FAR attributes
  13500.  Memory models
  13501.     adjustable-size arrays
  13502.     argument passing
  13503.     assumed-size arrays
  13504.     see also Attributes, FAR
  13505.     see also Attributes, HUGE
  13506.     see also Attributes, NEAR
  13507.     common blocks
  13508.     customizing
  13509.     default
  13510.     defined
  13511.     huge
  13512.        /AH option (FL)
  13513.        adjustable-size arrays
  13514.        arrays
  13515.        assumed-size arrays
  13516.        described
  13517.     large
  13518.        /AL option (FL)
  13519.        adjustable-size, assumed-size arrays
  13520.        described
  13521.     library support
  13522.     medium
  13523.        /AM option (FL)
  13524.        adjustable-size, assumed-size arrays
  13525.        argument passing
  13526.        common blocks
  13527.        default data segment
  13528.        described
  13529.     restrictions
  13530.     selecting
  13531.     specifying
  13532.     standard
  13533.  Metacommands
  13534.     $DEBUG
  13535.     $FLOATCALLS
  13536.     $LARGE
  13537.     $NOFLOATCALLS
  13538.     $NOTLARGE
  13539.     $STORAGE
  13540.  Microsoft Import Library Manager, see IMPLIB
  13541.  Microsoft Library Manager, see LIB
  13542.  Microsoft Windows
  13543.  Mixed-language programs
  13544.     compiling
  13545.     linking
  13546.  MLIBFOR7.LIB
  13547.  MLIBFORA.LIB
  13548.  MLIBFORE.LIB
  13549.  Modules, naming
  13550.  Monotype, use of
  13551.  movetow
  13552.  moveto
  13553.  moveto_w
  13554.  MRES16COLOR video mode
  13555.  MRES256COLOR video mode
  13556.  MRES4COLOR video mode
  13557.  MRESNOCOLOR video mode
  13558.  MT symbolic constant
  13559.  /MT compiler option
  13560.  Multitasking
  13561.  Multithread programs
  13562.     compiling and linking
  13563.     see Dynamic-link libraries
  13564.     function calls
  13565.     library support
  13566.     memory allocation
  13567.     possible problems
  13568.     run-time thread management
  13569.        BEGINTHREAD
  13570.        ENDTHREAD
  13571.        THREADID
  13572.        _BEGINTHREAD
  13573.     stack checking
  13574.  
  13575.  N
  13576.  ───────────────────────────────────────────────────────────────────────────
  13577.  Naming conventions
  13578.  Naming
  13579.     modules
  13580.     segments
  13581.  NANs
  13582.  Near addresses
  13583.     default data segment
  13584.     defined
  13585.     medium model
  13586.     subprograms
  13587.  NEAR attribute, FORTRAN
  13588.  NEAR attribute
  13589.     adjustable-size arrays
  13590.     alternative to medium model
  13591.     assumed-size arrays
  13592.     common blocks
  13593.     declaring subprograms with
  13594.     effects
  13595.     huge model
  13596.     large and huge models
  13597.     large and huge models
  13598.     library routines, used with
  13599.     subprograms
  13600.  Near reference parameters
  13601.     assembly
  13602.     BASIC
  13603.     C
  13604.     FORTRAN
  13605.     Pascal
  13606.  NO87 variable
  13607.  /NODEFAULTLIBRARYSEARCH (/NOD) linker option
  13608.  /NODEFAULTLIBRARYSEARCH option (LINK)
  13609.     standard libraries
  13610.  $NOFLOATCALLS metacommand
  13611.  /NOI linker option
  13612.  /NM option (FL)
  13613.  $NOTLARGE metacommand
  13614.  /NT option (FL)
  13615.  
  13616.  O
  13617.  ───────────────────────────────────────────────────────────────────────────
  13618.  origin
  13619.  OS/2 support files
  13620.     DOSCALLS.LIB
  13621.     LLIBFMT.LIB
  13622.     FDLLOBJS.LIB
  13623.  outgtext
  13624.  outtext
  13625.  Overlays
  13626.     reducing program size
  13627.  
  13628.  P
  13629.  ───────────────────────────────────────────────────────────────────────────
  13630.  Packed storage
  13631.  Palettes
  13632.  Palettes
  13633.     display
  13634.     remapping
  13635.  Parameter-passing methods
  13636.  Parameters
  13637.     calling conventions, effect of
  13638.     passing, see also Passing by
  13639.     varying number of
  13640.  PASCAL attribute
  13641.  pascal keyword
  13642.  Pascal
  13643.     address variables
  13644.     C attribute
  13645.     calling convention
  13646.     calling from
  13647.        FORTRAN
  13648.     compiling
  13649.     functions and procedures
  13650.     LSTRING
  13651.     naming convention
  13652.     parameter-passing
  13653.        defaults
  13654.        methods
  13655.     passing by
  13656.        near reference
  13657.     records
  13658.     string formats
  13659.  Passing arguments
  13660.     by value
  13661.     medium model
  13662.  Passing by
  13663.     far reference
  13664.        assembly
  13665.        BASIC
  13666.        C
  13667.        FORTRAN
  13668.     near reference
  13669.        assembly
  13670.        BASIC
  13671.        C
  13672.        FORTRAN
  13673.        FORTRAN
  13674.        Pascal
  13675.     value
  13676.        BASIC
  13677.        C
  13678.        FORTRAN
  13679.  pie, piewxy
  13680.  pie, pie_w
  13681.  Pixel values see Color indexes
  13682.  Pixels, defined
  13683.  Pointers
  13684.  Procedures
  13685.  Process, illustrated
  13686.  Programs, sample
  13687.     COLTEXT.C
  13688.     SAMPLER.C
  13689.     SAMPLER.FOR
  13690.     SINE
  13691.  Public data
  13692.  putimage, putimage_w
  13693.  
  13694.  R
  13695.  ───────────────────────────────────────────────────────────────────────────
  13696.  Receiving parameters and calling conventions
  13697.  Record structure
  13698.     binary direct files
  13699.     binary sequential files
  13700.     formatted direct files
  13701.     formatted sequential files
  13702.     unformatted direct files
  13703.     unformatted sequential files
  13704.  Records
  13705.  rectangle, rectanglew, rectanglewxy
  13706.  rectangle, rectangle_w
  13707.  REFERENCE attribute
  13708.  registerfonts
  13709.  Registers
  13710.     CS
  13711.     DS
  13712.        near addresses
  13713.        near, far, and huge addresses
  13714.     ES
  13715.     SS
  13716.  remapallpalette
  13717.     described
  13718.     use
  13719.  remappalette
  13720.     described
  13721.     use
  13722.  Remapping, see Palettes, remapping
  13723.  Resource, ownership of
  13724.  Round control
  13725.  Routines, categories
  13726.  Routiness
  13727.  Row-major order
  13728.  
  13729.  S
  13730.  ───────────────────────────────────────────────────────────────────────────
  13731.  Sample programs
  13732.     FMHELLO.FOR
  13733.     SNAP.FOR
  13734.  Screen groups, illustrated
  13735.  Segment directives, simplified
  13736.  Segments
  13737.     code
  13738.     data
  13739.        default
  13740.        naming
  13741.     naming
  13742.     text
  13743.        default
  13744.        naming
  13745.  selectpalette
  13746.     described
  13747.     use
  13748.  setactivepage
  13749.  setbkcolor
  13750.  setcliprgn
  13751.  setcolor
  13752.  setfillmask
  13753.     described
  13754.     dselection
  13755.     use
  13756.  setfont
  13757.  setlinestyle
  13758.  setpixelw
  13759.  setpixel
  13760.     described
  13761.     use
  13762.  setpixel_w
  13763.  settextcolor
  13764.  settextcursor
  13765.  settextposition
  13766.  settextrows
  13767.  settextwindow
  13768.  SETUP
  13769.     removing error-message text
  13770.  setvideomoderows
  13771.  setvideomode
  13772.     described
  13773.     use
  13774.  setvieworg
  13775.  setviewport
  13776.  setvisualpage
  13777.  setwindow
  13778.  sine
  13779.  Single-precision reals
  13780.  Small memory model
  13781.     C, use with
  13782.  Special data types
  13783.  SS register
  13784.  Stack
  13785.     allocating separately from DS
  13786.     changing size
  13787.     default data segment, used in
  13788.     large
  13789.  Stack checking
  13790.  /STACK option
  13791.     (LINK)
  13792.        default data segment
  13793.  Static data
  13794.  Static linking
  13795.  $STORAGE metacommand
  13796.  Strings
  13797.     passing from
  13798.        C
  13799.        FORTRAN
  13800.        Pascal
  13801.  Structured data types
  13802.  Structures
  13803.  Subprograms
  13804.  Subroutines
  13805.  Symbolic constants, described
  13806.  Syntax conventions
  13807.     Document conventions
  13808.  
  13809.  T
  13810.  ───────────────────────────────────────────────────────────────────────────
  13811.  Tc edit descriptor
  13812.  Text segment
  13813.     default name
  13814.     naming
  13815.  _TEXT
  13816.  TEXTC40 video mode
  13817.  TEXTC80 video mode
  13818.  THREADID run-time-library function
  13819.  THREADID variable
  13820.  Threads
  13821.     defined
  13822.     ending
  13823.     identifying
  13824.     illustrated
  13825.     synchronizing
  13826.  TLc edit descriptor
  13827.  Typefaces
  13828.  
  13829.  U
  13830.  ───────────────────────────────────────────────────────────────────────────
  13831.  Unpacked storage
  13832.  unregisterfonts
  13833.  Unsigned integers
  13834.  Uppercase, use of
  13835.  User-defined types
  13836.  
  13837.  V
  13838.  ───────────────────────────────────────────────────────────────────────────
  13839.  VALUE attribute
  13840.  VALUE keyword
  13841.  Value parameters
  13842.     BASIC
  13843.     C
  13844.     FORTRAN
  13845.     passing
  13846.  VAR keyword
  13847.  Variables
  13848.     address
  13849.     LIBPATH
  13850.     _THREADID
  13851.  VARPTR keyword
  13852.  VARS keyword
  13853.  VARSEG keyword
  13854.  VARYING attribute
  13855.  VGA (Video Graphics Array)
  13856.  Video adapters
  13857.     CGA
  13858.     EGA
  13859.     Hercules
  13860.     VGA
  13861.  Video memory
  13862.  Video modes
  13863.     graphics
  13864.        CGA
  13865.        described
  13866.        EGA
  13867.        setting
  13868.        setting color
  13869.        VGA
  13870.     table
  13871.     (table)
  13872.     text
  13873.  Video modesgraphics
  13874.     setting
  13875.  videoconfig structure
  13876.  VRES16COLOR video mode
  13877.  VRES2COLOR video mode
  13878.  
  13879.  W
  13880.  ───────────────────────────────────────────────────────────────────────────
  13881.  Windows, graphics
  13882.  wrapon
  13883.  
  13884.  Z
  13885.  ───────────────────────────────────────────────────────────────────────────
  13886.  /Zl compiler option
  13887.  /Zl option (FL)
  13888.  
  13889.