home *** CD-ROM | disk | FTP | other *** search
Text File | 2013-11-08 | 542.7 KB | 13,889 lines |
- Microsoft(R) FORTRAN ADVANCED TOPICS
- VERSION 5.0
-
- FOR MS(R) OS/2 AND MS-DOS(R) OPERATING SYSTEMS
-
- MICROSOFT CORPORATION
-
- Information in this document is subject to change without notice and does
- not represent a commitment on the part of Microsoft Corporation. The
- software described in this document is furnished under a license agreement
- or nondisclosure agreement. The software may be used or copied only in
- accordance with the terms of the agreement. It is against the law to copy
- the software on any medium except as specifically allowed in the license or
- nondisclosure agreement. No part of this manual may be reproduced or
- transmitted in any form or by any means, electronic or mechanical, including
- photocopying and recording, for any purpose without the express written
- permission of Microsoft.
-
- (c)Copyright Microsoft Corporation, 1989. All rights reserved.
-
- Printed and bound in the United States of America.
-
- Microsoft, MS, MS-DOS, CodeView, and QuickC are registered trademarks of
- Microsoft Corporation.
-
- AT&T is a registered trademark of American Telephone and Telegraph Company.
-
- Hercules is a registered trademark and InColor is a trademark of Hercules
- Computer Technology.
-
- IBM is a registered trademark of International Business Machines
- Corporation.
-
- Intel is a registered trademark of Intel Corporation.
-
- Olivetti is a registered trademark of Ing. C. Olivetti.
-
- Texas Instruments is a registered trademark of Texas Instruments, Inc.
-
- VAX is a registered trademark of Digital Equipment Corporation.
-
- WANG is a registered trademark of Wang Laboratories.
-
- Document No. LN0828-500-R00-0289
- Part No. 06384
- 10 9 8 7 6 5 4 3 2 1
-
-
- Table of Contents
- ───────────────────────────────────────────────────────────────────────────
-
- Introduction
- About This Manual
- Document Conventions
-
- Part 1 Working with Microsoft FORTRAN
-
- Chapter 1 Controlling Floating- Point Operations
- 1.1 Choosing a Math Package
- 1.1.1 The 8087/287/387 Package
- 1.1.2 The Emulator Package
- 1.1.3 The Alternate Math Package
- 1.2 Using the Floating-Point Options (/FP)
- 1.2.1 The /FPi87 Option
- 1.2.2 The /FPc87 Option
- 1.2.3 The /FPi Option
- 1.2.4 The /FPc Option
- 1.2.5 The /FPa Option
- 1.3 Library Considerations in Selecting /FP Options
- 1.3.1 Choosing In-Line Instructions or Calls
- 1.3.2 Using a Standard Library for Linking
- 1.3.3 Ensuring Compatibility between Options
- 1.3.4 Special Procedure for MS-DOS 3.2 Users
- 1.3.5 Using $FLOATCALLS and $NOFLOATCALLS
- 1.4 Using the NO87 Environment Variable
- 1.5 Handling 8087/287/387 Floating-Point Exceptions
- 1.5.1 Controlling the Processing Environment
- 1.5.2 Reading and Setting Status and Control Values
- 1.5.3 Floating-Point Exceptions under PC-DOS 3.2
- 1.6 Using Non-IBM(R)-Compatible Computers
-
- Chapter 2 Selecting a Memory Model
- 2.1 What Is a Memory Model?
- 2.2 Understanding Memory Models
- 2.2.1 Code and Data Segments
- 2.2.2 Near, Far, and Huge Addresses
- 2.2.3 The Default Data Segment
- 2.3 Working with FORTRAN Memory Models
- 2.3.1 Specifying a Memory Model
- 2.3.2 Data-Handling Strategies and Limits
- 2.3.3 Limits on Code Size
- 2.4 Selecting and Adjusting the Memory Model
- 2.4.1 Using Standard Memory Models
- 2.4.2 The NEAR, FAR, and HUGE Attributes
- 2.4.3 The $LARGE and $NOTLARGE Metacommands
- 2.4.4 Using Library Routines with Different Memory Models
- 2.4.5 Compiler Options Affecting Memory Usage
-
- Chapter 3 FORTRAN Programming under OS/2
- 3.1 Compiling and Linking under OS/2
- 3.2 Running under Both DOS and OS/2
- 3.3 Interfacing FORTRAN with OS/2
- 3.4 Understanding Multitasking, Threads, and Dynamic-Link Libraries
- 3.4.1 Multitasking and Threads
- 3.4.2 Dynamic-Link Libraries
- 3.5 Multithread Programs
- 3.5.1 Library Support for Multithread Programs
- 3.5.2 Thread Control Routines
- 3.6 A Multithread FORTRAN Program
- 3.6.1 Sample Program Operation
- 3.6.2 Compiling and Linking the Sample Multithread Program
- 3.6.3 Troubleshooting Multithread Programs
- 3.7 Using FORTRAN Dynamic-Link Libraries
- 3.7.1 Creating a Dynamic-Link Library
- 3.7.2 The LOADDS Attribute
- 3.7.3 Multithread Dynamic-Link Libraries: An Overview
- 3.7.4 Creating a Multithread Dynamic-Link Library
- 3.7.5 Creating a Custom FORTRAN Run-Time Definitions File
- 3.7.6 Using a Multithread Dynamic-Link Library
- 3.7.7 Compiling for Dynamic-Link and Multithread Capabilities
- 3.7.8 FORTRAN OS/2 Libraries
- 3.8 Limits on Multithread and Dynamic-Link Programs
- 3.8.1 Large and Huge Memory Models (/MT, /MD)
- 3.8.2 Math Support (/FPi87)
- 3.8.3 Limited CHARACTER*(*) Support
- 3.8.4 The C Attribute and REAL Numbers
- 3.8.5 Open Files
- 3.9 Recommendations
- 3.10 Additional Information
-
- Chapter 4 Mixed-Language Programming
- 4.1 Making Mixed-Language Calls
- 4.1.1 Naming Convention Requirement
- 4.1.2 Calling Convention Requirement
- 4.1.3 Methods for Passing Parameters
- 4.1.4 Compiling and Linking Considerations
- 4.2 Calling Other High-Level Languages
- 4.2.1 The INTERFACE Statement
- 4.2.2 An Alternative Interface to C
- 4.2.3 The ALIAS Attribute
- 4.2.4 FORTRAN Calls to C and Pascal
- 4.2.5 C Functions Available with FORTRAN Run-Time Libraries
- 4.2.6 FORTRAN Calls to BASIC
- 4.3 Using Assembly-Language Routines
- 4.4 Calling FORTRAN from Other Languages
-
- Chapter 5 Transferring Data between Languages
- 5.1 Passing by Reference or Value
- 5.1.1 BASIC Arguments
- 5.1.2 C Arguments
- 5.1.3 FORTRAN Arguments
- 5.1.4 Pascal Arguments
- 5.2 Passing Numeric, Logical, and String Data
- 5.2.1 Integer and Real Numbers
- 5.2.2 FORTRAN COMPLEX Types
- 5.2.3 FORTRAN LOGICAL Type
- 5.2.4 Strings
- 5.3 Handling Special Data Types
- 5.3.1 Arrays
- 5.3.2 Structures, Records, and User-Defined Types
- 5.3.3 External Data
- 5.3.4 Pointers and Address Variables
- 5.3.5 Common Blocks
- 5.3.6 Using a Varying Number of Parameters
-
- Chapter 6 Record Structures: File Formats and Access
- 6.1 Understanding Structures: Forms and Access Modes
- 6.2 Using Formatted Records
- 6.2.1 Formatted Sequential Records
- 6.2.2 Formatted Direct Records
- 6.3 Using Unformatted Records
- 6.3.1 Unformatted Sequential Records
- 6.3.2 Unformatted Direct Records
- 6.4 Using Binary Records
- 6.4.1 Binary Sequential Records
- 6.4.2 Binary Direct Records
-
- Chapter 7 Optimizing Programs
- 7.1 Compiling and Linking Strategies
- 7.1.1 Using Debugging and Integer-Size Options
- 7.1.2 Using 8087/287/387 Math Options
- 7.1.3 Using Overlays
- 7.2 Coding Strategies
- 7.2.1 Removing Error-Message Text during SETUP
- 7.2.2 Using Consistent File-Access and Format Types
- 7.2.3 Specifying Edit Lists
- 7.2.4 Using the BLOCKSIZE Option
- 7.2.5 Using Integer and Real Variables
- 7.2.6 Using Arrays and EQUIVALENCE Statements
-
- Part 2 The Microsoft FORTRAN Graphics Library
-
- Chapter 8 Graphics Library Routines
- 8.1 Using Graphics and Character-Font Functions
- 8.2 Defining Graphics Characteristics
- 8.2.1 Selecting Display Options
- 8.2.2 Setting Graphics Coordinates
- 8.2.3 Setting Palettes
- 8.2.4 Setting Figure Attributes
- 8.3 Displaying Graphics Output
- 8.3.1 Creating a Graphics Display
- 8.3.2 Displaying Text
- 8.3.3 Transferring Images
- 8.3.4 Displaying Font-Based Characters
- 8.4 Routines Available under OS/2
-
- Chapter 9 Drawing Graphic Elements
- 9.1 Working with Graphics Modes
- 9.1.1 Checking the Current Video Mode
- 9.1.2 Setting the Video Mode
- 9.1.3 Writing a Graphics Program (SINE)
- 9.2 Adding Color
- 9.2.1 Color Graphics Modes
- 9.2.2 Using the Color Video Text Modes
- 9.3 Understanding Coordinate Systems
- 9.3.1 Text Coordinates
- 9.3.2 Graphics Coordinates
- 9.3.3 Real Coordinates Program (REALG)
- 9.3.4 Drawing the Graphs
-
- Chapter 10 Using Fonts from the Graphics Library
- 10.1 Available Typefaces
- 10.2 Using Microsoft FORTRAN Fonts
- 10.2.1 Registering Fonts
- 10.2.2 Setting the Font and Displaying Text
- 10.3 Example Program (SAMPLER)
- 10.4 Using Fonts Effectively
-
- Chapter 11 Graphics Library Reference
- arc, arc_w
- clearscreen
- displaycursor
- ellipse, ellipse_w
- floodfill, floodfill_w
- getactivepage
- getbkcolor
- getcolor
- getcurrentposition, getcurrentposition_w
- getfillmask
- getfontinfo
- getgtextextent
- getimage, getimage_w
- getlinestyle
- getphyscoord
- getpixel, getpixel_w
- gettextcolor
- gettextcursor
- gettextposition
- getviewcoord, getviewcoord_w
- getvideoconfig
- getvisualpage
- getwindowcoord
- imagesize, imagesize_w
- lineto, lineto_w
- moveto, moveto_w
- outgtext
- outtext
- pie, pie_w
- putimage, putimage_w
- rectangle, rectangle_w
- registerfonts
- remapallpalette, remappalette
- selectpalette
- setactivepage
- setbkcolor
- setcliprgn
- setcolor
- setfillmask
- setfont
- setlinestyle
- setpixel, setpixel_w
- settextcolor
- settextcursor
- settextposition
- settextrows
- settextwindow
- setvideomode
- setvideomoderows
- setvieworg
- setviewport
- setvisualpage
- setwindow
- unregisterfonts
- wrapon
-
- Index
-
- Listing of Tables
-
- Table 1.1 Summary of Floating-Point Options
- Table 1.2 Floating-Point Exceptions
- Table 1.3 Mask Settings for Operation Exceptions
- Table 2.1 Data Allocation in Large Memory Models
- Table 2.2 Effects of the NEAR Attribute
- Table 2.3 Effects of the FAR and HUGE Attributes
- Table 3.1 FORTRAN OS/2 Libraries
- Table 4.1 Language Equivalents for Routine Calls
- Table 4.2 Parameter-Passing Defaults
- Table 5.1 Equivalent Numeric Data Types
- Table 5.2 Equivalent Array Declarations
- Table 9.1 Video Modes for Text and Graphics
- Table 9.1 Fill Patterns
- Table 9.2 Available CGA Colors
- Table 9.3 CGA Colors: $MRESNOCOLOR Mode
- Table 10.1 Typefaces and Type Sizes in the FORTRAN Graphics Library
- Table R.2 $MRES4COLOR Mode Palette Colors
- Table R.3 $MRESNOCOLOR Mode CGA Palette Colors
- Table R.4 $MRESNOCOLOR Mode EGA Palette Colors
- Table R.5 Symbolic Constants for Screen Mode
- Table R.6 Modes Selected by $MAXCOLORMODE and $MAXRESMODE
-
-
- Introduction
- ───────────────────────────────────────────────────────────────────────────
-
- Microsoft(R) FORTRAN Version 5.0 includes many enhancements since its last
- release. The language is now fully compatible with the Systems Application
- Architecture (SAA) FORTRAN extensions and many of the VAX(R) extensions. It
- supports new constructs such as compound data types, SELECT CASE
- decision-making blocks, and other features that extend its utility. This new
- version of Microsoft FORTRAN offers enhanced OS/2 systems support, including
- the use of dynamically linked libraries and multiple threads of execution.
-
- For complete flexibility, programs written with this new version can be
- designed to run under DOS, OS/2, or both operating systems. In addition, an
- extensive graphics library lets data and figures become an integral part of
- any FORTRAN application.
-
- This chapter introduces Microsoft FORTRAN Advanced Topics and describes the
- document conventions used in this manual. If you want to write and run
- FORTRAN programs immediately, the Getting Started with Microsoft FORTRAN and
- the Microsoft FORTRAN Reference man-uals will provide sufficient resources
- to get you up and running quickly.
-
-
- About This Manual
-
- Microsoft FORTRAN Advanced Topics contains two parts. Part 1, "Working with
- Microsoft FORTRAN," discusses how to get the most out of Microsoft FORTRAN
- 5.0, and includes such topics as selecting the appropriate memory models,
- using OS/2-specific features, or creating programs with parts written in
- different programming languages.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- Microsoft documentation uses the term "OS/2" to refer to the OS/2
- Systems──Microsoft Operating System/2 (MS(R) OS/2) and IBM(R) OS/2.
- Similarly, the term "DOS" refers to both the MS-DOS(R) and IBM Personal
- Computer DOS operating systems. The name of a specific operating system
- is used when it is necessary to note features that are unique to that
- system.
- ───────────────────────────────────────────────────────────────────────────
-
- The first two chapters discuss memory models and alternatives for handling
- floating-point math. Chapter 3, "FORTRAN Programming under OS/2," covers the
- special features available under OS/2, such as multitasking, dynamic-link
- libraries, virtual memory access, and protected and real modes. Chapter 4,
- "Mixed-Language Programming," describes how to access routines programmed in
- another Microsoft language. And, if you need to exchange data between
- languages, read Chapter 5.
-
- Chapter 6, "Record Structures: File Formats and Access," reviews the
- different file format and access combinations available to Microsoft
- FORTRAN. The last chapter of the Part 1, "Optimizing Programs," covers
- strategies for optimizing both the size and speed of an application, at both
- the compiling/linking and coding levels.
-
- Part 2, "The Microsoft FORTRAN Graphics Library," presents topics and
- considerations in writing graphics applications.
-
- Chapter 8 introduces the routines provided in the graphics library and their
- categories. Chapter 9, "Drawing Graphic Elements," describes graphics
- programming in detail, and steps through several example programs. Chapter
- 10, "Using Fonts from the Graphics Library," covers the different fonts
- available and how to use the font manipulating routines. The final chapter,
- "Graphics Library Reference," describes the use of each routine in detail.
-
- The graphics functions in the Microsoft FORTRAN Graphics Library are
- designed to work in the MS-DOS or IBM Personal Computer DOS (PC-DOS)
- environment; the text-based routines are also available under OS/2.
-
- The chapters in this manual can be read either individually or
- consecutively, although the graphics chapters in Part 2 follow a more
- sequential structure. The majority of the chapters in the Part 1 stand by
- themselves and can be read independently.
-
- Microsoft FORTRAN conforms to the American National Standard Programming
- Language FORTRAN 77, as described in the American National Standards
- Institute (ANSI) X3.9-1978 standard.
-
- Microsoft FORTRAN Advanced Topics assumes you have a working knowledge of
- both the computer and ANSI standard FORTRAN, and that you recognize the
- Microsoft extensions to FORTRAN.
-
-
- Document Conventions
-
- This book uses the following typographic conventions:
-
- Examples Description
-
- LLIBFOR7.LIB, LINK, FL, Uppercase (capital) letters
- FGRAPH.FI, /4Yb indicate file names and DOS-level
- commands. Uppercase is also used
- for command-line options (unless
- the application accepts only
- lowercase).
-
- C Comment line This kind of type is used for
- WRITE (*, *) 'Hello program examples, program output,
- + World' and error messages within the
- text.
-
- A capital C marks the beginning
- of a comment in sample programs.
- Continuation lines are indicated
- by a plus (+ ) in column 6.
-
- $TRUNCATE, INTRINSIC,WRITE, Bold capital letters indicate
- DosSleep language-specific keywords with
- special meaning to FORTRAN (or,
- in the case of DosSleep, with
- special meaning to the OS/2
- environment). Keywords are a
- required part of statement
- syntax, unless enclosed in double
- brackets, as explained below.
-
- near, adr Bold lowercase letters are used
- for keywords of languages that
- use lowercase letters by
- convention. For example, in the
- sentence, "The BASIC INTEGER and
- C short types are equivalent,"
- the word INTEGER is a Microsoft
- BASIC keyword and short is a
- keyword from Microsoft C.
-
- Apostrophes: '' ' ' In Microsoft FORTRAN, an
- apostrophe is entered as a single
- right quotation mark ('), not a
- single left quotation mark (`).
- Note that in the typeface used in
- program examples, such as
- 'string', apostrophes look like
- this: '.
-
- expression Words in italics indicate
- placeholders for information that
- you must supply. A file name is
- an example of this kind of
- information.
-
- «option» Items inside bold chevrons
- are optional.
-
- {choice1 | choice2} Braces and a vertical bar
- indicate a choice among two or
- more items. You must choose one
- of the items unless all of the
- items are also enclosed in double
- square brackets.
-
- Repeating elements... Three dots following an item
- indicate that more items having
- the same form may be entered.
-
- CALL GetNum (i, *10) A column of three dots indicates
- . that part of the example program
- . has intentionally been omitted.
- .
- SUBROUTINE GetNum (i, *)
-
- KEY NAMES Small capital letters are used
- for the names of keys and key
- sequences, such as ENTER and
- CTRL+C.
-
- A plus (+) indicates a
- combination of keys. For example,
- CTRL+E means to hold down the
- CTRL key while pressing the E
- key.
-
- The carriage-return key,
- sometimes marked with a bent
- arrow, is referred to as ENTER.
-
- The cursor movement ("arrow")
- keys on the numeric keypad are
- called DIRECTION keys. Individual
- DIRECTION keys are referred to by
- the direction of the arrow on the
- top of the key (LEFT, RIGHT, UP,
- DOWN) or the name on the top of
- the key (PGUP, PGDN).
-
- The key names used in this manual
- correspond to the names on the
- IBM Personal Computer keyboard.
- Other machines may use different
- names.
-
- "defined term" Quotation marks usually indicate
- a new term defined in the text.
-
- Video Graphics Array (VGA) Acronyms are usually spelled out
- the first time they are used.
-
-
- ───────────────────────────────────────────────────────────────────────────
- Part 1 Working with Microsoft FORTRAN
-
- Part 1 covers several topics that let you tailor applications written in
- Microsoft FORTRAN to your specific needs. These topics include options for
- handling floating-point math operations, control over memory models and
- segment usage, and special features available under OS/2, such as multiple
- threads of execution and dynam-ically linked libraries.
-
- Two chapters discuss how to call other-language programs from Microsoft
- FORTRAN──including C, Pascal, BASIC, and assembly languages, such as
- Microsoft Macro Assembler (MASM). Review these chapters if you plan to port
- programs written in FORTRAN to other computers and you want them to access
- data created by other applications. Since FORTRAN supports several record
- structures, one chapter reviews each of the different structures and its
- particular strengths. The last chapter describes strategies for optimizing
- programs for both size and speed.
-
-
- Chapter 1 Controlling Floating- Point Operations
- ───────────────────────────────────────────────────────────────────────────
-
- Microsoft FORTRAN 5.0 lets you control how your programs handle
- floating-point math operations. In calculation-intensive programs, a well
- chosen floating-point option can speed execution and increase precision.
- This chapter describes the math packages you can install in FORTRAN
- libraries when you run the SETUP program. It also discusses the FL command
- options for choosing the appropriate library for linking and controlling
- floating-point instructions. (For specific information on the FL command,
- see Chapter 7 in the Microsoft FORTRAN Reference.)
-
- This chapter also explains how to override floating-point options by
- changing libraries at link time; how to control an 8087, 80287, or 80387
- coprocessor with the NO87 environment variable; and how to handle the
- 8087/80287/80387 floating-point exceptions. Finally, if you run your program
- on a computer that is not IBM compatible, review the last section of the
- chapter for any special considerations for your machine.
-
-
- 1.1 Choosing a Math Package
-
- The Microsoft FORTRAN Compiler offers a choice of these floating-point math
- packages:
-
- ■ 8087/287/387 (default) package
- ■ Emulator package
- ■ Alternate math package
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- The math options support the Intel(R) 8087, 80287, and 80387 math
- coprocessors. For brevity, this book uses the term "8087/287/387" to
- refer to all three coprocessors.
- ───────────────────────────────────────────────────────────────────────────
-
- When you run the SETUP program, you choose one of these math packages. SETUP
- includes the math package you choose in the library it builds. Any programs
- linked to that library use the math package included in the library; you
- must apply the appropriate FL option to make sure that the library you want
- is used at link time.
-
- Use the following descriptions of the math packages to help you choose the
- option that best suits your needs when you run SETUP. (You can run SETUP as
- many times as necessary to build the libraries you want.)
-
-
- 1.1.1 The 8087/287/387 Package
-
- The FORTRAN 8087/80287/80387 math package takes full advantage of a math
- coprocessor to perform floating-point operations. Intensive floating-point
- operations tend to slow down computer operations. The 8087/287/387
- coprocessors are math chips dedicated to performing floating-point
- operations rapidly.
-
- This package requires an installed math coprocessor chip; programs compiled
- to use this package fail to run without the coprocessor (an error message
- reading floating point not loaded is issued). This is the default math
- package that SETUP uses if you do not explicitly choose another package.
-
-
- 1.1.2 The Emulator Package
-
- The emulator package uses an 8087, 80287, or 80387 coprocessor if one is
- installed. If no coprocessor is available, this package emulates many of the
- 8087/287/387 functions with software. The emulator package is the best
- choice if you want to maximize program precision and speed and you want the
- program to run on systems with and without coprocessors.
-
- The emulator package can perform basic operations to the same degree of
- precision as an 8087/287/387 chip. However, the emulator routines used for
- transcendental math functions differ slightly from the corresponding
- 8087/287/387 functions. This can cause a slight difference (usually within 2
- bits) in the results of such operations when performed with the emulator
- instead of with an 8087/287/387.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- When you use an 8087, 80287, or 80387 coprocessor or the emulator, the
- interrupt-enable, precision, underflow, and denormalized-operand
- exceptions are masked by default. The remaining exceptions are unmasked.
- ───────────────────────────────────────────────────────────────────────────
-
-
- 1.1.3 The Alternate Math Package
-
- The alternate math package gives you the smallest and fastest programs
- possible without a coprocessor. However, the program results are not
- accurate to as many significant digits as results given by the emulator
- package or 8087/287/387 math coprocessors.
-
- The alternate math package uses a subset of the Institute of Electrical and
- Electronics Engineers, Inc. (IEEE) standard format numbers. Infinities,
- NANs, and denormal numbers are not used.
-
-
- 1.2 Using the Floating-Point Options (/FP)
-
- The /FP options of the FL command control how a program handles
- floating-point operations. Based on the /FP option and the memory-model
- option you choose, the FL command embeds a library name in the object file
- it creates. (See Table 1.1, "Summary of Floating-Point Options," for a list
- of the library names used for each combination.) Unless the /Lp or /Lr
- option is specified, this library becomes the default library; that is, the
- linker searches in the standard places for a library with that name. If it
- finds such a library, the linker uses that library to resolve external
- references in the object file. Otherwise, the linker displays a message
- indicating that it could not find the library. (The /Lp and /Lr options use
- the OS/2 dual-mode naming conventions. See Chapter 3 for a discussion of
- OS/2 default library names. Unless otherwise indicated, this chapter assumes
- that you use the DOS naming conventions.)
-
- This mechanism allows the linker to link the object file automatically with
- the requested library. However, there are exceptions to the rule; you are
- allowed to link with a different library in some cases (as explained later
- in this section and in Section 1.3, "Library Considerations in Selecting /FP
- Options").
-
- You should use only one of these options on the FL command line. The option
- applies to the entire command line, regardless of its position. (Note that x
- represents a wild card, so that xLIBFORA.LIB refers to either LLIBFORA.LIB
- or MLIBFORA.LIB.) The available options are listed below.
-
- Option Effect
-
- /FPa Generates floating-point calls;
- selects xLIBFORA.LIB
-
- /FPc Generates floating-point calls;
- selects xLIBFORE.LIB
-
- /FPc87 Generates floating-point calls;
- selects xLIBFOR7.LIB
-
- /FPi Generates in-line instructions;
- selects xLIBFORE.LIB
-
- /FPi87 Generates in-line instructions;
- selects xLIBFOR7.LIB (default)
-
- Each /FP option includes two specifications:
-
- 1. The floating-point instructions, either in-line 8087/287/387
- instructions or calls to floating-point library functions. The letter
- "i" indicates in-line instructions; the letters "c" or "a" indicate
- floating-point calls.
-
- 2. The default floating-point package to use when you link the program.
-
- Table 1.1 summarizes the /FP options and their effects.
-
- Table 1.1 Summary of Floating-Point Options
-
- Use of
- Option Method Advantages Coprocessor
-
- /FPi87 In line Smallest memory Required
- requirements and
- fastest option
- available with a
- coprocessor
-
- /FPc87 Calls Slower than /FPi87, Required
- but allows library
- changes at link time
-
- /FPi In line Larger than /FPi87, Used if
- but works without a present
- coprocessor; maximizes
- precision without a
- coprocessor
-
- /FPc Calls Slower than /FPi, but Used if
- allows changing present
- library at link time
-
- /FPa Calls Fastest and smallest Ignores
- option available coprocessor
- without a coprocessor,
- but sacrifices
- accuracy to speed
-
-
- The /AL (large) memory-model option is the default. Therefore, if no
- memory-model option is given on the same FL command line, the default
- library for each floating-point option is LLIBFORx.LIB (where x is 7, E, or
- A, depending on the math package the library supports). If the /AM
- memory-model option is given, the default library is MLIBFORx.LIB.
-
- The compiler may evaluate some expressions. Such evaluations always use the
- highest precision possible independent of the floating-point option you
- choose.
-
- Sections 1.2.1-1.2.5 discuss the /FP options and the advantages and
- disadvantages of each option.
-
-
- 1.2.1 The /FPi87 Option
-
- The default floating-point option is /FPi87, which includes the name of an
- 8087/287/387 library (either LLIBFOR7.LIB or MLIBFOR7.LIB, depending on the
- memory model) in the object file. At link time, you can change your mind and
- link explicitly with an emulator library (either with LLIBFORE.LIB or
- MLIBFORE.LIB, depending on the memory model). If you use this option and
- link with an 8087/287/387 library, an 8087, 80287, 80387 coprocessor must be
- present at run time; otherwise, the program fails and the math package
- displays an error message reading
-
- floating point not loaded
-
- the /FPi87 option.
-
- If you compile with /FPi87 and link with an emulator library, and a
- coprocessor is present at run time, you can use the NO87 environment
- variable if you wish to suppress the use of the coprocessor. (See Section
- 1.4 for a description of NO87.) If you link with an 8087/287/387 library,
- the /FPi87 option is the fastest and smallest option available for
- floating-point operations.
-
- The Microsoft FORTRAN Compiler does not generate true in-line 8087/287 code
- when you use the /FPi87 option. Instead, the compiler inserts software
- interrupts to library-code software that direct each interrupt to use either
- the emulator or coprocessor, as appropriate. If you have linked the emulator
- code to your program, these interrupts will call the emulator if a math chip
- is not available.
-
- If your program is designed to run only with a coprocessor, you can speed up
- the program by assembling and linking the following code, which eliminates
- this special processing. In addition, all divide-by-zero errors will be
- masked.
-
- PUBLIC FIARQQ, FICRQQ, FIDRQQ, FIERQQ, FISRQQ, FIWRQQ
- PUBLIC FJARQQ, FJCRQQ, FJSRQQ
-
- FIARQQ EQU O
- FICRQQ EQU O
- FIDRQQ EQU O
- FIERQQ EQU O
- FISRQQ EQU O
- FIWRQQ EQU O
- FJARQQ EQU O
- FJCRQQ EQU O
- FJSRQQ EQU O
-
- extrn __fpmath:for
- extrn __fpsignal:for
- extrn __fptaskdata:for
-
- CDATA segment word common 'DATA'
- dw 0
- dw__fpmath
- dw__fpsignal
- dw__fptaskdata
- CDATA ends
-
- END
-
-
- 1.2.2 The /FPc87 Option
-
- The /FPc87 option generates function calls to routines in the 8087/287/387
- library (LLIBFOR7.LIB or MLIBFOR7.LIB, depending on the memory model) that
- perform the corresponding 8087/287/387 instructions. As with the /FPi87
- option, you must have an 8087, 80287, or 80387 coprocessor installed to run
- programs compiled with this option and linked to an 8087/287/387 library.
- How-ever, the /FPc87 option also allows you to change your mind at link time
- and link to an alternate math library instead of emulator or 8087/287/387
- libraries. (See Section 1.3, "Library Considerations in Selecting /FP
- Options," for information about changing libraries at link time.)
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- Certain optimizations are not performed when /FPc87 is used, reducing the
- efficiency of your code. Since arithmetic of different precision may
- occur, the results may vary slightly.
- ───────────────────────────────────────────────────────────────────────────
-
-
- 1.2.3 The /FPi Option
-
- The /FPi option generates in-line instructions for an 8087, 80287, or 80387
- coprocessor and places the name of the emulator library (LLIBFORE.LIB or
- MLIBFORE.LIB) in the object file. This option is particularly useful when
- you do not know in advance whether or not an 8087/287/387 coprocessor will
- be available at run time. If you distribute your program for use on other
- computers, you should use the /FPi option.
-
- If a coprocessor is present at run time, the program uses the coprocessor.
- If not, the emulator carries out the floating-point operations. If a
- coprocessor is not present at run time, the /FPi option is the most
- efficient way to maximize floating-point precision.
-
-
- 1.2.4 The /FPc Option
-
- The /FPc option generates floating-point calls to the emulator library and
- then places the name of the emulator library (LLIBFORE.LIB or MLIBFORE.LIB,
- depending on the memory model) in the object file. The /FPc option gives you
- more flexibility than /FPi, since it allows linking with either an
- 8087/287/387 or alternate math library instead of an emulator library. (See
- Section 1.3 below for information about changing libraries at link time.)
- This option is also recommended if you link to libraries other than the ones
- SETUP builds.
-
-
- 1.2.5 The /FPa Option
-
- The /FPa option generates floating-point calls and selects the alternate
- math library (LLIBFORA.LIB or MLIBFORA.LIB, depending on the memory model).
- This library provides the fastest and smallest library if you do not use an
- 8087, 80287, or 80387 coprocessor. Like the /FPc option, /FPa lets you
- decide at link time whether to use an emulator or 8087/287/387 library.
-
-
- 1.3 Library Considerations in Selecting /FP Options
-
- Sometimes you may want to use other libraries in addition to the default
- library for the floating-point option you chose on the FL command line. For
- example, you may want to create your own libraries or other collections of
- subprograms in object-file form and link these libraries at a later time
- with object files that you have compiled using different FL options. The
- following sections discuss these cases and how to handle them. Although the
- discussion assumes that you put your precompiled object files into
- libraries, the same considerations apply if you use individual object files.
-
-
- 1.3.1 Choosing In-Line Instructions or Calls
-
- To choose an appropriate floating-point option, you must first decide
- whether you want to use in-line instructions and compile with the /FPi87 or
- /FPi option, or if you want to use floating-point function calls and compile
- with the /FPc87, /FPc, or /FPa option.
-
- If you choose in-line instructions for your precompiled object files, you
- cannot use the alternate math package (that is, you cannot link with an
- xLIBFORA.LIB library). However, in-line instructions give the best
- performance if you run your program on machines with an 8087, 80287, or
- 80387 coprocessor.
-
- If you choose calls, your code executes more slowly, but at link time you
- can use any standard FORTRAN library (that is, any library created by the
- SETUP program) that supports the current memory model.
-
-
- 1.3.2 Using a Standard Library for Linking
-
- You must use only one standard FORTRAN library when you link. You can
- control which library is used in one of two ways:
-
- 1. At link time, as the first name in the list of object files to be
- linked, give an object file that contains the name of the desired
- library. For example, if you want to use the alternate math library,
- you must give the name of an object file compiled using the /FPa
- option. All floating-point calls in this object file refer to the
- alternate math library.
-
- 2. At link time, select the /NOD (no-default library search) option and
- then give the name of the library file containing the floating-point
- package you want to use in the "Libraries" field or in response to the
- "Libraries" prompt. This library overrides the library names in the
- object files; all floating-point calls refer to the named library.
-
- Each library in the object files being linked is added to the "linker search
- list" (that is, the list of libraries that the linker searches to resolve
- calls external to FORTRAN). This searching can complicate the choice of a
- standard library.
-
- Suppose, for example, that you use the /FPa option on a large memory-model
- program to create a set of object files and then use the LIB utility to
- combine these object files into a library. Very possibly, each object file
- would include a default library name (that is, you did not use the /Zl
- option to compile). If you want to link this library with an object file
- created using the /FPc87 option, note that both LLIBFOR7.LIB and
- LLIBFORA.LIB are in the linker search list (assuming you compiled with the
- default memory-model option). The linker searches libraries on the command
- line first, so it searches LLIBFOR7.LIB before it searches LLIBFORA.LIB.
- Since LLIBFOR7.LIB would resolve all external references correctly, this
- mechanism works correctly.
-
- You can ensure that the standard library of your choice is used for linking
- by explicitly giving the library name on the LINK command line. In this
- case, LINK always searches the library you specify before it searches any
- libraries named in the object files. However, make sure you specify this
- library after you have specified any of your own libraries on the LINK
- command line. If you do not specify it, and your library contains a
- different search directive, you may encounter problems.
-
- For example, suppose the object modules in library B were compiled with the
- /FPc87 option, so that each module contains a search directive for the
- library LLIBFOR7.LIB. You want to link with an object file A compiled with
- the /FPa option, so that this object file contains a search directive for
- LLIBFORA.LIB. The following command line links library B with the object
- file A:
-
- LINK A,,,LLIBFOR7+B;
-
- The linker then searches the libraries in the following order:
-
- 1. LLIBFOR7.LIB (since it is specified first on the command line)
-
- 2. B (since it is specified second on the command line)
-
- 3. LLIBFORA.LIB (since the object module A contains a search directive
- for this library)
-
- 4. LLIBFOR7.LIB (since the modules in your library B contain search
- directives for this library)
-
- The link procedure would be as follows:
-
- 1. The linker searches LLIBFOR7.LIB and resolves all references in object
- file A to standard run-time routines, since you specified this library
- on the command line.
-
- 2. The linker closes LLIBFOR7.LIB and searches the next library in the
- list to satisfy references to routines in your library B. These
- routines normally contain references to standard run-time routines.
- Since LLIBFORA.LIB is the next library to be searched, this library
- satisfies the references in B. How-ever, this is not the library you
- intended to use, since you compiled B with the /FPc87 option, which
- uses LLIBFOR7.LIB to resolve references to standard run-time routines.
-
- As indicated in the example above, you cannot mix libraries in this fashion;
- you may get linker errors if you try. Note that if you had specified the
- library B+LLIBFOR7.LIB instead of LLIBFOR7.LIB+B on the LINK command line,
- the linker would have searched LLIBFOR7.LIB instead of the library
- LIBFORA.LIB to resolve standard run-time references in B, and the linking
- operation would have proceeded correctly.
-
- To avoid this kind of ambiguity and to make absolutely sure you are
- specifying the correct standard library for linking, use the /NOD linker
- option. This option causes the linker to search only the libraries that you
- specify on the command line.
-
- Alternately, use the /NOD: libraryname form to suppress the default search
- for a specific library. This is useful if a library specified on the command
- line includes search directives for other libraries that you do not wish to
- specify explicitly on the command line. For example, the OS/2 protected-mode
- libraries contain search directives for the support library, DOSCALLS.LIB.
-
- Perhaps the safest course of all, especially when you are distributing
- libraries to other users, is to compile the object files that make up the
- library with the /Zl option. This option tells the compiler not to include
- search directives in the object files. Later on, when you link the library
- with different object files, the standard library used for linking depends
- only on the floating-point and memory-model options used to compile the
- later object files. The /FPc compiler option is recommended for maximum
- flexibility when linking with such libraries.
-
- In the example below, the source file CALC.FOR is compiled with the default
- floating-point option, /FPi87:
-
- FL /c CALC.FOR
- LINK CALC+ANOTHER+SUM;
-
- /FPi87 generates in-line instructions and selects the 8087/287/387 library
- (that is, LLIBFOR7.LIB, since no floating-point option is given and the
- large-model library is the default).
-
- In the following example, CALC.FOR is compiled with the alternate math
- option (/FPa):
-
- FL /c /FPa CALC.FOR
- FL CALC ANOTHER SUM /link LLIBFORE.LIB /NOD
-
- When the FL command is used to link, the /link field (options appearing
- after /link) specifies the /NOD option so that the LLIBFORA.LIB library
- (whose name is embedded in the object fileCALC.OBJ ) is not searched. This
- field gives the name LLIBFORE.LIB, which causes all floating-point calls to
- refer to the emulator library instead of the alternate math library.
-
- In the example below, SAMPLE.FOR is compiled with the /FPc87 option, which
- selects the 8087/287/387 library LLIBFOR7.LIB, as the default library:
-
- FL /FPc87 SAMPLE.FOR /link /NOD:LLIBFOR7.LIB LLIBFAP.LIB
-
- However, the command line uses the /NOD: option to suppress the selection of
- LLIBFOR7.LIB, and tells the linker to use LLIBFAP.LIB instead (the
- OS/2-protected mode of the alternate math library). The /NOD: option
- instructs the linker to ignore the next library specified on the command
- line, but to include any subsequent libraries (and any references they
- contain to other libraries). Thus, DOSCALLS.LIB (referenced in LLIBFAP.LIB)
- is still searched.
-
-
- 1.3.3 Ensuring Compatibility between Options
-
- Each time you compile a source file, you can specify a floating-point
- option. When you link more than one object file to produce an executable
- program file, you must ensure that floating-point operations are handled in
- a consistent way and that the current environment allows the linker to find
- the required library. Left to itself, the linker may or may not pick the
- library you intended. (See the Microsoft FORTRAN Getting Started manual for
- information about choosing floating-point options for the libraries you
- build with the SETUP program.)
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- If you are building your own libraries of routines that contain
- floating-point operations, the /FPc floating-point option is recommended
- for all compilations, as it offers the greatest flexibility.
- ───────────────────────────────────────────────────────────────────────────
-
-
- 1.3.4 Special Procedure for MS-DOS 3.2 Users
-
- This section is important only if your system has all of the following:
-
- ■ You use MS-DOS Version 3.2.
- ■ You boot from a hard disk drive.
- ■ Your computer uses a math coprocessor (such as the 80387).
- ■ You run programs that use floating-point math.
-
- For systems that satisfy all of the preceding conditions, you may be able to
- eliminate floating-point math problems by installing a small patch in DOS.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- The floating-point problem has been eliminated in versions of DOS higher
- than 3.2. This includes DOS 3.21 and 3.3.
- ───────────────────────────────────────────────────────────────────────────
-
- If you are not sure whether you need the patch, take these steps:
-
- 1. Copy the program PATCH87.EXE (included in this release) to the root
- directory of your hard drive.
-
- 2. Reboot your system from the hard disk. Do not perform any floppy-disk
- operations after rebooting. It is very important to avoid floppy-disk
- I/O after rebooting because it will affect the reliability of the
- diagnostic test you are about to perform.
-
- 3. If necessary, use the CD command from DOS to move to the root directory
- of your hard disk.
-
- 4. Run the PATCH87.EXE program by entering this command at the DOS prompt:
-
- PATCH87
-
- The program then performs a diagnostic test on your system to determine
- whether it needs the DOS patch and, if so, whether it can be performed
- successfully.
-
- If the test indicates that you should install the DOS patch, take these
- steps:
-
- 1. Format a blank floppy disk. (Do not use the /S formatting option to
- transfer system files to the disk. See Chapter 3 of the Microsoft
- FORTRAN Reference, "Nonrepeatable Edit Descriptors," for more
- information on /S.)
-
- 2. Use the SYS command to copy IO.SYS and MSDOS.SYS (or PCDOS.SYS) from
- the root directory of your hard disk to the new floppy disk. For
- instance, if you boot from drive C:, you would enter the following
- commands:
-
- C:
- SYS A:
-
- 3. Use the COPY command to copy COMMAND.COM and SYS.COM to the same floppy
- disk.
-
- 4. Use the COPY command to copy the program PATCH87.EXE (included in this
- release) to the same floppy disk.
-
- 5. Change the current drive and directory to the floppy disk, by entering
-
- A:
-
- 6. Install the DOS patch by entering
-
- PATCH87 /F
-
- ───────────────────────────────────────────────────────────────────────────
- WARNING
- If you experience any disk errors during steps 2 through 6, do not
- proceed with step 7. Reboot from your hard disk and repeat the entire
- process.
- ───────────────────────────────────────────────────────────────────────────
-
- 1. If you do not experience any errors, use the SYS command to transfer
- the files IO.SYS and MSDOS.SYS (or PCDOS.SYS) from the floppy disk back
- to your hard disk. For instance, if your system boots from the root
- directory of drive C:, you would enter the following command at the DOS
- prompt:
-
- A:
- SYS C:
-
- 2. The DOS patch has been installed. Reboot the system.
-
-
- 1.3.5 Using $FLOATCALLS and $NOFLOATCALLS
-
- The $FLOATCALLS and $NOFLOATCALLS metacommands control whether
- floating-point operations are processed through calls to library subroutines
- or by in-line instructions. These metacommands are no longer recommended.
- The /FP options offer similar control and are more flexible because they
- select the library to be used as well as the processing method.
-
- However, if you have existing code that contains these metacommands, keep in
- mind that $FLOATCALLS and $NOFLOATCALLS control only the processing method
- for floating-point operations. They do not affect the library name that the
- compiler places in the object file; this is still determined by the /FP and
- /A options that you choose on the FL command line.
-
- Also note that these metacommands take precedence over the floating-point
- options you give on the FL command line. This may mean, for example, that a
- source file containing $NOFLOATCALLS may result in an object file that
- contains in-line instructions, even if it were compiled with the /FPa
- option. Such an object file would not link correctly with an alternate math
- library.
-
-
- 1.4 Using the NO87 Environment Variable
-
- Programs compiled with the /FPc or /FPi option use an 8087/287/387
- coprocessor at run time if one is installed. You can override this and force
- the use of the emulator instead by setting the NO87 environment variable.
- (See Section 2.5.1 or your DOS documentation for a discussion of environment
- variables.)
-
- If NO87 is set to any value when the program executes, the program ignores
- an 8087/287/387 coprocessor. The value of the NO87 setting appears on the
- standard output as a message. The message displays only if an 8087/287/387
- is present and suppressed; if no coprocessor is present, no message appears.
- If you don't want a message printed out, set NO87 equal to one or more
- spaces.
-
- Note that only the presence or absence of the NO87 definition is important
- in suppressing use of the coprocessor. The actual value of the NO87 setting
- only affects whether a message prints on the screen.
-
- The NO87 variable takes effect with any program linked with the emulator
- library (LLIBFORE.LIB or MLIBFORE.LIB). It has no effect on programs linked
- with LLIBFOR7.LIB, MLIBFOR7.LIB, MLIBFORA.LIB, or LLIBFORA.LIB.
-
- The following is an example of how NO87 can be used:
-
- SET NO87=Use of coprocessor suppressed
-
- This statement causes the message Use of coprocessor suppressed to appear
- on the screen when running a program that can use an installed 8087, 80287,
- or 80387 coprocessor. Note that if the equal sign is followed by a blank
- space, the coprocessor is suppressed but no message is displayed.
-
- The example below assigns no variable to NO87; the statement does not affect
- the coprocessor Note that no characters or spaces can follow the equal sign.
-
- SET NO87=
-
- Programs that can use an 8087/287/387 coprocessor do use it, if one is
- present.
-
-
- 1.5 Handling 8087/287/387 Floating-Point Exceptions
-
- The five exceptions to floating-point arithmetic required by the IEEE
- standard are supported by the 8087/287/387 coprocessor and the real-math
- support routines. Exceptions that would result in a NAN ("Not a Number")
- error message are enabled by default. The others are disabled.
-
- These exceptions are not affected by the $DEBUG metacommand; instead, they
- are controlled by a "status" word and a "control" word, as explained below.
-
- Table 1.2 explains the six exceptions and their default and alternative
- actions.
-
- Table 1.2 Floating-Point Exceptions
-
- Floating-Point Default
- Exception Explanation Action
-
- Invalid operation Results in a NAN, such Enabled; gives
- as the square root of run-time error message
- -1 or 0*INF M6101
-
- Divide by zero Evaluates to a real Enabled; gives
- number divided by run-time error message
- zero: r/0.0 M6103
-
-
-
- Overflow Results in a number Enabled; gives
- greater than maximum run-time error message
- representable number M6104
-
- Underflow Results in a number Disabled; returns zero
- smaller than the
- smallest valid
- representable number
-
- Denormalized Results in a number
- operand so small that it can
- only be approximately
- represented
-
- Precision (or Occurs whenever a Disabled; returns
- inexact) result is subject to properly rounded
- rounding error result
-
-
- If any of these six exceptions are disabled, you can get NAN, Infinite, or
- Indefinite values in your variables. If you print such a value, the output
- field will contain NAN, INF, or IND, padded with periods to the field width.
- If the output field has fewer than three spaces, only periods are printed.
-
-
- 1.5.1 Controlling the Processing Environment
-
- The 8086/286/386 and 8087/287/387 processors are controlled by the status
- word and the control word, respectively. This section describes the uses of
- these memory locations.
-
- When one of the floating-point-exception conditions given in Table 1.2 above
- occurs, the appropriate bit in the status word is set. This flag remains set
- until you clear it.
-
- Figure 1.1 shows the format of the status word.
-
- When the bit corresponding to one of these exceptions is set (equals 1) in
- the control word, that exception is masked, and the operation that caused
- the exception proceeds with its default action. Alternately, if a bit is
- reset (equals 0), the corresponding exception generates an error message,
- halts the operation, and terminates the program. In either case, the
- exception is logically connected (with OR) into the status word. See Chapter
- 1 in the Microsoft FORTRAN Reference for more information on logical
- operators.
-
- Figure 1.2 shows the format of the control word.
-
- Besides masking-exception conditions, the control word is used to set the
- following modes for the internal arithmetic required by the IEEE standard:
-
- Mode Description
-
- Infinity control Chooses affine mode (the mode
- where the familiar +INF and -INF
- style of arithmetic is used) or
- projective mode (the mode where
- +INF and -INF are considered to
- be the same number). The
- principal effect of projective
- mode is to change the nature of
- comparisons; projective INF does
- not compare with anything but
- itself.
-
- Round control Rounds to nearest (or even), up,
- down, or truncates.
-
- Precision control Determines the bit of the
- mantissa (24, 53, or 64) at which
- rounding takes place. All results
- are stored to 64 bits regardless
- of precision control which
- affects only the rounding in the
- internal form. When stored, any
- result is rounded to the storage
- precision again.
-
- The current defaults for the control word are shown in the following list:
-
- Mode or Mask Default
-
- Infinity control Affine
- Round control Nearest
- Precision control 64 bits
- Interrupt-enable mask Unmasked
- Precision mask Masked
- Underflow mask Masked
- Overflow mask Unmasked
- Zero-divide mask Unmasked
- Denormalized-operand mask Masked (cannot be changed)
- Invalid-operation mask Unmasked
-
- Table 1.3 below defines the mask settings for the overflow, zero-divide, and
- invalid-operation exceptions associated with several optional control words.
- A control-word value of decimal 4914 specifies the default-mask settings
- that are customary during 8087/287/387 operations.
-
- Table 1.3 Mask Settings for Operation Exceptions
-
- Control Word Overflow Zero Divide
-
- 4914 = 16#1332 Unmasked Unmasked
- 4915 = 16#1333 Unmasked Unmasked
- 4918 = 16#1336 Unmasked Masked
- 4919 = 16#1337 Unmasked Masked
- 4922 = 16#133A Masked Unmasked
- 4923 = 16#133B Masked Unmasked
- 4926 = 16#133E Masked Masked
- 4927 = 16#133F Masked Masked
-
-
- 1.5.2 Reading and Setting Status and Control Values
-
- You can use the following procedures and functions to read or set the values
- of the status and control words──the INTEGER*2 arguments passed to the
- appropriate routines as described below. Their values determine the behavior
- of the 8086/286/386 (status-word) and 8087/287/387 (control-word)
- processors.
-
- The store-status-word (SSWRQQ) function returns the value of the status
- word. Use the following declaration for this procedure:
-
- INTERFACE TO INTEGER*2 FUNCTION SSWRQQ()
- END
-
- The store-control-word (SCWRQQ) function returns the value of the control
- word. Use the following declaration for this procedure:
-
- INTERFACE TO INTEGER*2 FUNCTION SCWRQQ()
- END
-
- The load-control-word (LCWRQQ) procedure sets the control word to a given
- value. LCWRQQ has the following declaration:
-
- INTERFACE TO SUBROUTINE LCWRQQ(CW)
- INTEGER*2 CW
- END
-
- Always use LCWRQQ to change the control word. To ensure that special
- routines handling stack-exceptions and denormal propagation will work
- correctly, the control-word and auxiliary variables must be set up in the
- same way that LCWRQQ organizes them. (Denormals are numbers very close to
- zero──on the order of 10^(-38) or smaller──that allow gradual underflow. The
- Microsoft FORTRAN numeric inquiry functions such as NEAREST and PRECISION do
- not apply to denormalized numbers. See IEEE math or Intel chip
- specifications for detailed information on denormals.)
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- Altering the 8087/287/387 control word with a macro assembler FLDCW
- (floating-point load-control word) instruction is not recommended if you
- use an 8087/287/387 coprocessor with a Microsoft language.
- ───────────────────────────────────────────────────────────────────────────
-
- Since the denormal exception is not a part of the IEEE standard, the
- Microsoft FORTRAN exception handler intercepts denormal exceptions to give
- the effect of being masked. The 8087/287/387 chips themselves do not mask
- denormals. You cannot alter this handling of denormals regardless of the
- denormal bit value in the LCWRQQ control word.
-
- The Microsoft FORTRAN exception handler allows for software masking of
- invalid operations, but does not allow the math chip to mask them. If you
- choose to use the software masking, be aware that this can affect program
- performance if you run software on other computers or compile code written
- for Microsoft FORTRAN with another compiler.
-
-
- 1.5.3 Floating-Point Exceptions under PC-DOS 3.2
-
- Programs running under IBM Personal Computer DOS (PC-DOS) 3.2 that
- explicitly trap for floating-point exceptions may not operate when
- floating-point exceptions occur.
-
- Use the following procedure to patch IBM PC-DOS 3.2:
-
- 1. Use the SYS command from PC-DOS to transfer IBMDOS.COM and IBMBIO.COM
- to a writable disk.
-
- 2. Copy COMMAND.COM, SYS.COM, and DEBUG.COM from your PC-DOS 3.2 floppy
- disk to the new disk.
-
- 3. Copy STKPAT.BAT, STKPAT.SCR, RMRHS.EXE, and SETRHS.EXE from the \PATCH
- directory (included in this release) to the new disk.
-
- 4. Reboot the system from the new disk.
-
- 5. Run STKPAT.BAT. This patches the IBMBIO.COM on the new disk.
-
- 6. Use the SYS command from PC-DOS to transfer the patch to any other IBM
- PC-DOS 3.2 disk.
-
- If you are running any version of DOS 3.2 other than IBM PC-DOS 3.2, contact
- your hardware manufacturer to see if the problem exists in your DOS 3.2
- version.
-
-
- 1.6 Using Non-IBM(R)-Compatible Computers
-
- If your computer is not an IBM or a closely compatible computer and you want
- to use an 8087/287/387 coprocessor, make sure that the computer handles
- exceptions correctly. All Microsoft languages that support the 8087/287/387
- coprocessors must intercept exceptions for accurate results and to detect
- error conditions properly. Most other language vendors do not detect or
- correct these errors.
-
- The exception handler in the emulator and the 8087/287/387 libraries (that
- is, LLIBFORE.LIB or MLIBFORE.LIB, and LLIBFOR7.LIB or MLIBFOR7.LIB,
- respectively) works without modification on the following computers:
-
- 1. The IBM PC family
-
- 2. Computers that are closely compatible with the IBM PC, such as the
- WANG(R) PC and the AT&T(R) 6300
-
- 3. The Texas Instruments(R) Professional Computer
-
- 4. Any machine that uses nonmaskable interrupts (NMI) for 8087/287/387
- exceptions
-
- If your computer is listed above, or if you are sure that it is completely
- IBM compatible, you can immediately begin linking your programs. If it is
- not listed, you may need to modify the 8087/287/387 libraries.
-
- The distribution disk contains an assembly-language source file, EMOEM.ASM,
- to help make any necessary modifications. Any machine that sends the
- 8087/287/387 exception to an 8259 Priority Interrupt Controller (master or
- master/slave) can be supported easily by a simple table change to the
- EMOEM.ASM module. The source file contains further instructions on how to
- modify EMOEM.ASM and patch executable files.
-
-
- Chapter 2 Selecting a Memory Model
- ───────────────────────────────────────────────────────────────────────────
-
- You can gain greater control over how your program uses memory by specifying
- the program's memory model. This chapter explains the concept of memory
- models and discusses in detail each of the different models provided with
- the Microsoft FORTRAN Compiler: medium, large, and huge models. Later
- sections advise you on how to select an appropriate model for your program
- and how to make any necessary adjustments to that model.
-
- Adjusting a memory model to meet your program's requirements can produce
- more efficient code than using the default model. Understand the default
- models first, then learn to modify them to fit specific needs.
-
-
- 2.1 What Is a Memory Model?
-
- A "memory model" is a set of predefined rules the compiler follows to
- transfer the program code and data into "segments" of 64K (kilobyte) blocks
- in memory. The memory model defines how the compiler organizes code and data
- into segments and what kind of addresses (near, far, or huge) will access
- the information in each segment. A near address is a 16-bit "offset"
- (location relative to the beginning of the current segment) that can access
- a maximum of 64K of mem-ory; a far address or a huge address is a 32-bit
- address that can access all avail-able memory. (See Section 2.2.2 for a
- discussion of the segmented memory and addresses of the 8086/80286
- microprocessor families.)
-
- When you select a memory model, you are telling the compiler that it can
- make certain assumptions about the program's characteristics and generate
- machine code accordingly. For example, when you select the large memory
- model (the default model for FORTRAN), the compiler allows for programs with
- more than 64K of code and 64K of data. The compiler must generate far
- addresses to access both code and data. In the medium model, the compiler
- expects only 64K or less of data, allowing it to generate near addresses to
- access data items.
-
-
- 2.2 Understanding Memory Models
-
- To understand how memory models work, you need a basic understanding of the
- segmented architecture of the 8086 family of processors. The remainder of
- this section gives an overview of the addressing conventions used on the
- 8086 processors and how they relate to memory models. Consult such
- references as the Programmer's Guide to the IBM PC for a detailed
- description of segments and their use.
-
-
- 2.2.1 Code and Data Segments
-
- When you load a program into memory, its code (compiled executable
- statements) and data (information the program uses) are placed in separate
- storage areas. The processor treats the stored code as a sequence of
- operations to be carried out. A program refers to other code locations by
- making calls to subroutines or functions. Stored data are any values needed
- by the program, for which an area of memory is reserved, including variable
- names, arrays, or common blocks.
-
- All processors make this fundamental distinction between code and data.
- However, the way in which a program's code and data are stored and accessed
- depends on the architecture and addressing schemes of the particular
- processor being used.
-
- On the 8086, 80286, and 80386, code and data occupy separate segments and
- are accessed through separate segment registers. (See Section 2.2.2 for an
- explanation of the different types of addresses and the use of segment
- registers on the 8086/286/386.)
-
-
- 2.2.2 Near, Far, and Huge Addresses
-
- The 8086 processor and its relatives are 16-bit machines. Normally, a
- machine using 16-bit addresses can access only 64K of memory. The 8086
- family of processors uses a special addressing scheme to overcome this
- limitation.
-
- To extend the amount of memory that can be addressed by a program, physical
- memory on the 8086 is divided into segments, each up to 64K long. The
- starting point of each segment in memory is represented by a 16-bit address.
-
-
- 2.2.2.1 Near Addresses
-
- The 8086 reserves four registers to hold segment base addresses: CS (code
- segment), DS (data segment), SS (stack segment), and ES (extra segment). A
- segment address, however, points only to the "base" (beginning) of the
- segment. To refer to a particular item within a segment, you must also give
- the location of the item within the segment. This requires a 16-bit offset
- address, which gives the address of an item relative to the base of a
- particular segment. A 16-bit offset is called a "near" address.
-
- Wherever possible, it is preferable for the compiler to generate near
- addresses, to access code and data items. Near addresses are much more
- efficient than far addresses, because they require less space and take less
- time to calculate.
-
- Although a complete 8086/286/386 address is 32 bits long, the 8086/286/386
- uses reserved segment registers in a way that makes it possible to access
- some items with just near addresses. To see how this works, take the
- simplest case, where a program has one code segment and one data segment.
- The 8086 family has two machine registers that are dedicated to accessing
- the code and data segments: the CS and DS registers. When a program loads,
- the CS register is set to the address of the code segment, and the DS
- register is set to the address of the data segment. Since these registers
- are reserved for this purpose, the built-in 8086 instructions assume that
- the appropriate segment addresses can be found there. So the instructions
- require only the 16-bit offset of an item within a segment.
-
-
- 2.2.2.2 Far Addresses
-
- Many programs, however, contain more than 64K of code or more than 64K of
- data. The addressing scheme becomes more complicated for larger programs.
-
- A complete address on the 8086/286/386, then, requires 32 bits: 16 bits for
- the segment address and 16 bits for the offset. A full 32-bit address is
- known as a "far" address.
-
- When program code exceeds 64K, it occupies more than one code segment. The
- Microsoft FORTRAN Compiler places the code from each "module" (compiled
- source file) in its own segment. Each module is therefore restricted to 64K
- or less, since it must fit in a segment. All calls to subroutines and
- functions require the compiler to use far addresses, since the address of
- the code must include both the segment (the location of the module) and the
- offset (the location of the subroutine or function within the module). This
- increases the size of the program and makes it less efficient, but allows it
- to grow beyond 64K.
-
- Similarly, programs with more than 64K of data occupy more than one data
- segment. The compiler divides data into different classes (for example,
- global uninitialized data, constants, and global initialized data) and
- assigns different classes to different segments.
-
- With multiple data segments, some data items are placed in the "default data
- segment," the data segment addressed by the DS register. (See Section
- 2.2.3 for more information about this data segment.) The compiler only
- needs to generate a 16-bit offset address to access these items, since it
- uses the DS register to "point" to this segment. However, it must generate
- full 32-bit (far) addresses to access any data items outside the default
- data segment. This increases the size and makes programs less efficient,
- but it allows the program to access large amounts of data, a common
- requirement for FORTRAN programs.
-
-
- 2.2.2.3 Huge Addresses
-
- One further complication can arise when a program has very large data items.
- A program may contain a single data item (array or common block) that
- exceeds 64K. Normally, the compiler calculates addresses of elements within
- a single data item using 16-bit (near) arithmetic. To do this, it assumes
- that all elements of the data item lie within the same segment, so the same
- base address can be used for the address of all elements. When a single data
- item exceeds 64K, this assumption no longer holds true.
-
- To access elements within a data item that exceeds 64K, the compiler must
- calculate addresses using 32-bit (far) arithmetic. In Microsoft FORTRAN, a
- single data item larger than 64K is known as a "huge" data item, and the
- address of the item is a "huge" address. A huge address, like a far address,
- is a full 32-bit address, but the huge address has the additional
- implication that 32-bit offsets are required to access all individual
- elements of the data item.
-
- Only data items can have huge addresses. The code for each module is
- restricted to 64K or less, so that it never exceeds one segment. Huge
- addresses are even less efficient than far addresses, but they resolve
- data-handling difficulties in programs that require very large data items.
-
-
- 2.2.3 The Default Data Segment
-
- Even in programs with multiple data segments, the address of a single data
- segment can remain in DS throughout program execution. This segment is known
- as the "default data segment." Items in this segment can be addressed with
- near addresses.
-
- Local data items (but not formal arguments) smaller than the "data
- threshold" (that is, the maximum allowable size for a single piece of data)
- are placed in this segment, unless a FAR or HUGE attribute is used to move
- the item outside the segment. (The data threshold is set with the /Gt
- option, described briefly in Section 2.4.5.1.) In addition, the default
- data segment always contains certain internal data, regardless of the data
- threshold value.
-
- Every program has a default data segment. In a program with only one data
- segment, the default data segment is the only data segment. See Section
- 2.3.2.1 for more information about the contents and use of the default
- data segment.
-
-
- 2.3 Working with FORTRAN Memory Models
-
- This section introduces the characteristics of the FORTRAN memory models
- (medium, large, and huge) and discusses strategies for working within the
- size limits for code and data. (Section 2.4 below gives additional
- information on selecting a memory model and adjusting it to program-specific
- needs.)
-
- Briefly, the standard memory models have the following characteristics:
-
- Model Characteristics
-
- Large (default) Total program code and data can
- each exceed 64K. Each module is
- given its own code segment;
- therefore, each module is limited
- to 64K. The compiler creates
- multiple code and data segments
- as needed. However, formal array
- arguments are restricted to 64K,
- unless the argument is explicitly
- declared with the HUGE attribute.
-
- Medium Total program data are restricted
- to 64K. Total program code can
- exceed 64K. Each module is given
- its own code segment and
- therefore limited to 64K.
-
- Huge This model has the same
- characteristics as the large
- model, but all formal array
- arguments are assumed to exceed
- 64K.
-
- Many of the code and data size limits apply to all three models. In fact,
- the only difference between the large and huge memory models is that the
- large model assumes arrays are smaller than 64K (both adjustable- and
- assumed-size arrays), while huge model assumes they are larger than 64K. The
- medium model differs from the large model only in its handling of common
- blocks, and use of near addresses rather than far addresses to pass
- subroutine arguments. See Section 2.3.2.4 for more information.
-
- Since the three memory models are similar in most respects, the following
- discussion of memory-model characteristics applies to all three models,
- except where noted.
-
-
- 2.3.1 Specifying a Memory Model
-
- Specify a memory model for your programs by taking the following steps:
-
- 1. When you run the SETUP program, you can either tell SETUP to build a
- library that supports the default (large) memory model or choose a
- different memory model. Based on your response, SETUP builds support
- for the preferred memory model into the run-time library it creates. If
- you want to use different memory models for different programs, create
- a separate library for each memory model.
-
- 2. When you compile a program with the FL command, you can give a
- memory-model option on the command line. This option allows FL to link
- the program to a library that supports that memory model. If you do not
- specify a memory model, FL links to a large-model library by default.
-
- Note that if you use the OS/2 dual-mode names (described in Section
- 3.1, "Compiling and Linking Under OS/2," in Chapter 3 of this manual),
- you may also need to specify the appropriate FL option /Lr, /Lp, or /Lc
- to select the correct library.
-
- The Microsoft FORTRAN Compiler defaults to the large memory model. The large
- model can accommodate programs that use more than 64K of total code and
- data. If the program uses multiple modules, each module can have up to 64K
- of code in a unique segment. For programs that require more than 64K of
- data, the compiler creates multiple data segments as needed by the program.
- See Sections 2.3.2.5 and 2.3.2.6 for specific restrictions of the large
- memory model.
-
- The large memory model can accommodate most of the programs compiled with
- the Microsoft FORTRAN Compiler. However, if a program does not fit in the
- large memory model, you must either shift to the huge memory model or use
- some of the techniques described in Chapter 7, "Optimizing Programs."
- Conversely, if a program runs under the large model, you may be able to
- improve its performance and decrease its size by changing to the medium
- memory model.
-
- Any large-model library (such as either LLIBFORE.LIB, LLIBFOR7.LIB, or
- LLIBFORA.LIB) works with the large or huge model. The medium model requires
- the library MLIBFORE.LIB, MLIBFOR7.LIB, or MLIBFORA.LIB.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- See Chapter 7, for a description of other ways you can improve program
- efficiency by choosing libraries during installation, choosing compiler
- command-line options, and using I/O options within the program.
- ───────────────────────────────────────────────────────────────────────────
-
-
- 2.3.2 Data-Handling Strategies and Limits
-
- The ways in which the three FORTRAN memory models allocate data result in
- different limits on data size. The sections below describe these
- data-allocation methods and the resulting limits. They also suggest
- strategies for working within these limits.
-
- See Table 2.1, "Data Allocation in Large Memory Models," in Section 2.3.2.6
- for a summary of data allocation.
-
-
- 2.3.2.1 Limits on the Default Data Segment
-
- Keeping data in the default data segment increases a program's efficiency.
- Items in the default data segment are usually accessed with near (16-bit)
- addresses, since the program only requires an offset from the address in the
- DS register. In the large and huge models, however, 32-bit addresses are
- used to pass arguments to other routines, unless the formal arguments are
- declared with the NEAR attri-bute (see Section 2.4.2 for more information).
-
- The default data segment contains the following:
-
- ■ The program stack, which holds arguments passed to subprograms and
- local data declared in an AUTOMATIC statement. Normally the stack is
- 2K, although you can change its size. In a multithread and/or
- dynamic-link library application running under OS/2, the program stack
- receives its own segment.
-
- ■ Floating-point and character constants, including constants generated
- by the compiler and I/O routines. These constants may differ in number
- or value from constants specified in the source program.
-
- ■ Data allocated or used by the run-time library, including run-time data
- and internal forms of formats for formatted I/O in medium-model
- programs.
-
- ■ Space for file I/O buffers for medium-model programs and space for
- dynamic allocation of file-control blocks (FCBs). Whenever an I/O
- package links with a program, FCBs are allocated for the terminal
- (console), for internal files, and for any additional files the program
- opens.
-
- For every FCB allocated, an associated I/O buffer is allocated as well;
- for medium-model programs, these buffers are allocated in the default
- data segment. In large-model programs, I/O buffers are allocated
- outside the default data segment. If you specify redirection on the FL
- command line, the compiler allocates an additional FCB and I/O buffer.
-
- ■ Arrays smaller than the data-threshold value in the large and huge
- models. The data threshold is a cutoff value set by the /Gt option
- which the compiler uses in allocating data. Any arrays larger than or
- the same size as the data threshold are stored in separate segments
- outside the default data segment and accessed with far addresses.
-
- ■ Subprogram entry and exit information, if the /4Yb option (or the
- $DEBUG metacommand) is in effect.
-
- ■ Allocatable arrays, if no far heap space is available.
-
- In the medium memory model, the default data segment also contains all
- common blocks not explicitly declared with the HUGE or FAR attribute.
-
- The total space required by the items listed above, including all local
- variables and arrays allocated in the default data segment, cannot exceed
- 64K and still remain in the default data segment. If the program violates
- this restriction, you have the following options:
-
- ■ Move some data items out of the default data segment by using the FAR
- or HUGE attribute. See Section 2.4.2 for more information on these
- attributes.
-
- ■ Use the /Gt option, described in Section 2.4.5.1, to move all data
- items larger than a given size out of the default data segment. Note
- that this option does not work with medium-model programs.
-
- ■ Use the BLOCKSIZE option in OPEN statements in the source program to
- change the size of the I/O buffers allocated to the units you open. By
- default, each unit is allocated a 1,024-byte I/O buffer; however, the
- BLOCKSIZE option allows you to specify a different buffer size. Note
- that this solution is effective only in medium-model programs, since
- these buffers are not stored in the default data segment in large and
- huge models.
-
- ■ Remove the /4Yb option (or the $DEBUG metacommand) from all debugged
- programs.
-
- Any of the above strategies help reduce the amount of information stored in
- the default data segment. As your program approaches 64K, heeding one or
- more of these suggestions may keep the entire program within the default
- segment.
-
-
- 2.3.2.2 Limits on Fixed-Size Arrays Exceeding 64K
-
- Fixed-size arrays larger than 64K are automatically allocated as many
- segments as necessary outside the default data segment. The compiler
- generates huge ad-dresses for these arrays since they cross segment
- boundaries. The only limit on the number of these huge arrays in the program
- is available memory.
-
- No individual scalar object, including an array element, can, however, span
- a segment boundary. If possible, the compiler offsets the start of an array
- in the segment so that this spanning does not occur. This cannot be done for
- character and structure arrays whose element size is not a power of two and
- whose length is greater than 128K. Common blocks cannot be adjusted either,
- since Microsoft FORTRAN does not require different program units to use the
- same declarations or ordering of variables. An error results if your array
- or common block declaration tries to allocate a scalar item across a segment
- boundary.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- Arrays smaller than 64K (65,536 bytes) but larger than 65,521 bytes
- should be considered larger than 64K and declared with the HUGE attribute
- (see Section 2.4.2 for more information). Even though such arrays do
- not exceed the 64K limit, they may be too large for a segment if the
- segment does not start on a paragraph boundary.
- ───────────────────────────────────────────────────────────────────────────
-
-
- 2.3.2.3 Limits on Adjustable- and Assumed-Size Arrays
-
- Adjustable-size and assumed-size arrays can appear in a FORTRAN program as
- formal arguments to subprograms. The size of an adjustable- or assumed-size
- array is determined at execution time by the size of the array passed as the
- cor-responding actual argument to the subprogram. (See the DIMENSION
- statement entry in Chapter 4 of the Microsoft FORTRAN Reference for more
- information on these types of arrays.)
-
- Although the size of such an array is actually determined at execution time,
- the compiler must decide on an addressing convention at compile time to
- generate references to the array. To do so, the compiler assumes either that
- the array is 64K or smaller, in which case it can generate near or far
- addresses, depending on where the array is stored──or, that the array is
- larger than 64K, in which case huge addressing is required.
-
- In the large and medium models, the compiler assumes that adjustable- and
- assumed-size arrays are 64K or smaller, and therefore generates near or far
- addresses to access them. If the actual size of an adjustable-size or
- assumed-size array exceeds 64K at execution time, the program's results are
- unpredictable.
-
- To arrange the program so that it will correctly handle adjustable-size and
- assumed-size arrays larger than 64K, you have the following choices:
-
- ■ You can specify the HUGE attribute when you declare a particular array
- as a formal argument. This attribute tells the compiler that the actual
- argument may be (but is not required to be) larger than 64K, causing
- the compiler to generate a huge address for that particular array.
-
- ■ You can use the huge memory model (described in Section 2.4.1.2). In
- the huge model, the compiler assumes that all adjustable-size and
- assumed-size arrays are larger than 64K and generates huge addresses to
- access them. To improve program efficiency in the huge model, you can
- use either the NEAR or FAR attribute with any adjustable-size or
- assumed-size array whose actual size will always be smaller than 64K.
-
- Note that both of the methods mentioned above work in all cases, whether or
- not the actual size of the adjustable-size or assumed-size array is larger
- than 64K.
-
- Fixed-size formal array arguments are treated as if they were assumed-size,
- except that a fixed-size formal array argument larger than 64K is implicitly
- treated as huge. All of the preceding comments about assumed-size arrays
- apply to fixed-size arrays, too. (This treatment of arrays promotes
- compatibility with earlier versions of FORTRAN that did not support assumed-
- or adjustable-size arrays, but did support their functionality by ignoring
- the last dimension of an array.)
-
-
- 2.3.2.4 Limits on Common Blocks
-
- In the large and huge memory models, each common block in the program is
- allocated as many segments as it needs outside the default data segment. If
- the common block is larger than 64K, the compiler generates huge addresses.
- If the common block is 64K or smaller, the compiler generates far addresses.
-
- Some restrictions apply to the variables of a common block larger than 64K.
- No individual array element or variable in a common block can span a segment
- boundary. The compiler allocates common blocks so that they always start at
- the beginning of a segment. This restriction means that the boundary between
- bytes 65,536 and 65,537 of the common block must fall between two variables
- or between two elements of an array.
-
- If an array in a common block spans a segment boundary and is passed as an
- actual argument, the corresponding formal argument must be declared with the
- HUGE attribute.
-
- If you have small, frequently accessed common blocks in your program, you
- may benefit from declaring such blocks with the NEAR attribute. This
- attribute causes the compiler to place the common block in the default data
- segment, where it can be accessed with more efficient near addresses.
- However, this is an option only if you have room in the default data
- segment. (See Section 2.3.2.1, "Limits on the Default Data Segment," for
- more information.)
-
- As an alternative, if you have room in the default data segment, you may be
- able to use the medium memory model. The medium memory model places all
- common blocks in the default data segment except the following:
-
- ■ Blank common blocks explicitly declared with the FAR attribute
- ■ Named common blocks larger than 64K
-
-
- 2.3.2.5 Limits on Arguments Passed to Subprograms
-
- Normally, FORTRAN arguments are passed by reference. When a subroutine is
- called, the compiler places the addresses of the arguments on the program
- stack. Such a method of passing arguments places some restrictions on the
- different memory models:
-
- ■ In the large and huge models, the compiler uses far (32-bit) addresses
- in order to pass arguments to subprograms, even if the arguments are in
- the default data segment.
-
- ■ In the medium memory model, the compiler uses near addresses to pass
- arguments to subprograms, with the assumption that all program data
- resides in the default data segment.
-
- The following strategies can help you bypass these stack restrictions:
-
- ■ In large and huge models, if a formal argument is declared with the
- NEAR attribute in the INTERFACE statement, the compiler uses a near
- (16-bit) address to pass the actual argument to the subprogram. Since
- near addresses are more efficient than far addresses, this will improve
- program efficiency. However, any actual arguments passed to NEAR formal
- arguments must reside in the default data segment, or unpredictable
- behavior may result.
-
- ■ In the medium memory model, if you want to pass an argument that is
- outside the default data segment (for example, an array declared with
- the FAR attribute, or any fixed-size array larger than 64K), you must
- declare the corresponding formal argument with the FAR or HUGE
- attribute.
-
- ■ In Microsoft FORTRAN, you can also pass arguments by value. When you
- use the VALUE attribute with an argument, you specify that the argument
- is to be passed by value instead of by reference. Instead of placing
- the address of the argument on the stack, the compiler places a copy of
- the argument's value on the stack.
-
- ■ The stack is normally part of the default data segment. The default
- stack size is 2K; you can change the size by using the /F option with
- FL, the /STACK option with LINK, or the EXEMOD utility. When passing
- arguments by value to a subprogram, be sure the total size required by
- the arguments does not exceed available stack space. Passing entire
- arrays by value can cause problems. Since arrays can exceed the stack
- size all by themselves, passing an array by value can cause a stack
- overflow with unpredictable results.
-
-
- 2.3.2.6 Summary of Data Allocation
-
- Table 2.1 summarizes data allocation in the large memory model. Differences
- between the large, huge, and medium models appear in footnotes to the table.
-
- Table 2.1 Data Allocation in Large Memory Models
-
- Type of Data Storage Address Type Restrict
-
- Local variables Default data segment Near Combined
- and fixed-size all such
- arrays smaller than variable
- the data threshold arrays,
- stack an
- data sto
- default
- segment,
- exceed 6
-
- Arrays smaller than Separate segments Far Availabl
- 64K but larger than outside default data
- the data threshhold segment
-
- Arrays larger than As many segments as Huge Availabl
- 64K needed outside default
- data segment
-
- Common blocks As many segments as Far if the Availabl
- needed outside default common block
- data segment is 64K or
- smaller; huge
- otherwise
-
-
- Also, for the large memory model the compiler assumes that all formal array
- arguments are 64K or smaller, unless specifically declared with the HUGE
- attribute. This is also true of the medium model. In the huge model, the
- compiler assumes that the adjustable-size and assumed-size arrays are larger
- than 64K, unless specifically declared with the NEAR or FAR attribute.
-
-
- 2.3.3 Limits on Code Size
-
- The Microsoft FORTRAN Compiler places the code from each module in its own
- segment. Since the maximum size of a segment is 64K, the compiled code in
- each module cannot exceed 64K. You can determine how much code each program
- module contains by looking at a source-file or map-file listing.
-
- The following sections describe some strategies you can use to minimize the
- size of your program code and make it more efficient. (See Chapter 7,
- "Optimizing Programs," for descriptions of other strategies.)
-
-
- 2.3.3.1 Creating Programs Larger than 64K
-
- If a module exceeds the 64K code-size limit, you must reduce its size by
- breaking it into two or more source files. An effective way is to break the
- source program into sections based on functionality and compile them
- separately. Working with the sections separately does not affect the final
- program size (although it may increase the total size of the object files),
- but it does alter the number of memory segments used. Keeping each piece
- focused on a particular aspect of the program also makes the source code
- easier to understand and maintain.
-
- Conversely, you can combine the code from two or more modules into one
- segment by using the /NT option (described in Section 2.4.5.2). Modules with
- identical text-segment names are loaded into the same segment, provided
- their combined length does not exceed the 64K segment limit.
-
-
- 2.3.3.2 Improving Efficiency with the NEAR Attribute
-
- FORTRAN uses far (32-bit) addresses to reference progam code because the
- reference must provide both the segment address and the offset of the code
- item within the segment. If the program uses some subprograms very heavily,
- you may increase program efficiency by using the NEAR attribute.
-
- When applied to a subprogram, the NEAR attribute specifies that the
- subprogram code resides in the same segment as the calling routine. Since
- the segment ad-dress remains constant, the compiler can generate a near
- (16-bit) address to call the subprogram.
-
- To use the NEAR attribute on a subprogram, you must make sure that the
- subprogram actually appears in the correct segment. You can do this by
- placing the subprogram in the same source file as the calling routine, thus
- ensuring that they compile into a single module.
-
- If you want to keep the routines in separate source files, you can use the
- /NT option to set the text-segment names for both modules. If you give both
- modules the same text-segment name, they will be loaded into the same
- segment.
-
- See Section 2.4.2 of this manual and Chapter 1 of the Microsoft FORTRAN
- Reference for more information on the NEAR attribute.
-
-
- 2.4 Selecting and Adjusting the Memory Model
-
- This section describes the methods you can use to select and adjust memory
- models. You can choose one of the three standard FORTRAN memory models by
- giving one of the /A options on the FL command line; these options are
- described in Section 2.4.1 below.
-
- When you use the standard memory models, the FL command handles library
- support for you. FL automatically links with a library corresponding to the
- memory model you specify on the command line, provided that you had already
- created this library at the time you ran the SETUP program. Unless you
- specify otherwise, FL uses a large-model library for linking; this is also
- the default for the library created by the SETUP program if you do not
- choose a memory model during installation. The large and huge models use the
- same library; the medium model has its own library.
-
- The advantage of using standard models for your program is simplicity. For
- the standard models, memory management is specified by compiler options and
- does not require the use of extended keywords. This is an important
- consideration if you expect to transfer your program to other systems,
- particularly systems that do not use segmented architecture. Note that
- the threshold option (/Gt), the text-segment-naming option (/NT), and the
- data-segment-naming option (/ND) are also portable ways to control
- allocation.
-
- The disadvantage of using standard memory models exclusively is that they
- may not produce the most efficient code. For example, if you have an
- otherwise large-model program with one assumed-size array that may exceed
- 64K, it is to your advantage to declare the single large array with the HUGE
- attribute. Switching to the huge model forces the compiler to consider all
- assumed- and adjustable-size arrays to be huge.
-
- Sections 2.4.1-2.4.3 describe ways to adjust allocation for one or more
- items without changing the entire memory model. The methods described in
- these sections give you greater control over the program's structure and
- performance. However, to understand the effects of using the options and
- attributes described in these sections and to use them safely, you need a
- thorough understanding of FORTRAN memory models and the 8086 architecture.
-
-
- 2.4.1 Using Standard Memory Models
-
- The /AL, /AH, or /AM option selects a memory model. You can use only one
- memory-model option on the FL command line. The option applies to all source
- files on the command line and has no effect on object files given on the
- command line.
-
- Options Model Selected
-
- /AL Large model (default; corresponds
- to the default library generated
- by SETUP)
-
- /AH Huge model
-
- /AM Medium model
-
- If you compile separate source files of a program at different times, you
- must specify the same memory model for all of them.
-
- The following discussion assumes the standard DOS library naming
- conventions. If you use the OS/2 dual-mode command-line options /Lp, /Lr, or
- /Lc, then the naming conventions appropriate to OS/2 dual-modes apply. (See
- Section 3.4, "Understanding Multitasking, Threads, and Dynamic-Link
- Libraries," for more information on OS/2 library names.)
-
-
- 2.4.1.1 Large Model (/AL)
-
- The /AL option tells the compiler to use the large memory model. The large
- memory model is the default, so you do not have to give this option
- explicitly. The large-model option allows the compiler to create multiple
- segments as needed for both code and data.
-
- The default for large-model programs is that both code and data items are
- accessed with far addresses. You override the default with the NEAR or HUGE
- attribute for data and the NEAR attribute for code.
-
- The /AL option causes the name of the large-model, standard FORTRAN
- library──LLIBFORE.LIB, LLIBFOR7.LIB, or LLIBFORA.LIB, depending on the /FP
- option you specified on the FL command line──to be placed in each object
- file created. This allows the linker to use the required library
- automatically, provided that the library exists (that is, you built it using
- SETUP).
-
-
- 2.4.1.2 Huge Model (/AH)
-
- The /AH option tells the compiler to use the huge memory model.
-
- The huge model differs from the large model only in the treatment of
- adjustable- and assumed-size arrays. With the huge model, the compiler
- assumes that such arrays are larger than 64K and generates huge addresses to
- access them; in the large models, the compiler assumes that such arrays are
- smaller than 64K unless they are explicitly declared with the HUGE
- attribute.
-
- These huge addresses make huge models less efficient than large models.
- How-ever, the huge model is useful when you want most or all adjustable-size
- and assumed-size arrays in the program to handle arrays larger than 64K
- correctly.
-
- When using the huge model, you can use the NEAR or FAR attribute with any
- formal array argument whose actual size is always smaller than 64K. This
- attribute tells the compiler to generate near or far addresses for the
- array; these addresses are more efficient than huge addresses. (See Section
- 2.4.2 of this manual and Chapter 1 of the Microsoft FORTRAN Reference for
- more information about the FAR and NEAR attributes, respectively.)
-
- As an alternative to using the huge model, you can use the large model,
- specifying the HUGE attribute for any adjustable-size or assumed-size array
- whose actual size may exceed 64K. (See Section 2.4.2 of this manual and
- Chapter 1 of the Microsoft FORTRAN Reference for more information on the
- HUGE attribute.)
-
- The same libraries are used for huge model as for large model, so the /AH
- option places the name of the appropriate large-model FORTRAN library (that
- is, LLIBFORE.LIB, LLIBFOR7.LIB, or LLIBFORA.LIB) in each object file.
-
-
- 2.4.1.3 Medium Model (/AM)
-
- The /AM option tells the compiler to use the medium memory model.
-
- The medium model differs from the large model in two respects: common blocks
- are allocated differently, and arguments to subprograms are passed
- differently.
-
- In medium models, blank common blocks not explicitly declared with the FAR
- or HUGE attribute──and named common blocks that are 64K or smaller──are
- placed in the default data segment. This allocation method allows the
- compiler to generate near addresses to access these common blocks. As a
- result, medium-model programs are usually more efficient in terms of speed
- and space than large- and huge-model programs. Common blocks larger than 64K
- are placed outside the default data segment and must be accessed with huge
- addresses.
-
- The argument-passing convention used by the medium model is also smaller and
- faster than in the large and huge models. In the medium model, the compiler
- passes actual arguments to subprograms using near addresses (instead of the
- far addresses used in large and huge models). This is possible because the
- compiler assumes that all data reside in the default data segment. If you
- want to pass data from outside the default data segment to a subprogram in
- the medium model, you must declare the corresponding formal argument in the
- subprogram with the FAR or HUGE attribute.
-
- Even if you cannot use the medium model for the program, you can force the
- compiler to use more efficient near addresses for passing arguments by
- declaring formal arguments with the NEAR attribute. You must be sure,
- however, that the actual arguments to be passed to the near formal arguments
- are located in the default data segment.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- Input and output (I/O) on far and huge items are not allowed in the
- medium model. How-ever, you can copy these items to a temporary location
- in the default data segment to perform I/O on them.
- ───────────────────────────────────────────────────────────────────────────
-
- The size of the default data segment cannot exceed 64K, and contains the
- stack and variables, in addition to common blocks. This restricts the
- practical size of the common blocks to less than 64K in order to remain
- within the segment boundaries. (See Section 2.3.2.1 for a description of
- the contents of the default data segment.)
-
- In practice, few FORTRAN programs can meet this restriction. You may still
- be able to use the medium model, however, by specifying the FAR and HUGE
- attributes in the program. For example, if the program contains large,
- infrequently accessed common blocks, you can use the FAR or HUGE attribute
- to move these blocks out of the default data segment. Smaller common blocks
- that are accessed more frequently can remain in the default data segment.
-
- You can also use the FAR and HUGE attributes to move other large data items,
- such as arrays, out of the default data segment. This creates more room in
- the segment for common blocks.
-
- As an alternative to using the medium memory model, you can use the NEAR
- attribute with specific common blocks to cause them to be placed in the
- default data segment. This improves program efficiency when you have one or
- more small, heavily used common blocks.
-
- See Section 2.4.2 of this manual and Chapter 1 of the Microsoft FORTRAN
- Reference for more information about the FAR, HUGE, and NEAR attributes.
-
- The name of the appropriate medium-model library──MLIBFORE.LIB,
- MLIBFOR7.LIB, or MLIBFORA.LIB, depending on the /FP option you specified on
- the FL command line──is placed in each object file created, provided the
- library exists (that is, you built it using SETUP).
-
-
- 2.4.2 The NEAR, FAR, and HUGE Attributes
-
- The NEAR, FAR, and HUGE attributes are keywords used in a FORTRAN program to
- override default-addressing conventions. Section 1.6 of the Microsoft
- FORTRAN Reference describes the syntax of these attributes and outlines
- restrictions on their use. This section describes the effects of these
- attributes on code and data items in the three FORTRAN memory models.
-
- The NEAR, FAR, and HUGE attributes give you more flexibility than selecting
- one of the standard memory models. For example, you may be able to avoid
- switching from the large to the huge memory model if you use the HUGE
- attribute on any adjustable- or assumed-size arrays that may exceed 64K. On
- the other hand, even if the program requires the huge model, you can improve
- program efficiency by identifying small, frequently accessed items that
- could benefit from being placed in the default data segment.
-
- The FAR attribute is also useful for programs that have more data than can
- fit in the default data segment. You can declare less frequently accessed
- items with the FAR attribute in order to move them out of the default data
- segment, which leaves room for the more heavily used items. You can also use
- the /Gt option, described in Section 2.4.5.1, to move some data items out
- of the default data segment.
-
- Keep in mind, however, that the NEAR, FAR, and HUGE attributes are
- extensions to the FORTRAN language. They are meaningful only on processors,
- such as the 8086, which have a segmented architecture. If portable code is a
- high priority, do not use these attributes. The standard memory-model
- options, along with the /Gt option, allow you to alter the memory model in a
- portable way; since these options are given at compile time, they do not
- affect the source code.
-
- The discussion of each memory model in the preceding sections suggests
- strategies for using the NEAR, FAR, and HUGE attributes with each model.
- Tables 2.2 and 2.3 summarize the effects of each attribute on items in each
- of the three standard memory models.
-
- Table 2.2 Effects of the NEAR Attribute
-
- Large Huge
- Item Memory Model Memory Model
-
- Variables and No effect for items Same as large model
- fixed-size arrays smaller than data
- threshold value.
- Arrays larger than
- threshold value but
- smaller than 64K are
- placed in default data
- segment.
-
- Formal arguments Actual arguments are Same as large model
- passed with near
- addresses and must be
- in default data
- segment.
-
- Common blocks Placed in default data Same as large model
- segment; near
- addresses
-
- Subprograms Near calls Near calls
-
- Assumed-size and Actual arguments are Same as large model
- adjustable-size passed with near
- arrays addresses and must be
- in default data
- segment.
- ───────────────────────────────────────────────────────────────────────────
-
-
- Table 2.3 Effects of the FAR and HUGE Attributes
-
- Large Huge
- Item Memory Model Memory Model
-
- Variables and If variable or array Same as large model
- fixed-size arrays is smaller than 64K,
- it is moved out of the
- default data segment
- and accessed with far
- addresses. If array is
- larger than 64K, the
- FAR or HUGE attribute
- has no effect and huge
- addresses are
- generated.
-
- Formal arguments FAR has no effect. If If FAR is used, far
- HUGE is applied to an addresses are gen-
- array, huge addresses erated instead of huge
- are generated. addresses. HUGE has
- no effect.
-
- Common blocks No effect No effect
-
-
-
-
-
-
-
-
-
-
- Subprograms No effect No effect
-
- Assumed-size, FAR has no effect. If FAR is used, far
- allocatable, and Huge addresses are addresses are gen-
- adjustable-size generated with HUGE erated instead of huge
- arrays attribute. addresses. HUGE has
- no effect.
- ───────────────────────────────────────────────────────────────────────────
-
-
- 2.4.3 The $LARGE and $NOTLARGE Metacommands
-
- The $LARGE and $NOTLARGE metacommands are related to the NEAR, FAR, and HUGE
- attributes, although their meanings are slightly different. Use of the
- $LARGE and $NOTLARGE metacommands is no longer recommended; the attributes
- are preferred.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- The term "large" can be confusing since it is used both for the $LARGE
- metacommand and for the large memory model. The $LARGE metacommand is not
- related to the large memory model; instead, the size defined by the
- $LARGE metacommand corresponds to the huge memory model (for formal
- arguments to subprograms) or the HUGE attribute (for fixed-size arrays).
- The $LARGE and $NOTLARGE metacommands are retained for compatibility with
- previous versions of FORTRAN.
- ───────────────────────────────────────────────────────────────────────────
-
- Fixed-size arrays declared under the $LARGE metacommand are treated the same
- as arrays declared with the HUGE attribute: arrays are placed outside the
- default data segment and must be accessed with far addresses for arrays 64K
- or smaller or with huge addresses for arrays larger than 64K. In the huge
- memory model, fixed-size arrays can be accessed with near addresses if they
- are smaller than a segment and smaller than the specified threshold value.
- In the medium and large memory models, declaring an array with the $NOTLARGE
- metacommand (either explicitly or by default) has no effect on the array's
- allocation. This is also true for fixed-size arrays in the huge model.
-
-
- 2.4.4 Using Library Routines with Different Memory Models
-
- The standard libraries built by SETUP are designed to correspond to the
- three memory models. The libraries impose these restrictions on FORTRAN
- programs:
-
- ■ Arrays containing format specifiers cannot be declared with a HUGE
- attribute, specified in a $LARGE metacommand, or span more than one
- segment, in any memory model.
-
- ■ Huge arrays cannot be used as internal files in any memory model.
-
- ■ In medium-model programs, all items involved in I/O operations must be
- near, including items in I/O lists, format specifications, and internal
- files.
-
- ■ In medium-model programs, far format specifiers are illegal.
-
-
- 2.4.5 Compiler Options Affecting Memory Usage
-
- Some FL command-line options──/Gt, /NT, and /ND──tell the compiler to change
- the manner in which it allocates memory. These are discussed briefly below.
- (Chapter 7 of the Microsoft FORTRAN Reference, "The FL Command,"describes
- these compiler options in detail.)
-
-
- 2.4.5.1 Data Threshold Option (/Gt)
-
- The /Gt option sets the data threshold. The "data threshold" is a cutoff
- value the compiler uses in allocating data. In the large and huge models,
- each array or variable larger than or the same size as the assigned
- threshold value──but smaller than 64K──is stored in a new data segment
- outside the default data segment and accessed with a far address.
-
- Decreasing the threshold value is useful when you want to move data out of
- the default data segment without declaring them with the FAR attribute.
- Increasing the threshold value allows you to store arrays larger than 32,767
- bytes (the default value) in the default data segment, provided you have
- room for them. You can also accomplish this by declaring such arrays with
- the NEAR attribute.
-
-
- 2.4.5.2 Naming Segments Option (/NT)
-
- The /NT option lets you override the default-naming conventions used by the
- FORTRAN compiler and supply your own name for text segments.
-
- "Text" is simply another term for "code"; therefore, a text segment is a
- code segment. Segments with the same name are loaded into the same physical
- segment in memory. For example, you can use the /NT option to give two
- different modules the same text-segment name, thus ensuring that they will
- be loaded into the same segment in memory. This is useful when you want to
- use the NEAR attribute with a subprogram.
-
- In all three of the FORTRAN memory models, the compiler places the code from
- each module in a separate segment with a distinct name, which is formed by
- using the module base name along with the suffix "_TEXT." See Section
- 2.3.3, "Limits on Code Size," for more information on code size
- restrictions.
-
-
- 2.4.5.3 Naming Data Option (/ND)
-
- The /ND option lets you override the default-naming conventions used by the
- Microsoft FORTRAN Compiler and supply your own name for data segments. The
- default data segment is named "_DATA." The compiler places data stored
- outside the default data segment in private segments with unique names.
- These items are: huge arrays; arrays larger than the threshold value; items
- declared with the FAR or HUGE attribute; and common blocks in large and huge
- models. (See Section 2.2.1, "Code and Data Segments," for more information
- on the names.)
-
- The /ND option places data from the module in a uniquely named data segment.
- When execution transfers to that module, the compiler loads the DS register
- with the base address of the named data segment; when execution leaves the
- module, the compiler restores DS to its previous value (usually DGROUP). As
- a result, during execution in that module, the compiler can use near
- addresses for calls to data residing in the named segment. This technique
- particularly improves the performance of routines that repeatedly access
- data.
-
-
- Chapter 3 FORTRAN Programming under OS/2
- ───────────────────────────────────────────────────────────────────────────
-
- This chapter presents an overview of the steps required to compile and link
- FORTRAN programs within the OS/2 environment and discusses some important
- programming strategies for use with OS/2. The chapter assumes you are
- already familiar with OS/2 programming. Microsoft FORTRAN now supports
- multithread and dynamic-link-library programming under OS/2, as described in
- this chapter. The Microsoft CodeView and Utilities User's Guide, included
- with this release, contains a guide to using the Microsoft CodeView(R)
- debugger in a multithread or dynamic-link-library environment.
-
- Section 3.10, "Additional Information," refers you to other publications
- that can deepen your understanding of OS/2. These publications address
- concerns particular to multithread programming and provide more com-plete
- discussions of dynamic-link libraries.
-
-
- 3.1 Compiling and Linking under OS/2
-
- If you have set up FORTRAN for programming only under OS/2, you do not need
- to use any additional options to compile and link with the FL command. Use
- FL just as you would under DOS. If you wish to alter your current library
- and directory arrangement, you can rerun the SETUP program and create any
- new arrangement you want.
-
- In discussions throughout this chapter, the run-time libraries are referred
- to with the general single-mode naming convention, xLIBFORy.LIB (where x
- equals L or M and refers to a large or medium memory model, and y equals 7,
- E, or A and refers to the math coprocessor, emulator, or alternate math
- library). However, when the discussion calls for dual-mode development (that
- is, when you want to build libraries for both OS/2 protected-mode and
- real-mode development), then a new naming convention is used. It will
- distinguish between versions of the libraries that use the same memory model
- and floating-point options, but operate under real mode or protected mode.
- Those libraries follow the naming convention xLIBFy«R|P».LIB, with R used
- for real mode and P indicating protected mode.
-
- When you set up FORTRAN to compile under both real and protected modes, you
- must use one of the library options when compiling and linking with FL.
- Specifying the /Lr option selects the real-mode libraries so your program
- runs under DOS or in the OS/2 compatibility box. The /Lp option selects the
- OS/2 protected mode versions of the libraries and creates a program that
- runs only under OS/2 in protected mode. For example, to compile BESSEL.FOR
- for OS/2 protected mode, you would use the following command:
-
- FL /Lp BESSEL.FOR
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- You must use the OS/2 (protected-mode) version of the CodeView debugger,
- CVP.EXE, to debug protected-mode programs.
- ───────────────────────────────────────────────────────────────────────────
-
-
- 3.2 Running under Both DOS and OS/2
-
- You can create programs that run under DOS or in real and protected modes
- under OS/2 by linking your program for protected mode and "binding" it.
- Binding resolves references to OS/2 dynamic-link libraries so the program
- runs in both modes and under either operating system.
-
- To bind a program, link it with the protected-mode library. Then, use the
- BIND utility. For example, the following commands compile, link, and bind
- the file BESSEL.FOR:
-
- FL /Lp BESSEL.FOR
- BIND BESSEL APILMR.OBJ C:\LIB\DOSCALLS.LIB C:\LIB\API.LIB
-
- You must include the full path to the DOSCALLS.LIB and API.LIB files in
- the command line. Alternately, you can compile, link, and bind the program
- automatically by specifying the /Fb option with the FL command. For example,
-
- FL /Lp /Fb BESSEL.FOR
-
- will automatically invoke the BIND utility for you.
-
- The AMPILMR.OBJ file is always required if you are using the large memory
- model. It also is required in the medium model if you use the ALLOCATE
- statement or the near and far heap in mixed-language programs. Although it
- is not explicitly required in other situtations, it is recommended that you
- link with AMPILMR.OBJ.
-
- If you write your own routines that use OS/2 system functions and you want
- to bind the resulting program, you must use only a subset of the Application
- Program Interface (API) functions, known as "Family API functions." See the
- Microsoft OS/2 Programmer's Reference for a list of Family API functions.
-
- See the Microsoft CodeView and Utilities User's Guide for complete
- information about the BIND command.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- Bound programs cannot be debugged using the CodeView debugger. However,
- you can use the OS/2 version of CodeView, CVP.EXE, to debug a
- protected-mode version of the program.
- ───────────────────────────────────────────────────────────────────────────
-
-
- 3.3 Interfacing FORTRAN with OS/2
-
- To facilitate access to OS/2 routines, this release of Microsoft FORTRAN
- provides include files that contain the FORTRAN interfaces and declarations
- of all the standard OS/2 system routines. The interface files (the file
- names ending with .FI) must be included as the first executable statement in
- a source file that references OS/2 routines. However, the declaration files
- (files ending with .FD) must appear at the beginning of each subprogram that
- calls OS/2 routines; they declare the structures and symbolic constants
- needed by the same OS/2 routines.
-
- To reduce compilation time and memory requirements, include only those
- particular parts of the file that you want. To do so, you need to set
- conditional-compilation flags when referencing the include files. See
- BSE.FI, BSE.FD, OS2.FI, OS2.FD, PM.FI, and PM.FD on the distribution disks
- for specific details. For information on the base OS/2 routines (BSE files),
- see the Microsoft Operating System/2 Programmer's Toolkit, Programmer's
- Reference. For information on the Presentation Manager routines (PM files),
- see the Microsoft Operating System/2 Programmer's Toolkit, Presentation
- Manager Reference, Volume 1.
-
-
- 3.4 Understanding Multitasking, Threads, and Dynamic-Link Libraries
-
- Special library support for OS/2 programming is provided with Microsoft
- FORTRAN Version 5.0. This version provides libraries for creating types of
- programs not previously supported, including multiple-thread programs and
- dynamically linked libraries.
-
- Sections 3.4.1-3.4.2 briefly describe multitasking and dynamic-link
- libraries; they are aspects of programming that OS/2 supports but MS-DOS
- does not.
-
-
- 3.4.1 Multitasking and Threads
-
- "Multitasking" occurs when multiple, mutually independent programs share the
- same central processing unit (CPU) simultaneously. This term does not imply,
- however, that more than one person is interacting with the processor.
-
- OS/2 performs the scheduling and allocation of real hardware resources to
- "threads," which are paths of execution belonging to one or more "processes"
- (pieces of program code).
-
- A thread can share the code and data segments of a process with other
- threads in the same process, but it has its own stack, unique register
- values, and current instruction address. The system grants processor time to
- each thread, so that all threads of a process execute simultaneously. A
- thread is also the smallest unit of execution that OS/2 can schedule.
-
- The OS/2 environment offers the following types of multitasking:
-
- Type of
- Multitasking Description
-
- Screen group One or more processes that share
- a logical screen and keyboard;
- highest-level multitasking
- element. A word processor and a
- data base operating
- simultaneously under OS/2 will
- normally run in two different
- screen groups.
-
- Process Part of an executing program that
- is the unit of ownership for
- resources such as memory, open
- files, semaphores (see Section
- 3.6.1 below), and one or more
- threads.
-
- Thread Execution path within a process;
- smallest multitasking unit
- managed by OS/2.
-
- A sample program supplied with this release highlights the use of threads.
- The program, FMHELLO.FOR, is a multithread version of the classic "Hello
- world" program.
-
- A pictorial representation of screen groups, processes, and threads is shown
- in Figure 3.1.
-
- In the figure above, each screen group consists of two processes. Each
- process can be composed of several threads.
-
- In any process, Thread 1 is the main thread. All threads in a process act
- independently. Unless you take steps to make one visible to another, each
- thread executes completely independently of another thread. They do,
- however, share the same variables and resources.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- It is not recommended that you use mixed-language programming in
- conjunction with multithread programs or dynamic-link libraries.
- ───────────────────────────────────────────────────────────────────────────
-
-
- 3.4.2 Dynamic-Link Libraries
-
- A "dynamic-link library" is a set of routines linked to a program either at
- load time or at run time, rather than at the time of compilation. OS/2
- supports dynamic-link libraries; MS-DOS does not. The easiest way to
- understand dynamic linking is to contrast it with the more familiar method
- of static linking.
-
- Static linking involves the following steps:
-
- 1. Write and compile a program that uses a standard FORTRAN I/O statement,
- such as WRITE. This produces an object file that contains a reference
- to the external function in the standard FORTRAN library that supports
- this high-level statement.
-
- 2. Link the object file with the library file containing the external
- function. This linking step combines the two files by including the
- code for the referenced function into the final executable file. In
- other words, the external reference is resolved at link time.
-
- 3. Run the executable file produced in step 2. This executable file is
- totally self- contained because it contains the code for the external
- function.
-
- Static linking is useful, but it has some disadvantages. For example, the
- final exe-cutable code cannot be upgraded or changed without relinking with
- the main program's object files. When there is a new release of a commercial
- program, the entire executable file must be replaced with a new version.
-
- Another disadvantage of static linking is that common sets of code cannot be
- shared. Any and all executable files that use the WRITE statement must
- explicitly link with the necessary routine. Thus, the code needed to
- support WRITE may be duplicated in many different executable files on a disk
- or in memory.
-
- Executable files that take advantage of dynamic-link libraries are smaller
- than statically linked files because they do not contain the code for
- external functions. They can also be upgraded by supplying new versions of
- the dynamic-link libraries. No relinking of the executable file is required.
-
- A less obvious but very important advantage of using dynamic-link libraries
- is that executable files may share code. A common set of routines can be
- placed in a dynamic-link library and accessed by any number of executable
- files.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- The OS/2 operating system uses dynamic-link libraries extensively. All of
- the OS/2 system functions are presented as external procedures that a
- user program can call.
- ───────────────────────────────────────────────────────────────────────────
-
- Dynamic linking involves the following basic steps:
-
- 1. Write and compile a program that references an external function, just
- as you would for static linking.
-
- 2. Create a special .DEF (definitions) file that specifies which functions
- the main program will import from the dynamic-link library.
-
- 3. Link the main program with the appropriate "imports library." An
- imports library is a file that contains a reference to the external
- function in the dynamic-link library. This file does not contain code
- from the external function.
-
- 4. DOSCALLS.LIB is an example of an imports library; if you did not link
- with DOSCALLS.LIB, the .DEF file would have to specify each OS/2 API
- function used in your program.
-
- You must describe the functions your program imports from dynamic-link
- libraries either in the .DEF file or in an imports library. The
- resulting file, after linking, does not contain any code from the
- external dynamic-link library.
-
- 5. Create a dynamic-link library that contains the code referenced in the
- main program.
-
- 6. Execute the program created in step 3. When this executable file is
- run, OS/2 loads the code and discovers the special reference to the
- dynamic-link library. For each external dynamic-link-library reference,
- OS/2 searches the dynamic-link-library directory and resolves the
- external reference at load time.
-
-
- 3.5 Multithread Programs
-
- The simplest multithread program is an independent self-contained program
- created by the static linking method. The following sections describe the
- support needed by multithread processes and the special software routines
- used in han-dling them.
-
-
- 3.5.1 Library Support for Multithread Programs
-
- This section discusses the multithread library LLIBFMT.LIB. See Section
- 3.7.4, "Creating a Multithread Dynamic-Link Library," for a discussion of
- FDLLOBJS.LIB.
-
- LLIBFMT.LIB is a statically linked, multithread, large-model FORTRAN
- li-brary. Use this library to construct statically linked executable files
- that support multiple threads of execution. A multithread program created
- with this library is a large model program by default, but can be adjusted
- to use the huge model. Note that LLIBFMT.LIB does not support the medium
- memory model.
-
- LLIBFMT.LIB is used to create a program that is entirely self-contained and
- that does not share FORTRAN run-time code or data with any other programs or
- dynamic-link libraries. Note also that LLIBFMT.LIB uses the emulator math
- package.
-
- A multithread program that uses this library must be linked only with the
- files LLIBFMT.LIB and DOSCALLS.LIB. No other FORTRAN run-time libraries
- should be used in linking. When you build object files with LLIBFMT.LIB, use
- the /MT command-line option to ensure that the code links with the correct
- library. For a complete description of the /MT option, see Chapter 7 of the
- Microsoft FORTRAN Reference.
-
-
- 3.5.2 Thread Control Routines
-
- The FORTRAN run-time library allows thread creation through the BEGINTHREAD
- function. Thread termination should be performed by calling the FORTRAN
- run-time thread-termination function ENDTHREAD. Threads terminate
- automatically when they complete execution. The function THREADID is used
- in the multithread environment; it returns an INTEGER*2 representing the
- identification number used by OS/2 to manage that thread within a process.
-
- ───────────────────────────────────────────────────────────────────────────
- WARNING
- The OS/2 Application Program Interface (API) call DosCreateThread
- should not be used with FORTRAN. If the low-level API calls
- DosCreateThread and DosExit are used, the results are unpredictable.
- ───────────────────────────────────────────────────────────────────────────
-
- The next three sections provide the specifications for the FORTRAN run-time
- thread-management functions. In each of these sections, you will find:
-
- ■ A description of the routine, including any return values
-
- ■ An example showing the INTERFACE statement for the function and the
- order and type of any arguments
-
- ■ A discussion of any arguments
-
- ■ Notes or comments on the use of the routine
-
-
- 3.5.2.1 The BEGINTHREAD Function
-
- The BEGINTHREAD function creates a new thread. Multithread programs must
- call BEGINTHREAD repeatedly, once for every thread created.
-
- If BEGINTHREAD successfully creates a new thread, it returns an
- identification number for the new thread. If BEGINTHREAD fails, a run-time
- error results. Such an error can occur if you specify an odd address stack;
- specify an odd or zero-length stack; attempt to create more threads than the
- run-time library can support (32); or experience a low-level system error.
- The example below shows the required interface to BEGINTHREAD and
- demonstrates how it can be used.
-
- Example
-
- INTERFACE TO INTEGER*2 FUNCTION
- + BEGINTHREAD(RTN,STK,SIZE,ARG)
- INTEGER*4 RTN [VALUE] ! pass LOCFAR(thread_routine)
- INTEGER*1 STK(*)
- INTEGER*4 SIZE
- INTEGER*4 ARG
- END
-
- C Example call to BEGINTHREAD
- EXTERNAL CHILD
- INTEGER*1 STACK(2048)
- INTEGER*2 TID
- TID = BEGINTHREAD (LOCFAR(CHILD), STACK(1), 2048, 0)
- .
- .
- .
- END
-
- The arguments used in the BEGINTHREAD function are discussed below:
-
- Argument Description
-
- RTN The far address of the routine
- you want the new thread to
- execute. For BEGINTHREAD to work
- properly, you must pass it the
- number returned by the LOC or
- LOCFAR function by value. The
- thread terminates automatically
- when it returns from the routine
- supplied by the RTN argument.
- You also can terminate the thread
- by calling ENDTHREAD within the
- far routine.
-
- STK The memory address of an area to
- be used as the new thread's
- stack. The address must be on a
- word boundary (an even number)
- and must specify an area at least
- as long as the SIZE argument.
- Usually the address refers to
- either a static array or an area
- created by the ALLOCATE
- statement.
-
- SIZE The size of the thread's stack,
- in bytes. The SIZE argument must
- be even, positive, and non-zero.
-
- ARG A parameter to pass to the newly
- created thread, passed by far
- reference. Typically, ARG is the
- address of a data item, which may
- be a structure containing
- multiple data fields. If you do
- not need to pass an argument to
- the child thread, set ARG equal
- to zero.
-
- Note that in the sample interface
- above, ARG is declared as
- INTEGER*4. In general, you can
- modify the INTERFACE statement to
- reflect the type of the actual
- argument you pass. This
- modification avoids type mismatch
- warnings from the compiler.
-
- If you pass different types of
- arguments to more than one
- thread──which all use the same
- interface──the compiler will warn
- you with a recoverable error
- message.
-
- See Appendix D in the Microsoft
- FORTRAN Reference for more
- information on these types of
- errors. You can either ignore the
- messages or move each BEGINTHREAD
- call to a separate module with a
- custom interface.
-
- When a thread is created, the system calls the function supplied by the
- argument RTN. The new thread can access all files and resources owned by the
- parent process.
-
- If you write multiple-thread programs that make FORTRAN run-time calls from
- child threads, take care to allocate adequate stack space. To be safe,
- allocate at least 2K bytes for each thread's stack. In general, you should
- have 2K of stack space free when calling any API routine.
-
-
- 3.5.2.2 The ENDTHREAD Subroutine
-
- The subroutine ENDTHREAD terminates a thread created by the BEGINTHREAD
- function. ENDTHREAD does not require any arguments. The example below shows
- the interface and a typical call to ENDTHREAD.
-
-
- Example
-
- INTERFACE TO SUBROUTINE ENDTHREAD()
- END
-
- C SAMPLE USAGE OF ENDTHREAD
- IF (i.EQ.0)
- CALL ENDTHREAD()
- .
- .
- .
-
- Threads terminate automatically when they finish executing. However, the
- subroutine ENDTHREAD lets a thread conditionally terminate itself before it
- com-pletes its normal execution path.
-
-
- 3.5.2.3 The THREADID Function
-
- The function THREADID returns to a thread its own unique identification
- number within a process. THREADID does not take any arguments. The example
- below shows the required interface to THREADID and demonstrates how it can
- be used.
-
- Example
-
- INTERFACE TO INTEGER*2 FUNCTION THREADID()
- END
- .
- .
- .
- RESULT(THREADID())=.TRUE.
- RETURN
- END
-
- Use THREADID when a thread needs to know its own identification number. For
- example, it could serve as an index to a global array that manages thread
- status.
-
-
- 3.6 A Multithread FORTRAN Program
-
- The sections below describe the steps to compile, link, and run a
- multithread version of the classic "Hello world" program. The source code
- for this program is included on the distribution diskettes as FMHELLO.FOR.
-
- The FORTRAN multithread "Hello world" program FMHELLO brings up one thread
- for each command-line argument. Each thread will print "Hello world from
- thread n!" the number of times specified in the corresponding argument. The
- multithread library supports a maximum of 32 threads. For FMHELLO, since the
- main body is itself a thread, the maximum number of child threads is 31.
-
-
- 3.6.1 Sample Program Operation
-
- To try the multithread implementation of "Hello world," type
-
- FMHELLO arg1 «arg2...»
-
- For example,
-
- FMHELLO 2 4 6
-
- brings up 3 threads; the first thread says "hello" two times, the second
- thread says "hello" four times, and the third thread says "hello" six times.
-
- In operation, FMHELLO follows these steps:
-
- 1. Brings up the requested number of threads with BEGINTHREAD
- 2. Waits until all threads have been brought up
- 3. Begins multithread execution and waits for completion
-
- The synchronization in step 2 keeps the threads from all starting as the
- same thread (with the same thread ID number). Multiple threads with the same
- ID number can occur if the first spawned thread completes execution before
- the next request to create a thread is acted upon. The amount of time
- allotted to any individual thread is actually much larger than the execution
- time spent in each thread.
-
- An alternative method of thread synchronization is to use semaphores. A
- "semaphore" is a software flag used by OS/2 to precisely coordinate the
- activities of two or more threads. Microsoft FORTRAN does not directly
- support semaphores. If you wish, you can access semaphores through the OS/2
- API calls. See the OS/2 documentation (such as Microsoft Operating System /2
- Programmer's Reference) for a complete discussion of the required functions.
-
- In order to synchronize its threads, FMHELLO uses the DosSleep function,
- which causes a thread to periodically "wake up." During these wake-ups, the
- thread can check for a software flag. Polling a flag using DosSleep has some
- drawbacks, however, because
-
- ■ The thread wakes up unnecessarily and performs some processing only to
- find it has to go to sleep again.
-
- ■ The thread oversleeps (that is, the event it is waiting for has already
- occurred, but the thread sleeps until the sleep request expires).
-
- Often, your program will have to wait for a process to complete. If you do
- not know exactly how long that process will take, it is better to make the
- thread wait for a semaphore rather than use DosSleep.
-
- In the case of FMHELLO, however, the use of DosSleep is more appropriate
- because
-
- ■ DosSleep is easily understood and clearly functional.
-
- ■ The program is not particularly time dependent, so the above
- disadvantages will not adversely affect it. Also, we know that this is
- a one-time event and that the main code "quickly" wakes up the
- child-code portion of the program. That is, the DosSleep code path
- occurs once at child start-up time and is never entered again during
- child execution.
-
- Also, the sleep time is short and predetermined. The parent code sets the
- flag as soon as all of the threads have been started. In other words, there
- is no chance for the parent code to do other things and leave the thread
- waiting for DosSleep for long periods of time.
-
-
- 3.6.2 Compiling and Linking the Sample Multithread Program
-
- The program FMHELLO.FOR is a statically linked multithread program. The
- steps in compiling and linking this program are as follows:
-
- 1. Ensure that the files LLIBFMT.LIB and DOSCALLS.LIB are available.
-
- Either place them in the current working directory or in a directory
- specified in the LIB environment variable.
-
- The file LLIBFMT.LIB takes the place of the regular run-time-library
- file used in linking. See Section 3.5.1 for more information on
- LLIBFMT.LIB.
-
- The file DOSCALLS.LIB provides support for any OS/2 calls made in the
- multithread program. In this example, the OS/2 call DosSleep is used.
- In addition, the LLIBFMT.LIB file refers to DOSCALLS.LIB in the form of
- OS/2 calls.
-
- 2. Compile and link the program with the following conditions set:
-
- ■ Large code address size
- ■ Far or huge data address size
- ■ Segment setup of SS not equal to DS; DS fixed
-
- The first two conditions are specified by either the large (the
- default) or huge memory models. The last condition is specified by
- using the /MT option with the FL command. (See Section 3.8.1 for a
- complete description of the /MT option.) The complete FL invocation is
- shown below:
-
- FL /MT FMHELLO.FOR
-
- When compiling multithread programs, you can specify any of the
- floating-point options except /FPa (the alternate math package). To
- maximize efficiency, however, use the default floating-point option
- (/FPi87). The library LLIBFMT.LIB includes the emulator math package,
- but will use a math coprocessor if one is present. The other
- floating-point options (except /FPa) will also work, but cause their
- respective versions of the default library name to be placed in the
- object files. These differences are only a concern if you link as a
- separate step and use the /NOD: option to suppress default library
- searches.
-
- 3. Link the resulting object file with LLIBFMT.LIB and DOSCALLS.LIB only.
- (The FL driver automatically takes care of this step.)
-
- Note that the default memory model (large) implies a far data address
- size. You can also specify huge data address with the /AH command-line
- option, but the linker will use the same library.
-
- 4. Compile and link your programs separately, invoking the linker as
- follows to link the object file with LLIBFMT.LIB:
-
- link FMHELLO,,,/NOD:LLIBFOR7 LLIBFMT.LIB;
-
- LLIBFMT.LIB contains search directives for DOSCALLS.LIB, so you do not
- need to reference it explicitly. The /NOD: option turns off the default
- library search; you may need to specify a library other than LLIBFOR7
- if you specified a floating-point option other than the default.
-
- 5. Run the program under OS/2.
-
-
- 3.6.3 Troubleshooting Multithread Programs
-
- Several problems may occur when creating, linking, or executing a
- multithread FORTRAN program. Two of the more common ones are listed below:
-
- Problem Probable Cause
-
- LINK searches for LLIBFOR7.LIB or If you link in a separate step
- LLIBFORE.LIB. and omit the /NOD option from the
- LINK command, the linker searches
- for the default library. The
- default library should not be
- used with multithread programs.
-
- The /NOD: option tells the linker
- to ignore the default library and
- use the specified library instead
- (see also Section 3.6.2). This
- problem may also be avoided by
- compiling with the /Zl option,
- which suppresses
- default-library-search records in
- the object files. However, you
- must then explicitly specify
- LLIBFMT.LIB on the link command
- line.
-
- Protection violation error Many OS/2 programming errors will
- occurs. cause a protection violation. One
- cause of this error is failure to
- specify the condition "SS is not
- equal to DS" in the FL command
- invocation.
-
- Specify the correct conditions
- with the /MT option. Recompile
- the program with /MT. See the
- Microsoft FORTRAN Reference for
- specific FL command information.
- Another common cause of
- protection violations is
- over-addressing a common block or
- array without using the $DEBUG
- metacommand.
-
-
- 3.7 Using FORTRAN Dynamic-Link Libraries
-
- Microsoft FORTRAN 5.0 includes support for dynamic link libraries. You can
- write routines in FORTRAN in such a way that they can be dynamically linked.
- In addition, this release provides an object-file library, FDLLOBJS.LIB,
- that can be used to create a dynamically linked multithread FORTRAN run-time
- library.
-
- Dynamic-link libraries can be debugged with the protected-mode CodeView
- debugger. (See Chapter 12 in the Microsoft CodeView and Utilities User's
- Guide.)
-
-
- 3.7.1 Creating a Dynamic-Link Library
-
- FORTRAN 5.0 allows you to build your own dynamic-link libraries.To create
- such a library, take the following steps:
-
- 1. Write a subroutine as you normally would (in a separate file).
-
- 2. Use the LOADDS attribute on any subroutine name that will be used as an
- entry point to the dynamic-link library.
-
- 3. Build a definitions (.DEF) file that exports the appropriate routine
- names. (That is, build a file that uses the EXPORT module definition
- statement to name the routines you want to include in the library
- available to the calling program.)
-
- 4. Compile and link the routine to build it as a dynamic-link library.
-
- The example in Section 3.7.4 steps through this process in detail. A
- dynamic-link routine written in this way will require a dynamically linked
- FORTRAN run-time library if the routine requires run-time support.
-
-
- 3.7.2 The LOADDS Attribute
-
- You can use this attribute for routines that serve as entry points to your
- own dynamic-link libraries. The LOADDS attribute causes the data segment
- (DS) register to be loaded with the base address of the default data segment
- of the dynamic-link library upon entering the routine named with the
- attribute. The previous DS value is restored when the routine terminates.
-
- You do not need to specify the LOADDS attribute on local routines called
- from within the dynamic-link library. The correct DS register is set up
- during the call to the dynamic-link library provided the LOADDS attribute
- was specified on the entry routine. This attribute must appear with the
- names of routines that act as interfaces to a dynamic-link library.
-
-
- 3.7.3 Multithread Dynamic-Link Libraries: An Overview
-
- The FDLLOBJS.LIB OS/2 support file is an object-file library used to create
- a dynamically linked FORTRAN run-time library. This library is provided as
- an object library with an associated definition file (FDLLOBJS.DEF) that
- defines the entry points into the FORTRAN run-time library. These entry
- points let you choose only those run-time modules that your program requires
- for a particular application. Three additional start-up object modules are
- also required to support dynamic linking in FORTRAN:
-
- Start-up Module Supported files
-
- FRTEXE.OBJ Start-up code for executable
- files
-
- FRTDLL.OBJ Start-up code for user-written
- dynamic-link libraries
-
- FRTLIB.OBJ Start-up code for dynamically
- linked FORTRAN run-time library
-
- A FORTRAN run-time library created with FDLLOBJS.LIB is dynamically linked
- and available to a multithread program and optionally to a group of closely
- associated dynamic-link libraries. User-written dynamic-link libraries that
- require run-time support must use an appropriately created, dynamically
- linked FORTRAN run-time library (see Section 3.7.6).
-
- The close association of the multithread program, the FORTRAN run-time
- library, and a group of dynamic-link libraries is shown in Figure 3.2.
-
- The main program (PROGRAM.EXE) and the two dynamic-link libraries (DLL1.DLL
- and DLL2.DLL) share the FORTRAN run-time data in the file FRTLIB.DLL. Each
- PROG.EXE, DLL1.DLL, and DLL2.DLL file has its own private data segments.
-
- The FORTRAN run-time dynamic-link library is closely tied to the program and
- the other dynamic-link libraries, because it contains global FORTRAN
- run-time data, thread-identification numbers, and FORTRAN run-time routines
- required by the program and other dynamic-link libraries.
-
- If you build a program using the dynamically linked multithread support of
- the FORTRAN run-time library, it can share the FORTRAN run-time library with
- one or more dynamic-link libraries that are closely related. FORTRAN
- run-time global data used to manage I/O are shared.
-
- Threads are managed in a dynamic-link library by the FORTRAN functions
- BEGINTHREAD and ENDTHREAD. See Section 3.5.2 for a description of these
- functions.
-
-
- 3.7.4 Creating a Multithread Dynamic-Link Library
-
- The process of creating a multithread dynamic-link FORTRAN run-time library
- under OS/2 is outlined below. This example of how to create a dynamic-link
- library of the FORTRAN run-time routines is also contained in FDLLOBJS.CMD.
-
- 1. Create a definitions file (.DEF) that specifies the functions in the
- FORTRAN run-time library you want the dynamic-link library to export
- (see Section 3.7.5, below). The file FDLLOBJS.DEF, included with this
- release, is a sample definitions file that includes all of the FORTRAN
- run-time functions currently supported.
-
- 2. Link the special start-up file FRTLIB.OBJ with the files FDLLOBJS.LIB,
- DOSCALLS.LIB, and the definitions file from step 1. This linking
- creates a customized FORTRAN run-time dynamic-link library file. If you
- use the sample file FDLLOBJS.DEF, you'll create a library named
- FRTLIB.DLL. The following files are then linked together:
-
- File Name Description
-
- FRTLIB.OBJ Start-up code for library files
-
- FDLLOBJS.LIB FORTRAN run-time-library objects
-
- DOSCALLS.LIB OS/2 support library
-
- FDLLOBJS.DEF Definition module from step 1
-
- FRTLIB.DLL Output from LINK
-
- To accomplish this, type the command
-
- LINK FRTLIB.OBJ,FRTLIB.DLL,,FDLLOBJS.LI B/NOE,
- FDLLOBJS.DEF
-
-
- 3. Run the Microsoft Import Library Manager (IMPLIB) on the definitions
- file from step 1, and the support file DIFFHLP.DEF supplied with this
- release, to create a customized imports library file containing the
- exported functions. The form of the command is shown below:
-
- IMPLIB FRTLIB.LIB FDLLOBJS.DEF DIFFHLP.DEF
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- The name FRTLIB.DLL is used only as an example. You should use a unique
- name particular to your application. If you do not, you run the risk of
- having a FORTRAN run-time library named FRTLIB.DLL built with any
- customized routines overwritten by another software vendor's dynamic-link
- library.
- ───────────────────────────────────────────────────────────────────────────
-
-
- 3.7.5 Creating a Custom FORTRAN Run-Time Definitions File
-
- The general process described in Section 3.7.4, "Creating a Multithread
- Dynamic-Link Library," can be used to build a dynamic-link FORTRAN run-time
- library which includes only those routines required by a particular
- application (or set of applications). To do this, create a definitions
- (.DEF) file that specifies exactly those routines required by your program.
- You can build a custom definitions file through the following process:
-
- 1. Print a copy of the sample definitions file, FDLLOBJS.DEF. It will act
- as a reference.
-
- 2. Compile your program using the /MD option on the FL command line
- with-out specifying a library. As a result, the linker will list an
- "unresolved external" error for every routine referenced in the
- program. Note the names of each unresolved symbol.
-
- 3. Create a new file as your custom definitions file. Place the names that
- appear in both the linker's unresolved symbols list and in the sample
- definitions file in your new file's EXPORT list. Use the copy of
- FDLLOBJS.DEF as a syntax guideline for your new file.
-
- You can now substitute your custom definitions file in place of the
- file FDLLOBJS.DEF in the instructions listed in steps 2 and 3 in
- Section 3.7.4. Be certain to uniquely name any dynamic-link FORTRAN
- run-time library created this way.
-
-
- 3.7.6 Using a Multithread Dynamic-Link Library
-
- Once you create a FORTRAN run-time multithread dynamic-link library, it can
- be used by a program and the program's associated dynamic-link libraries.
- This release of FORTRAN includes a sample program that calls both a
- user-written dynamic-link library and a customized version of a dynamic-link
- FORTRAN run-time library (such as the one created in Section 3.7.4). The
- sample files FMTMAIN.FOR, FMTMAIN.DEF, FMTDLL.FOR, and FMTDLL.DEF on the
- distribution disks demonstrate dynamic linking.
-
- In order to use a run-time multithread dynamic-link library, follow the
- steps below as an example. The batch file MKFDLL.CMD included in this
- release also shows this process.
-
- 1. Compile and link the main program FMTMAIN.FOR to produce the file
- FMTMAIN.EXE.
-
- Use the FL command
-
- FL /MD FMTMAIN.FOR FRTEXE.OBJ FRTLIB.LIB FMTMAIN.DEF
-
- See Section 3.8.1 for more information on the /MD option. The above
- FL command links the following files:
-
- File Name Description
-
- FMTMAIN.OBJ Output from the compilation of
-
- FRTEXE.OBJ Start-up code for executable
- files
-
- FRTLIB.LIB Customized FORTRAN run-time
- imports library
-
- DOSCALLS.LIB OS/2 support library
-
- FMTMAIN.DEF Definitions (.DEF) file for
- FMTMAIN.FOR
-
- FMTMAIN.EXE Output from LINK
-
- Given the object file FMTMAIN.OBJ compiled with the /MD option, you
- can also invoke the linker separately, with the following command:
-
- LINK FMTMAIN+FRTEXE,,,FRTLIB.LIB,FMTMAI N.DEF
-
- You must explicitly link the special start-up file FRTEXE.OBJ into any
- executable program that requires dynamically linked FORTRAN run-time
- support.
-
- An alternate method to the above process would be to build an imports
- library for FMTDLL.DLL and link FMTMAIN.OBJ with the imports library.
- This method avoids creating a definitions file which imports the
- functions.
-
- 2. Compile and link a dynamic-link-library module (FMTDLL.FOR) to produce
- FMTDLL.DLL. Do this by entering the command
-
- FL /MD /FeFMTDLL.DLL FMTDLL.FOR FRTDLL.OBJ FRTLIB.LIB FMTDLL.DEF
-
- The following files are now linked together:
-
- File Name Description
-
- FMTDLL.OBJ Output from the compilation of
- FMTDLL.FOR
-
- FRTDLL.OBJ Start-up code for
- dynamic-link-library files
-
- FRTLIB.LIB Customized FORTRAN run-time
- imports library
-
- DOSCALLS.LIB OS/2 support library
-
- FMTDLL.DEF Dynamic-link-library definitions
- file
-
- FMTDLL.DLL Output from LINK
-
- The FL command compiles and links the dynamic-link library. The /Fe
- option allows you to rename the output from the linker to the .DLL
- extension.
-
- Given the object file, FMTDLL.OBJ, compiled with /MD, you can also
- invoke the linker separately with the following command:
-
- LINK FMTDLL+FRTDLL,FMTDLL.DLL,,FRTLIB.L IB,FMTDLL.DEF
-
- You must explicitly link the special start-up file FRTDLL.OBJ with any
- user-written dynamic-link library.
-
- FMTDLL.DLL performs I/O functions, requiring run-time support (provided
- by the example file FRTLIB.LIB). If the dynamic-link library does not
- require run-time support, omit this file from the command line.
-
- 3. Place the FMTDLL.DLL file (from step 2) and the FRTLIB.DLL file in a
- directory on your LIB PATH so OS/2 can find it. You can now run the
- program FMTMAIN.EXE under OS/2.
-
-
- 3.7.7 Compiling for Dynamic-Link and Multithread Capabilities
-
- The program FMHELLO discussed in Section 3.6 can also be compiled to use the
- dynamically linked multithread capabilities available with Microsoft FORTRAN
- 5.0. Assuming that the example dynamic-link FORTRAN run-time library is on
- your LIB PATH, compile FMHELLO with the following command:
-
- FL /MD FMHELLO.FOR FRTEXE.OBJ FRTLIB.LIB
-
- The /MD option implies multithread support, so the /MT option is not
- required.
-
-
- 3.7.8 FORTRAN OS/2 Libraries
-
- Table 3.1 shows the different FORTRAN libraries available under OS/2 and the
- forms of execution they support.
-
- Table 3.1 FORTRAN OS/2 Libraries
- ───────────────────────────────────────────────────────────────────────────
- Executable Executable Dynamic-Link
- Single-Thread Multiple-Thread Multiple-Thread
- Component Library Library Run-Time Library
-
- .OBJ --- --- FRTDLL.OBJ
- FRTEXE.OBJ
- FRTLIB.OBJ
-
- .LIB mLIBFfP.LIB LLIBFMT.LIB FDLLOBJS.LIB
- DOSCALLS.LIB FDLLOBJS.DEF
- DOSCALLS.LIB
-
-
- 3.8 Limits on Multithread and Dynamic-Link Programs
-
- There are some restrictions on running multithread and dynamic-link
- programs. You must work within these limitations when you run a multithread
- and/or a dynamically linked program. Conventional DOS FORTRAN programs do
- not face these restrictions.
-
-
- 3.8.1 Large and Huge Memory Models (/MT, /MD)
-
- You can use both the /MT and /MD options in conjunction with the normal
- memory model switches /AL and /AH. However, the /AM (medium model) option is
- strictly disallowed with the /MT and /MD options since the run-time names
- differ under the medium model. See Chapter 7 the Microsoft FORTRAN Reference
- for more information on these FL command-line switches.
-
-
- 3.8.2 Math Support (/FPi87)
-
- The default-floating-point option, /FPi87, is still in effect for /MT and
- /MD compilation. Note, however, that any other form of /FP is allowed except
- /FPa (the alternate math option). The LLIBFMT.LIB and FDLLOBJS.LIB files
- contain the emulator math package. Although the emulator works when linked
- to object files compiled with any math option, it is recommended that the
- in-line forms (/FPi and /FPi87) be used for efficiency. A coprocessor will
- be used if it is available.
-
-
- 3.8.3 Limited CHARACTER*(*) Support
-
- The FORTRAN Compiler uses a global symbol, _FCclenv, to tell a function the
- actual length of a character argument or function. If two threads update
- this variable simultaneously, unpredictable behavior may result. Do not use
- CHARACTER*(*) or restrict its use to a single thread in multithread
- programs.
-
- ───────────────────────────────────────────────────────────────────────────
- WARNING
- The GETARG() subroutine returns its buffer argument in the CHARACTER*(*)
- form. Therefore, any calls to GETARG() must be restricted to a single
- thread and use no other CHARACTER*(*) calls.
- ───────────────────────────────────────────────────────────────────────────
-
-
- 3.8.4 The C Attribute and REAL Numbers
-
- Functions returning REAL values cannot use the C attribute. A global symbol,
- _fac, is used to return REAL values when you specify the C attribute for a
- function. If two threads access this variable simultaneously, the results
- cannot be predicted. Statically linked multithread programs will resolve
- this conflict. Therefore, you may not become aware of the problem. It may or
- may not influence your program. In a dynamically linked program the _fac
- symbol cannot be accessed outside of the FORTRAN run-time data segment, and
- therefore cannot be used. The simplest way to avoid this difficulty is to
- use the default calling convention with any function returning a REAL value.
-
-
- 3.8.5 Open Files
-
- You can open up to 40 files simultaneously in programs that use the
- multithread and/or dynamic-link capabilities of FORTRAN. (Since the system
- reserves a few of these files for its own use and others manage devices, the
- actual number of files a process can open is slightly less than 40.)
-
- Using all available units prior to any terminal I/O may result in an OS/2
- lack of storage space error. You can prevent this by forcing I/O to the
- terminal before reaching the system limit.
-
-
- 3.9 Recommendations
-
- The following points offer some general guidelines for creating multithread
- and dynamic-link programs. They are not requirements for creating such
- programs, but recommendations to help you around some common pitfalls.
-
- ■ Recompile all code in a multithread or dynamic-link program with the
- appropriate compile-time option (/MT or /MD), since it is necessary
- that the compiler assume that the segment addresses stored in the SS
- (which contains the stack address) and DS (which contains the near data
- address) registers are not equal. See the discussion of the /MD and /MT
- options in Chapter 7 of the Microsoft FORTRAN Reference for more
- information.
-
- ■ Allow threads to conduct I/O only on those units which they explicitly
- open. Since threads within a process share the resources of that
- process, it is possi-ble for one thread to perform I/O to units opened
- by other threads in the same process. This allows the possibility of
- delaying one request in the event that both threads attempt to access
- the same file simultaneously.
-
- ■ For multithread and dynamic-link programs, note that if the program
- terminates prematurely due to a MATH-class error, then the system does
- not flush the final buffer of any output files, since the termination
- code may not execute properly.
-
- ■ Because threads within a single process share resources, take care when
- using the preconnected units (units 0, 5, and 6 all connect to the
- terminal) in multithread programs. If a thread reconnects one of these
- units to a file, then when the process dies or a thread later closes
- the unit, it reassumes its preconnected status to the terminal. Any
- other threads which may have been reading or writing to that unit may
- unexpectedly read and write to the terminal.
-
- ■ Do not use a STOP statement inside a routine which is executing as a
- thread in a multithread program. The STOP statement terminates the
- process (including flushing and closing all open files), not just the
- thread that encountered the statement. Instead, use the ENDTHREAD
- subroutine to cause a thread to terminate itself.
-
- ■ In a multithread program, a thread that causes a run-time error in a
- statement without an explicit error-recovery sequence will cause the
- entire process to terminate──with a run-time error.
-
- ■ Files opened within a thread should be explicitly closed with the CLOSE
- statement. Closing the files returns the resource to the process and
- makes the files available to other threads. Thread termination does not
- implicitly close files in the way that process termination does.
-
-
- 3.10 Additional Information
-
- The following publications contain more information on OS/2 programming and
- philosophy:
-
- Cortesi, David E. The Programmer's Essential OS/2 Handbook. Redwood City,
- CA: M&T Publishing Co, 1988.
-
- Jamsa, Kris A. Using OS/2. Berkeley, CA: Osborne McGraw-Hill, 1988.
-
- Letwin, Gordon. Inside OS/2. Redmond, WA: Microsoft Press, 1987. (An
- explanation of OS/2 from Microsoft's Chief Architect, Systems Software.)
-
- Microsoft Systems Journal, May 1987. (Issue devoted to OS/2.)
-
- Petzold, Charles. PC Magazine column "Environments." (A series of articles
- on OS/2 programming topics begun with the October 13, 1987 issue.)
-
- Young, Michael J. Programmer's Guide to OS/2. San Francisco, CA: SYBEX,
- 1988.
-
-
- Chapter 4 Mixed-Language Programming
- ───────────────────────────────────────────────────────────────────────────
-
- Microsoft FORTRAN supports calls to routines written in Microsoft C and
- Pascal. In addition, if the main program is in Microsoft QuickBASIC 4.0 or
- later (or Microsoft BASIC Compiler 6.0 or later), then a FORTRAN routine can
- call a BASIC routine.This chapter describes the elements of mixed-language
- programming: how languages differ and how to resolve these differences.
-
- If you understand the basic principles involved in making a mixed-language
- call, then you may wish to turn directly to the detailed syntax information
- in Sections 4.2-4.4. These sections outline procedures for calling routines
- written in other high-level languages and in assembly language from
- Microsoft FORTRAN.
-
-
- 4.1 Making Mixed-Language Calls
-
- Mixed-language programming always involves a call to a function, procedure,
- or subroutine. For example, a FORTRAN main module may need to execute a
- specific task programmed in a different language. Instead of writing a new
- FORTRAN routine, you might decide to call a preexisting function written
- in──say──C.
-
- Mixed-language calls with Microsoft languages necessarily involve multiple
- modules. Instead of compiling all of your source modules with the same
- compiler, you use different compilers. In the instance mentioned above, you
- would compile the main-module source file with the FORTRAN compiler; compile
- a second source file (written in C) with the C compiler; and then link the
- two object files together.
-
- Figure 4.1 illustrates how the syntax of a mixed-language call works, using
- the example mentioned above.
-
- In the illustration above, the FORTRAN call to C is CALL Prn (), similar to
- a call to a FORTRAN subprogram. However, there are two differences between
- this mixed-language call and a call between two FORTRAN modules:
-
- ■ The subprogram Prn is actually implemented in C, using standard C
- syntax.
-
- ■ FORTRAN must use the INTERFACE statement in order to create
- compatibility with C.
-
- The INTERFACE statement is an example of a mixed-language interface
- statement (it is FORTRAN's interface statement). Each language provides
- its own form of interface.
-
- Despite syntactic differences, C functions, Pascal procedures, BASIC
- procedures, Microsoft Macro Assembler MASM routines, and FORTRAN
- subroutines and functions are all similar. The principal difference is that
- some kinds of routines return values and others do not. You can interchange
- routines that have a return value, and you can interchange routines that
- have no return value. Note that in this chapter, the term "routine" refers
- to any function, procedure, or subroutine that can be called from another
- module.
-
- Table 4.1 below shows the correspondence between routine calls in different
- languages.
-
- Table 4.1 Language Equivalents for Routine Calls
-
- Language Return Value No Return Value
-
- FORTRAN Function Subroutine
- C Function (Void) function
- Pascal Function Procedure
- BASIC FUNCTION procedure Subprogram
- Macro Assembler Procedure Procedure
-
- For example, a BASIC module can make a subprogram call to a FORTRAN
- subroutine. BASIC needs to make a FUNCTION call in order to call a FORTRAN
- function; otherwise, the call can be made, but the return value will be
- lost. This adapts the calling program to the conventions of the called
- routine.
-
- Note that FORTRAN cannot call BASIC DEF FN functions or GOSUB subroutines,
- since they are not independent from other programs or procedures; that is,
- they are contained within the main module of a BASIC program.
-
-
- 4.1.1 Naming Convention Requirement
-
- The term "naming convention" refers to the way a compiler alters the name of
- the routine before placing it into an object file.
-
- When you issue a mixed-language call, it is important that you adopt a
- consistent naming convention. If the name of the called routine is stored
- differently in each object file, then the linker will not be able to find a
- match. Instead, it will report an error.
-
- Object files contain not only machine code but also the names of all
- routines and variables that need to be accessed publicly. The linker must be
- able to compare the name of a routine called in one module to the name of a
- routine defined in another module and recognize a match. Names are stored in
- ASCII format. You can see precisely how they are stored if you use the DEBUG
- utility to dump an object file's bytes.
-
- FORTRAN, Pascal, and BASIC use roughly the same naming conventions. They
- translate each letter to uppercase. BASIC type declaration characters (%, &,
- !, #, $) are dropped.
-
- However, each language recognizes a different number of characters.
- Microsoft FORTRAN recognizes the first 31 characters of any name (or 6, if
- you use the $TRUNCATE metacommand); C the first 31; Pascal the first 8; and
- BASIC the first 40. If a name is longer than the number of characters the
- language will recognize, additional characters are dropped. For this reason,
- any time a FORTRAN program using the $TRUNCATE metacommand calls a routine
- from another language with a name longer than 6 characters, it must use the
- ALIAS statement. (See Section 4.2.3 for more information on ALIAS.)
-
- C uses a quite different convention. The C compiler does not translate any
- letters to uppercase, but inserts a leading underscore (_) in front of the
- name of each routine.
-
- Differences in naming conventions are taken care of automatically when you
- use mixed-language keywords, as long as you follow two rules:
-
- 1. If you use the $TRUNCATE metacommand, keep all routine names called by
- FORTRAN to 6 characters or less in length.
-
- 2. Do not use the /NOIGNORE linker option (which causes the linker to
- distinguish between Prn and prn). With C modules, this means that you
- will have to be careful not to rely upon differences between uppercase
- and lowercase letters.
-
- The CL driver and Microsoft QuickC use the /NOIGNORE option when
- linking. To solve the problems this creates, either link separately
- with the LINK utility or use all lowercase letters in your C modules.
-
- Figure 4.2 illustrates a complete mixed-language development example, which
- shows how naming conventions enter into the process.
-
- Note that the FORTRAN Compiler inserts a leading underscore in front of Prn
- as it places the name into the object file, because the C attribute directs
- the FORTRAN compiler to use the C naming convention. FORTRAN will also
- convert all letters to lowercase when this keyword is used. Note that
- converting letters to lowercase is not part of the C naming convention, but
- it is consistent with the programming style of most C programs.
-
-
- 4.1.2 Calling Convention Requirement
-
- The term "calling convention" refers to the way a language implements a
- call. The choice of calling convention affects the actual machine
- instructions that a compiler generates in order to execute──and return
- from──a function, procedure, or subroutine call.
-
- The calling convention is a low-level protocol. It is crucial that the
- routine issuing a call and the routine being called recognize the same
- protocol. Otherwise, the processor may receive inconsistent instructions,
- causing the system to crash.
-
- The use of a calling convention affects programming in two ways:
-
- 1. The calling routine uses a calling convention to determine the order in
- which to pass arguments (parameters) to another routine. Usually this
- convention can be specified in a mixed-language interface.
-
- 2. The called routine uses a calling convention to determine the order in
- which to receive the parameters that were passed to it. In most
- languages, including FORTRAN, the routine's heading specifies this
- convention. BASIC, however, always uses its own convention to receive
- parameters.
-
- In other words, each call to a routine uses a certain calling convention,
- and each routine heading specifies or assumes some calling convention. The
- two conventions must be compatible. With each language except BASIC, it is
- possible to change either calling convention. However, it is usually
- simplest to adopt the convention of the called routine. For example, a
- FORTRAN function would use its own convention to call another FORTRAN
- function and use the C convention to call C.
-
- FORTRAN, Pascal, and BASIC use the same standard calling convention. C,
- however, uses a quite different convention. The Microsoft BASIC, FORTRAN,
- and Pascal calling conventions each push parameters onto the stack in the
- order in which they appear in the source code. For example, the FORTRAN
- statement CALL Calc(A,B) pushes the argument A onto the stack before it
- pushes B. These conventions specify that the stack is restored by the called
- routine, before returning control to the caller. The stack is restored by
- removing parameters.
-
- The C calling convention pushes parameters onto the stack in the reverse
- order in which they appear in the source code. For example, the C function
- call calc(a,b); pushes b onto the stack before it pushes a. In contrast
- with other high-level languages, the C calling convention specifies that a
- calling routine always restores the stack immediately after the called
- routine returns control.
-
- The FORTRAN, Pascal, and BASIC conventions produce slightly less object
- code. However, the C convention makes calling with a variable number of
- parameters possible. Because the first parameter is always the last one
- pushed, it is always on the top of the stack; therefore it has the same
- address relative to the frame pointer, regardless of how many parameters
- were actually passed. You don't need to be aware of all variations in
- calling conventions in order to do mixed-language programming successfully,
- but you do need to remember that such differences exist.
-
-
- 4.1.3 Methods for Passing Parameters
-
- Section 4.1.2 discusses the overall protocol (the calling convention) that
- two routines use to communicate with each other; this section discusses how
- an individual item of data (a parameter) is actually exchanged.
-
- If your routines do not agree on how a parameter is to be sent, then a
- called routine will receive bad data. It is also possible that the program
- could cause a system error.
-
- Microsoft compilers support three methods for passing a parameter:
-
- Method Description
-
- By near reference Passes a variable's near (offset)
- address.
-
- This method gives the called
- routine direct access to the
- variable itself. Any change the
- routine makes to the parameter
- will be reflected in the calling
- routine.
-
- By far reference Passes a variable's far
- (segmented) address.
-
- This method is similar to passing
- by near reference, except that a
- longer address is passed. This
- method is slower than passing by
- near reference, but it is
- necessary when you pass data that
- is outside the default data
- segment. This is not an issue in
- BASIC or Pascal, unless you have
- specifically requested far
- memory.
-
- By value Passes only the variable's value,
- not address.
-
- With this method, the called
- routine knows the value of the
- parameter, but has no access to
- the original variable. Changes to
- a value parameter have no effect
- on the value of the parameter in
- the calling routine, once the
- routine terminates.
-
- The fact that there are different parameter-passing methods has two
- implications for mixed-language programming:
-
- ■ You need to make sure that the called routine and the calling routine
- use the same method for passing each parameter (argument). In most
- cases, you will need to check the parameter-passing defaults used by
- each language and possibly make adjustments. Each language has keywords
- or language features that allow you to change parameter-passing
- methods.
-
- ■ You may want to use a particular parameter-passing method rather than
- using the defaults of any language because of characteristics of your
- programming task.
-
- Table 4.2 summarizes the parameter-passing defaults for each language. Each
- language has methods for overriding these defaults.
-
- Table 4.2 Parameter-Passing Defaults
-
- By Near By Far
- Language Reference Reference By Value
-
- FORTRAN All All ---
- C Near arrays Far arrays Nonarrays
- Pascal VAR, CONST VARS, CONSTS Other parameters
- BASIC All BASIC All ---
-
-
- 4.1.4 Compiling and Linking Considerations
-
- After you write your source files and resolve the issues of naming
- conventions and parameter-passing procedures raised in Sections
- 4.1.1-4.1.3, you are ready to compile individual modules and then link
- them together. To do this successfully, the different modules need to use
- compatible memory models──that is, they must agree on where information is
- stored. These modules also need to know which libraries to reference in
- order to avoid unresolved external calls or duplicate routine definitions.
-
-
- 4.1.4.1 Using Compatible Memory Models
-
- With Microsoft FORTRAN, Pascal, and BASIC, no special options are required
- to compile source files that are part of a mixed-language program.
-
- With Microsoft C, however, you need to be aware that not all memory models
- will be compatible with other languages. FORTRAN, Pascal, and BASIC use only
- far (segmented) code addresses. Always compile C modules in medium, large,
- or huge models because these models also use far code addresses. Compiling
- in small or compact models causes the mixed-language program to crash as
- soon as a call is made to or from C. This problem can be averted if you
- apply the FAR keyword to a C function definition, in order to specify that
- the function uses a far call and return.
-
- Differences in the size of data addresses can be resolved through compile
- options or in the source code. Your choice of memory model affects the
- default data pointer size in FORTRAN and C, although this default can be
- overridden with the NEAR and FAR attributes in FORTRAN, or the near and far
- keywords in C. The FORTRAN and C memory models also affect whether data
- objects are located in the default data segment; if a data object is not
- located in the default data segment, it cannot be directly passed by near
- reference. For more information on memory models, see Section 2.3.2 in
- Chapter 2, "Selecting a Memory Model."
-
-
- 4.1.4.2 Specifying Libraries
-
- In many cases, linking modules compiled with different languages can be done
- easily. When you use the linker with the FORTRAN libraries you may need to
- specify the /NOD (no-default libraries) option and specify all the libraries
- you need directly on the LINK command line. You can also specify these
- libraries with an automatic-response file (or batch file).
-
- If your program uses both FORTRAN and C, then specify the library for the
- most recent of the two language products first. If you use C 4.0 with
- FORTRAN 4.0 or later, specify the FORTRAN library first. If you use C 5.1 or
- later, specify the C library first. In addition, make sure you choose a
- C-compatible library when you install FORTRAN.
-
- If you are listing BASIC libraries on the LINK command line, the BASIC
- libraries must precede all others, as in the following example:
-
- LINK /NOD mod1 mod2,,,GRAFX+LLIBCE+LLIBFORE
-
- Here two object modules, mod1 and mod2, are linked with the C 5.1 and
- FORTRAN 5.0 large-model libraries. In addition, the example links in an
- extra library, GRAFX.
-
-
- 4.2 Calling Other High-Level Languages
-
- In addition to the compiling and linking considerations mentioned above,
- your program will also need to follow some internal conventions for calling
- a routine written in another language. These considerations include creating
- an interface to the called routine and using keywords appropriate to the
- particular language called.
-
- For information on transferring data between languages, consult Chapter 5.
-
-
- 4.2.1 The INTERFACE Statement
-
- To call another language routine from within a FORTRAN function, first write
- an interface to the routine with the INTERFACE statement. This statement
- allows you to use special keywords (attributes) that affect the way FORTRAN
- carries out calls. These keywords allow you to adjust naming conventions,
- calling conventions, and parameter-passing methods so that you can make
- routines from other languages compatible with FORTRAN.
-
- Here are the guidelines to interfaces for routines from other languages:
-
- 1. Write an INTERFACE statement for each routine you call.
-
- Write the interface to a FUNCTION if the routine returns a value, or to
- a SUBROUTINE if the routine does not return a value. The INTERFACE
- statement needs to precede any calls to the routine.
-
- 2. Apply the C attribute to the routine if it is written in C (unless the
- C module is compiled with the /Gc routine or is modified with the
- fortran or pascal keyword).
-
- The C attribute causes the routine to be called with the C naming and
- calling conventions. It also changes the default parameter-passing
- method for all parameters to pass by value. To apply the C attribute,
- type [C] immediately after the name of the routine.
-
- 3. If the routine is called from Pascal, you may want to apply the PASCAL
- attribute to the routine. This keyword does not change calling or
- naming conventions, but causes all parameters to pass by value.
-
- To apply the PASCAL attribute, type [PASCAL] immediately after the
- name of the routine.
-
- 4. If $TRUNCATE is on and the name of the routine is longer than 6
- characters, use the ALIAS attribute. The use of ALIAS is explained in
- Section 4.2.3 below.
-
- 5. Adjust the way parameters are passed by applying the NEAR, FAR, VALUE,
- and REFERENCE attributes to parameter declarations.
-
- The REFERENCE attribute can be useful because the C and PASCAL keywords
- automatically change the default parameter-passing method to passing by
- value. For any given parameter, REFERENCE reverts the method to passing
- by reference. (By default, FORTRAN passes by far reference unless you
- are using the medium memory model available with FORTRAN, Versions 4.0
- or later.)
-
- To apply an attribute to a parameter declaration, put the attribute in
- brackets, along with any other attributes that modify the same object,
- and place the attribute and brackets immediately after the parameter.
- (See the examples below.)
-
- 6. Once the proper interface is set up, call the routine just as you would
- call any FORTRAN function or subroutine.
-
- Examples
-
- In the examples below, the variables N, I, and J are not significant,
- except for their types and attributes.
-
- This first example declares the subroutine TEST with the PASCAL attribute.
-
- INTERFACE TO SUBROUTINE TEST [PASCAL] (N)
- INTEGER*2 N [NEAR, REFERENCE]
- END
-
- The subroutine takes one argument, N, which contains both of the NEAR and
- REFERENCE attributes. Therefore N is passed by near reference.
-
- The second example declares a C function, CFUN, which returns a value of
- type REAL*8.
-
- INTERFACE TO REAL*8 FUNCTION CFUN [C] (I,J)
- REAL*8 I [REFERENCE]
- REAL*8 J
- END
-
- The argument I is passed by far reference because of the REFERENCE
- attribute; the argument J is passed by value because the C attribute
- changes the default.
-
-
- 4.2.2 An Alternative Interface to C
-
- Step 2 of the above guidelines suggests modifying the behavior of FORTRAN
- with the C attribute when calling a C routine. Alternately, since the pascal
- and fortran keywords are functionally equivalent, you can modify the
- behavior of C by applying either keyword to the function definition heading.
- Or, you can compile the C module with the /Gc option, which specifies that
- all C functions, calls, and public symbols use the FORTRAN/Pascal/BASIC
- conventions.
-
- For example, the following C function uses the FORTRAN/Pascal/BASIC
- conventions to receive an integer parameter:
-
- int fortran fun1(n)
- int n;
-
-
- 4.2.3 The ALIAS Attribute
-
- The ALIAS attribute allows you to refer to a routine by one name in your
- code while the object code uses another name. The attribute is particularly
- helpful when the called routine has a cryptic name.
-
- The ALIAS attribute uses this syntax ALIAS: ' aliasname '. Note that
- aliasname is the name FORTRAN will actually place in the object code
- whenever the declared routine is called. When you use this feature,
- aliasname is precisely what FORTRAN will place in the object code;
- therefore, if you are linking to a C routine, be sure to type a leading
- underscore (_) before the name.
-
- The ALIAS feature is necessary when using the $TRUNCATE metacommand and the
- name of a routine exceeds 6 characters. Without ALIAS, FORTRAN would place
- only the first 6 characters into the object file, while the other language
- would place 8 or more characters into the other object file (up to 40 in the
- case of BASIC). This difference would prevent the linker from finding a
- match. Without $TRUNCATE, Microsoft FORTRAN will accept up to 31 characters.
-
- In the example below, ALIAS is used because PRINTNUM is longer than 6
- characters. Note that the leading underscore should be used only when
- linking to a routine that uses the C naming convention.
-
- $TRUNCATE
- INTERFACE TO PRINTNUM [C, ALIAS:'_printnum'] (N)
- INTEGER*2 N
- END
-
-
- 4.2.4 FORTRAN Calls to C and Pascal
-
- Writing FORTRAN interfaces to C is fairly straightforward. Calling Pascal
- from FORTRAN is also simple, because the PASCAL attribute causes FORTRAN to
- use the Pascal default of passing data by value. This section applies the
- steps outlined in Section 4.2.1 to two examples of FORTRAN-C programs. A
- brief analysis follows each example.
-
-
- 4.2.4.1 Calling C from FORTRAN──No Return Value
-
- The example below demonstrates a FORTRAN main module calling a C function,
- maxparam. This function returns no value but adjusts the lower of two
- parameters to equal the higher argument.
-
- C FORTRAN SOURCE FILE - CALLS C FUNCTION, NO RETURN
- C VALUE
- C
- INTERFACE TO SUBROUTINE MAXPARAM [C] (I,J)
- INTEGER*2 I [NEAR, REFERENCE]
- INTEGER*2 J [NEAR, REFERENCE]
- END
-
- C
- C C ATTRIBUTE DIRECTS FORTRAN TO USE C CONVENTIONS
- C EACH PARAMETER PASSED BY NEAR REFERENCE
- C
- INTEGER*2 I,J
- I = 5
- J = 7
- WRITE (*,*) 'I = ',I,' J = ', J
- CALL MAXPARAM(I,J)
- WRITE (*,*) 'I = ',I,' J = ', J
- END
-
- /* C source file */
- /* Compile in MEDIUM or LARGE memory model */
- /* Maxparam declared VOID because no return value */
-
- void maxparam(p1, p2)
- int near *p1; /* Integer params received by near ref. */
- int near *p2; /* NEAR keyword not needed in MEDIUM model */
- {
- if (*p1 > *p2)
- *p2 = *p1;
- else
- *p1 = *p2;
- }
-
- Both modules place _maxparam (consistent with the C naming convention) into
- an object file. The C attribute in the INTERFACE statement causes the
- MAXPARAM function to be called with the C calling convention, which pushes
- param-eters in reverse order and specifies other lower-level differences.
-
- Since the function maxparam may alter the value of either parameter, both
- must be passed by reference. Near reference is implemented in FORTRAN with
- the NEAR and REFERENCE attributes and in C by using near pointers. The
- REFERENCE attribute is necessary in FORTRAN, since the C keyword changes the
- default-passing method to pass by value.
-
- Far reference could have been specified by leaving off the NEAR keyword from
- the FORTRAN parameter declarations. In that case, the C module would need to
- use far pointers.
-
-
- 4.2.4.2 Calling C from FORTRAN──Function Call
-
- The example below demonstrates a FORTRAN main module calling a C function,
- fact. This function returns the factorial of an integer value.
-
- C FORTRAN SOURCE FILE - CALLS C FUNCTION
- C
- INTERFACE TO INTEGER*2 FUNCTION FACT [C] (N)
- INTEGER*2 N
- END
-
- C
- C C ATTRIBUTE DIRECTS FORTRAN TO USE C CONVENTIONS
- C PARAMETER PASSED BY VALUE, WHICH IS DEFAULT WHEN
- C C ATTRIBUTE IS IN USE
- C
- INTEGER*2 FACT
- INTEGER*2 I,J
- I = 3
- J = 4
- WRITE (*,*) 'The factorial of I is ',FACT(I)
- WRITE (*,*) 'The factorial of J is ',FACT(J)
- WRITE (*,*) 'The factorial of I+J is ',FACT(I+J)
- END
-
- /* C source file */
- /* Compile in MEDIUM or LARGE model */
- /* Factorial function, returning integer */
-
- int fact(n)
- int n; /* Integer received by value, the C default */
- {
- int result = 1;
-
- while (n)
- result *= n--; /* Parameter n modified here */
- return (result);
- }
-
- The C attribute in the INTERFACE statement causes FACT to be called with
- the C naming convention (as _fact). The C attribute in the INTERFACE
- statement causes FACT to be called with the C calling convention, which
- pushes parameters in reverse order and specifies other lower-level
- differences.
-
- The C function above should receive the parameter by value. Otherwise, the
- function will corrupt the parameter's value in the calling module. Passing
- by value is the default method for C; it is also the default method for
- FORTRAN whenever the C attribute is in use.
-
-
- 4.2.4.3 Calling Pascal from FORTRAN──Procedure Call
-
- The example below demonstrates a FORTRAN main module calling a Pascal
- procedure, Maxparam. This procedure adjusts the lower of two parameters to
- equal the higher argument.
-
- C FORTRAN SOURCE FILE - CALLS PASCAL PROCEDURE
- C
- INTERFACE TO SUBROUTINE MAXPARAMETER
- + [ALIAS:'MAXPARAM'] (I,J)
- INTEGER*2 I [NEAR]
- INTEGER*2 J [NEAR]
- END
-
- C
- C ALIAS NECESSARY BECAUSE 'MAXPARAMETER' LONGER
- C THAN 8 CHARS.
- C EACH PARAMETER PASSED BY NEAR REFERENCE
- C
- INTEGER*2 I,J
- I = 5
- J = 7
- WRITE (*,*) 'I = ',I,' J = ', J
- CALL MAXPARAMETER(I,J)
- WRITE (*,*) 'I = ',I,' J = ', J
- END
-
- { Pascal source code - Maxparam procedure. }
-
- module Psub;
- procedure Maxparam(var a:integer; var b:integer);
-
- { Two integer parameters are received by near reference. }
- { Near reference is specified with the VAR keyword. }
-
- begin
- if a > b then
- b := a
- else
- a := b
- end;
- end.
-
- By default, FORTRAN places all 12 characters of MAXPARAMETER into the
- object file, whereas Pascal places only 8. The ALIAS attribute resolves this
- conflict: both modules place MAXPARAM into an object file. FORTRAN and
- Pascal use the same convention for calling.
-
- Since the procedure Maxparam may alter the value of either parameter, both
- must be passed by reference. Near reference was implemented in FORTRAN with
- the NEAR attribute, and in Pascal with the VAR keyword. The PASCAL attribute
- is not used here because no parameter is being passed by value.
-
- Far reference could have been specified by leaving off NEAR from the FORTRAN
- parameter declarations, using VARS instead of VAR in the Pascal module.
-
-
- 4.2.4.4 Calling Pascal from FORTRAN──Function Call
-
- The example below demonstrates a FORTRAN main module calling a Pascal
- function, Fact. This function returns the factorial of an integer value.
-
- C FORTRAN SOURCE FILE - CALLS PASCAL FUNCTION
- C
- INTERFACE TO INTEGER*2 FUNCTION FACT [PASCAL] (N)
- INTEGER*2 N
- END
-
- C
- C PARAMETER PASSED BY VALUE, WHICH IS DEFAULT WHEN
- C PASCAL ATTRIBUTE IS IN USE
- C
- INTEGER*2 FACT
- INTEGER*2 I,J
- I = 3
- J = 4
- WRITE (*,*) 'The factorial of I is ',FACT(I)
- WRITE (*,*) 'The factorial of J is ',FACT(J)
- WRITE (*,*) 'The factorial of I+J is ',FACT(I+J)
- END
-
- { Pascal source code - factorial function. }
-
- module Pfun;
- function Fact (n : integer) : integer;
-
- { Integer parameters received by value, the Pascal default. }
-
- begin
- Fact := 1;
- while n > 0 do
- begin
- Fact := Fact * n;
- n := n - 1; { Parameter n modified here.}
- end;
- end;
- end.
-
- FORTRAN and Pascal use a similar naming convention. The ALIAS statement is
- unnecessary because the function name does not exceed the Pascal limit of 8
- characters. FORTRAN and Pascal use the same calling convention.
-
- The Pascal function above should receive the parameter by value. Otherwise,
- the function will corrupt the parameter's value in the calling module.
- Passing by value is the default method for Pascal; it is also the default
- method for FORTRAN whenever the PASCAL attribute is in use.
-
-
- 4.2.5 C Functions Available with FORTRAN Run-Time Libraries
-
- The FORTRAN run-time libraries MLIBFORx.LIB and LLIBFORx.LIB include the
- system routine and a subset of the spawnlp routine (as well as other
- rou-tines) originally from the C library. FORTRAN programs access these
- routines in the FORTRAN run-time libraries; however, these routines may
- present compatibility problems with future versions of Microsoft C. Sections
- 4.2.5.1-4.2.5.2 show how to access these C routines and discuss future
- compatibility issues. (The demonstration program DEMOEXEC.FOR included with
- the Microsoft FORTRAN Compiler also gives examples of how to call these C
- routines.)
-
-
- 4.2.5.1 Accessing system and spawnlp Functions
-
- The system function has the following declaration in C:
-
- int system (string)
- char *string;
-
- The system function passes a specified C string (ending with a null
- character) to the DOS command interpreter (COMMAND.COM), which interprets
- and exe-cutes the string as a DOS command. This allows DOS commands (such as
- DIR or DEL), batch files, and programs to be executed.
-
- The following program fragment shows how to access the system function from
- a FORTRAN program to display all files in the current directory with the
- file extension .FOR.
-
- INTEGER*2 SYSTEM
- C RETURN TYPE MUST BE DECLARED;
- C NOTICE THE C LITERAL STRING '...'C
- I = SYSTEM ('DIR *.FOR'C)
-
- The INTERFACE statement required to access system is given below. The C
- attribute is specified after the function name. The argument string includes
- the REFERENCE attribute to indicate that the argument is passed by
- reference.
-
- INTERFACE TO INTEGER*2 FUNCTION SYSTEM [C]
- + (STRING[REFERENCE])
- CHARACTER*1 STRING
- END
-
- The spawnlp function has the following declaration in C:
-
- int spawnlp (mode,path,arg0,arg1,...,argn)
- int mode; /* spawn mode */
- char *path; /* pathname of program to execute */
- char *arg0; /* should be the same as path */
- char *arg1,...,*argn; /* command line arguments */
- /* argn must be NULL */
-
- This function creates and executes a new child process. There must be enough
- memory to load and execute the child process. The mode argument determines
- which form of spawnlp is executed. For the version of the spawnlp function
- in the FORTRAN run-time libraries, this value must be 0, which tells spawnlp
- to suspend the parent program and execute the child program. When the child
- program terminates, the parent program resumes execution. The return value
- from spawnlp is -1 if an error occurs. If the child process runs
- successfully, the return value is the return code from the child process.
-
- The path argument specifies the file to be executed as the child process.
- The path can specify a full path name from the root directory, a partial
- path name from the current working directory, or a file name. If the path
- argument does not have a file-name extension or end with a period (.), the
- spawnlp call first appends the extension .COM and searches for the file. If
- spawnlp cannot find the file, it appends the extension .EXE and tries to
- find the file again. The spawnlp routine also searches for the file in any
- of the directories specified in the PATH environment variable using the same
- procedure.
-
- The INTERFACE statement required to access spawnlp from a FORTRAN program is
- given below. The C attribute must appear after the function name. The
- VARYING attribute indicates that a variable number of arguments may be
- passed to the function.
-
- INTERFACE TO INTEGER*2 FUNCTION SPAWNLP
- + [C,VARYING] (MODE)
- INTEGER*2 MODE
- END
-
- If you use the $STRICT or $TRUNCATE metacommands, you must use a name 6
- characters or less in the INTERFACE statement and use the ALIAS attribute to
- associate the FORTRAN name SPAWN with the C identifier spawnlp.
-
- The following program fragment illustrates how to call the spawnlp function
- from a FORTRAN program:
-
- C (THE RETURN TYPE MUST BE DECLARED)
- INTEGER*2 SPAWNLP
- .
- .
- .
- C EXECUTE AS A CHILD PROCESS
- I = SPAWNLP(0, LOC('EXEMOD'C), LOC('EXEMOD'C), c
- + LOC('DEMOEXEC.EXE'C), INT4(0))
-
- Notice in this example that the method used to pass strings to spawnlp is
- different from the method used to pass strings to system. This is because
- the string arguments to spawnlp are undeclared in the INTERFACE statement
- and assumed to be passed by value. The spawnlp function expects the
- addresses of the strings rather than the actual characters, so the FORTRAN
- program uses the LOC intrinsic function to pass the address. (Remember that
- functions with the C attribute pass arguments by value.) The last argument
- to the spawnlp routine must be a C null pointer (an integer 0), so the
- FORTRAN program must use either the INT2(0) or the INT4(0) intrinsic
- function (depending on the memory model) to pass this pointer by value as
- the last argument.
-
-
- 4.2.5.2 FORTRAN Libraries and Future Versions of Microsoft C
-
- If you plan to mix Microsoft FORTRAN modules with modules compiled using
- Microsoft C, you should use the SETUP utility to prepare new copies of your
- FORTRAN run-time libraries. When you create these copies, tell SETUP that
- you want the copies to interface with C. In these copies, SETUP removes the
- C routines. Later, when you link FORTRAN modules with C modules, you should
- link with the appropriate C run-time library for the memory model that you
- are using. This link will take care of unresolved references from
- MLIBFORx.LIB and LLIBFORx.LIB. You can still use your original copies of
- MLIBFORx.LIB and LLIBFORx.LIB for programs that do not include C modules.
-
-
- 4.2.6 FORTRAN Calls to BASIC
-
- Calls from FORTRAN programs to BASIC (MS QuickBASIC 4.0 or later or
- Microsoft BASIC Compiler 6.0 or later) programs are not directly supported.
- No BASIC routine can be executed unless the main program is in BASIC,
- because a BASIC routine requires the environment to be initialized in a way
- that is unique to BASIC. No other language will perform this special
- initialization.
-
- It is possible for a program to start up in BASIC, call a FORTRAN function
- that does most of the work of the program, and then call BASIC subprograms
- and function procedures as needed. Figure 4.3 illustrates how this can be
- done.
-
- Here are the recommended rules for calling BASIC from FORTRAN:
-
- 1. Start up in a BASIC main module. You will need to use QuickBASIC,
- Version 4.0 or later, and may want to use the DECLARE statement to
- write an interface to the principal FORTRAN routine. (See Section
- 5.1.1, "BASIC Arguments," for more information.)
-
- 2. Write an interface in FORTRAN for each BASIC routine you plan to call.
- Since BASIC and FORTRAN use the same calling convention, no special
- keyword is required to make FORTRAN compatible with BASIC.
-
- 3. Make sure that all data are passed by near reference. BASIC can pass
- data in a variety of ways, but is unable to receive data in any form
- other than near reference.
-
- With near pointers, the program assumes that the data are in the
- default data segment. If you want to pass data that are not in the
- default data segment (this is only a consideration with large-model
- programs), then first copy the data to a variable that is in the
- default data segment.
-
- The example below demonstrates a BASIC program which calls a FORTRAN
- subroutine. The FORTRAN subroutine then calls a BASIC function that returns
- twice the number passed it, and a BASIC subprogram that prints two numbers.
-
- ' BASIC source
- '
- DEFINT A-Z
- DECLARE SUB Fprog ()
- CALL Fprog
- END
- '
- FUNCTION Dbl(N) STATIC
- Dbl = N*2
- END FUNCTION
- '
- SUB Printnum(A,B) STATIC
- PRINT "The first number is ";A
- PRINT "The second number is ";B
- END SUB
-
-
- C FORTRAN subroutine
- C Calls a BASIC function that receives one integer,
- C and a BASIC subprogram that takes two integers.
- C
- INTERFACE TO INTEGER*2 FUNCTION DBL (N)
- INTEGER*2 N [NEAR]
- END
- C
- INTERFACE TO SUBROUTINE PRINTNUM(N1, N2)
- INTEGER*2 N1 [NEAR]
- INTEGER*2 N2 [NEAR]
- END
- C
- C Parameters must be declared NEAR in the parameter
- C declarations; BASIC receives ONLY 2-byte pointers
-
- C
- SUBROUTINE FPROG
- INTEGER*2 DBL
- INTEGER*2 A, B
- A = 5
- B = 6
- WRITE (*, *) 'Doubling 5 equals ', DBL(A)
- CALL PRINTNUM(A, B)
- END
-
- In the example above, note that the NEAR attribute is used in the FORTRAN
- routines, so that near addresses will be passed to BASIC instead of far
- addresses.
-
-
- 4.3 Using Assembly-Language Routines
-
- You may want to consider writing routines in assembly language when you need
- extreme speed (or when another language would run too slowly). With the
- Microsoft Macro Assembler (MASM) you can write assembly modules that can be
- linked to modules developed with Microsoft FORTRAN. This section outlines
- the recommended programming guidelines for writing assembly routines
- compatible with Microsoft FORTRAN and gives specific examples.
-
- Writing assembly routines for Microsoft FORTRAN is easiest when you use the
- simplified segment directives provided with the Microsoft Macro Assembler,
- Version 5.0. In general, this chapter assumes that you have MASM 5.0.
-
- A FORTRAN program can call an external assembly procedure with the use of
- the INTERFACE statement. However, the INTERFACE statement is not strictly
- necessary unless you intend to change one of the FORTRAN defaults. However,
- you may find the following guidelines helpful:
-
- 1. Declare procedures called from FORTRAN as FAR.
-
- 2. Observe the FORTRAN calling convention.
-
- a. Upon exit, the procedure must reset SP to the value it had before
- the arguments were placed on the stack. This is accomplished with
- the instruction RET size, where size is the total size of all the
- parameters.
-
- b. Arguments are placed on the stack in the same order in which they
- appear in the FORTRAN source code. The first parameter will be
- highest in memory (because it is also the first parameter to be
- placed on the stack, and the stack grows downward).
-
- c. By default, FORTRAN parameters are passed by reference as far
- addresses if the FORTRAN module is compiled in the large or huge
- memory model, and as near addresses if the FORTRAN module is
- compiled in the medium model. Versions of FORTRAN prior to 4.0 are
- always large model.
-
- 3. Observe the FORTRAN naming convention.
-
- FORTRAN only recognizes the first 6 characters of any name if the
- metacommand $TRUNCATE is specified, while the assembler recognizes the
- first 31. By default, FORTRAN recognizes 31 characters.
-
- In the following example, FORTRAN calls an assembly procedure that
- calculates "A x 2^(B)," where A and B are the first and second parameters,
- respectively. This is done by shifting the bits in A to the left, B times.
-
- The following example shows how FORTRAN would call the assembly procedure:
-
- INTERFACE TO INTEGER*2 POWER2(A,B)
- INTEGER*2 A,B
- END
- C
- INTEGER*2 A,B
- A = 3
- B = 5
- WRITE (*,*) '3 times 2 to the power of 5 is ',
- + POWER2(A,B)
- END
-
- To understand how to write the assembly procedure, consider how the
- parameters are placed on the stack, as illustrated in Figure 4.4.
-
- Figure 4.4 assumes large-model FORTRAN. If you compile the FORTRAN module in
- medium model, then each argument will be passed as a two-byte, not four-byte
- address. The return address is four bytes long because procedures called
- from FORTRAN must always be FAR.
-
- Arg 1 (parameter 1) is higher in memory than Arg 2 because FORTRAN pushes
- arguments (parameters) in the same order that they appear.
-
- The assembly procedure can be written as follows:
-
- .MODEL LARGE
- .CODE
- PUBLIC Power2
- Power2 PROC
- push bp ; Entry sequence - save old BP
- mov bp,sp ; Set stack frame pointer
-
- les bx,[bp+10] ; Load Arg1 into
- mov ax,es:[bx] ; AX
- les bx,[bp+6] ; Load Arg2 into
- mov cx,es:[bx] ; CX
- shl ax,cl ; AX = AX * (2 to power of CX)
- ; Leave return value in AX
-
- pop bp ; Exit sequence - restore old BP
- ret 8 ; Return and restore 8 bytes
- Power2 ENDP
- END
-
- In the example above, each argument must be loaded using the four-byte
- address that was pushed onto the stack. The procedure loads four-byte
- addresses with the les instruction, which loads the destination operand (in
- this case, BX) with the source operand, and also loads ES with the object
- two bytes higher in memory. Thus, the instruction
-
- les bx,[bp+10]
-
- loads BX with the value at BP+10 (an offset address), and ES with the
- value at BP+12 (a segment address), which is necessary to set up the next
- instruction.
-
- Upon exit, the stack is restored with the instruction ret 8, since the total
- size of parameters pushed onto the stack is eight bytes.
-
- 4.4 Calling FORTRAN from Other Languages
-
- Other compiled Microsoft languages──C, Pascal and BASIC──support calls to
- compiled FORTRAN subroutines and functions. If there is a set of FORTRAN
- routines you use regularly, but you also program in one or more of these
- languages, you can save a duplication of effort by calling these FORTRAN
- routines rather than translating them into other languages.
-
- Note that, unlike Pascal and C, FORTRAN does not have public variables. Only
- functions, subroutines, and common blocks are public; individual FORTRAN
- variables cannot be declared public. Therefore, if you want a procedure
- written in another language to directly access a FORTRAN variable, that
- variable must appear in a FORTRAN common block. For example, you can declare
- a common block in a FORTRAN routine, then access it from a C program by
- declaring an external structure with the same form.
-
- Each language has its own conventions and procedures for accessing Microsoft
- FORTRAN. They are explained in the section of that language's manual which
- covers mixed-language programming.
-
-
- Chapter 5 Transferring Data between Languages
- ───────────────────────────────────────────────────────────────────────────
-
- Chapter 4 introduced the general concepts of passing parameters by reference
- and by value. In some situations you may want to pass parameters by a
- particular method or to pass different types of data (logicals, strings, or
- arrays as opposed to strictly numerical data). This chapter provides you
- with the information you'll need.
-
- The first section of this chapter discusses ways to change each language's
- standard manner of passing data. The second section covers numeric, logical,
- and string data; the third addresses special situations involving structured
- data (such as arrays) and externally accessed data.
-
-
- 5.1 Passing by Reference or Value
-
- This section describes how to override the default method each language uses
- to pass data. The section contains four parts, each of which summarizes
- parameter-passing methods in a particular language and discusses how to pass
- arguments by value, by near reference, and by far reference. To successfully
- pass data between languages, you must consider how each parameter is passed
- by the calling routine and how each is received by the called routine.
-
-
- 5.1.1 BASIC Arguments
-
- The default for BASIC is to pass all arguments by near reference. Every
- BASIC subprogram or function always receives parameters by near reference.
-
- A BASIC argument passes by value when the called routine is first declared
- with a DECLARE statement and the BYVAL keyword is applied to the argument.
- Note that BYVAL applies to one argument only; if your routine uses three
- arguments and you want all of them to pass by value, you must put the BYVAL
- option in front of each argument.
-
- BASIC will pass each argument in a call by far reference when CALLS is used
- to invoke a routine. Using SEG to modify a parameter in a preceding DECLARE
- statement will also cause BASIC to pass that parameter by far reference.
-
-
- 5.1.2 C Arguments
-
- The default for C is to pass all arrays by reference (near or far, depending
- on the memory model) and all other data types by value. C uses far data
- pointers for compact, large, and huge models, and near data pointers for
- small and medium models. FORTRAN supports medium, large, and huge memory
- models.
-
- The C default is to pass all nonarrays (which includes all data types other
- than those explicitly declared as arrays) by value.
-
- Arrays can be passed by value by declaring them as the only member of a
- structure.
-
- In C, passing a pointer to an object is equivalent to passing the object
- itself by reference. The default for arrays is to pass by reference. In C,
- near reference is the default for passing pointers in small and medium
- models. Far reference is the default in the compact, large, and huge models.
-
-
- 5.1.3 FORTRAN Arguments
-
- The FORTRAN default is to pass and receive all arguments by reference. The
- size of the address passed depends on the memory model.
-
- A parameter passes by value when declared with the VALUE attribute. This
- declaration can occur either in an INTERFACE statement (which determines how
- to pass a parameter) or in a function or subroutine declaration (which
- determines how to receive a parameter).
-
- A function or subroutine declared with the PASCAL or C attribute will pass
- by value all parameters declared in its parameter list except for those
- parameters declared with the REFERENCE attribute. This change in default
- passing method applies to function and subroutine definitions, as well as to
- an INTERFACE statement.
-
- Passing by reference is the default for FORTRAN. However, if either the C or
- PASCAL attribute is applied to a function or subroutine declaration, then
- you need to apply the REFERENCE attribute to any parameter of the routine
- that you want passed by reference.
-
- Near reference is the default for medium-model FORTRAN programs; far
- reference is the default for large- and huge-model programs.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- Versions of FORTRAN prior to 4.0 always compile in large memory model.
- ───────────────────────────────────────────────────────────────────────────
-
- You can apply the NEAR attribute to reference parameters in order to specify
- near reference. You can apply the FAR attribute to reference parameters in
- order to specify far reference. These keywords override the default, but
- have no effect when they specify the same method as the default.
-
- You can apply more than one attribute to a given parameter. In that case,
- enclose both attributes in brackets, separated by a comma:
-
- REAL*4 X [NEAR, REFERENCE]
-
-
- 5.1.4 Pascal Arguments
-
- The Pascal default is to pass all arguments by value. Parameters are passed
- by near reference when declared as VAR or CONST. Parameters also pass by
- near reference when the ADR of a variable, or a pointer to a variable, is
- passed by value. In other words, the address of the variable is first
- determined, then passed by value. This is essentially the same method used
- in C.
-
- Parameters pass by far reference when declared as VARS or CONSTS. Parameters
- are also passed by far reference when the ADRS of a variable is passed by
- value.
-
-
- 5.2 Passing Numeric, Logical, and String Data
-
- This section explains procedures for passing and receiving different types
- of data. The discussion focuses on the differences in string formats and on
- the methods of passing strings between FORTRAN and other languages.
-
-
- 5.2.1 Integer and Real Numbers
-
- Integers and reals are usually the simplest kinds of data to pass between
- languages. However, the type of numerical data is named differently in each
- language; furthermore, not all data types are available in every language,
- and another type may have to be substituted in some cases.
-
- Table 5.1 shows equivalent data types in each language.
-
- Table 5.1 Equivalent Numeric Data Types
- ───────────────────────────────────────────────────────────────────────────
-
- BASIC C FORTRAN Pascal
-
- x% short INTEGER*2 INTEGER2
- INTEGER int --- INTEGER (defaul
- --- unsigned short --- WORD
- --- unsigned --- ---
- x& long INTEGER*4 INTEGER4
- LONG --- INTEGER (default) ---
- --- unsigned long --- ---
- x! float REAL*4 REAL4
- x (default) --- REAL REAL (default)
- SINGLE --- --- ---
- x# double REAL*8 REAL8
- DOUBLE --- DOUBLE PRECISION ---
- --- unsigned char CHARACTER*1 BOOLEAN
-
-
- ───────────────────────────────────────────────────────────────────────────
- WARNING
- C sometimes performs automatic data conversions that the other languages
- do not perform. You can prevent C from performing such conversions by
- declaring a variable as the only member of a structure and then passing
- this structure. For example, you can pass a variable x of type float by
- first declaring it as a structure. If you pass a variable of type char or
- float by value and do not take this precaution, then the C conversion may
- cause the program to fail.
- ───────────────────────────────────────────────────────────────────────────
-
-
- 5.2.2 FORTRAN COMPLEX Types
-
- The FORTRAN types COMPLEX*8 and COMPLEX*16 are not directly implemented in
- any other language. However, you can write precisely equivalent structures
- in C, records in Pascal, or user-defined types in BASIC.
-
- The type COMPLEX*8 has two fields: The first is a four-byte floating-point
- number that contains the real component, and the second is a four-byte
- floating- point number that contains the imaginary component.
-
- The type COMPLEX*16 is similar to COMPLEX*8, with the only difference being
- that each field contains an eight-byte floating-point number. The type
- COMPLEX is equivalent to the type COMPLEX*8.
-
- ┌──────────────────────────────┬───────────────────────────────┐
- │ Float real component │ Float imaginary component │
- └──────────────────────────────┴───────────────────────────────┘
- └───────────────┬──────────────┴───────────────┬───────────────┘
- 4 bytes 4 bytes
-
- FORTRAN COMPLEX Data Format
-
- 5.2.3 FORTRAN LOGICAL Type
-
- The FORTRAN LOGICAL type is not equivalent to either the Pascal BOOLEAN or C
- char type. Instead, a FORTRAN LOGICAL*2 is stored as a one-byte indicator
- value (1=true, 0=false), followed by an unused byte. A FORTRAN LOGICAL*4 is
- stored as a one-byte indicator value followed by three unused bytes. The
- type LOGICAL is equivalent to LOGICAL*4, unless $STORAGE:2 is in effect.
-
- To pass or receive a FORTRAN LOGICAL type, declare a C structure, Pascal
- record, or BASIC user-defined type, with the appropriate fields.
-
-
- 5.2.4 Strings
-
- Strings are stored in a variety of formats. Therefore, some transformation
- is frequently required to pass strings between languages.
-
- This section presents the string formats used in each language and then
- describes methods for passing strings from FORTRAN to these languages.
-
-
- 5.2.4.1 BASIC Strings
-
- Strings are stored in BASIC as four-byte string descriptors, as illustrated
- below:
-
- ┌──────────────────────┬───────────────────────┐
- │ Length │ Address (offset) │
- └──────────────────────┴───────────────────────┘
- └───────────┬──────────┴───────────┬───────────┘
- 2 bytes 2 bytes
-
- BASIC String Descriptor Format
-
- The first field of the string descriptor contains a two-byte integer
- indicating the length of the actual string text. The second field contains
- the address of this text. This address is an offset into the default data
- area. BASIC's string management routines reassign this address whenever the
- length of the string changes, yet these management routines are only
- available to BASIC. Therefore, FORTRAN should not alter the length of a
- BASIC string.
-
- ───────────────────────────────────────────────────────────────────────────
- WARNING
- When you pass a string from BASIC to FORTRAN, the called routine should
- under no circumstances alter the length of the string. Other languages
- lack BASIC's string space management routines. Therefore, altering the
- length of a BASIC string is liable to corrupt parts of the BASIC string
- space. Changes that do not affect length, however, are relatively safe.
- The routine that receives the string must not call any BASIC routine. If
- it does, BASIC's string space management routines may change the location
- of the string data without warning.
- ───────────────────────────────────────────────────────────────────────────
-
- FORTRAN must receive by near reference. The NEAR attribute makes this
- adjustment, since the FORTRAN default is to receive by far reference.
-
-
- 5.2.4.2 C Strings
-
- C stores strings as simple arrays of bytes and uses a null character
- (numerical 0, ASCII NUL) as a delimiter. For example, consider the string
- declared as follows:
-
- char str[] = "String of text"
-
- The string is stored in 15 bytes of memory as
-
- ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
- │ S │ t │ r │ i │ n │ g │ │ o │ f │ │ t │ e │ x │ t │\0 │
- └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
- C String Format
-
- Since str is an array like any other, it is passed by reference, just as
- other C arrays are. To pass by value, declare the array as a member of a
- structure. (See Section 5.1.2, "C Arguments," for more information.)
-
- When a C string appears in an argument list, C passes the address of the
- string. C can easily pass data to a fixed-length FORTRAN string.
-
- To pass strings to FORTRAN, make sure the called routine receives the string
- by reference and allocates sufficient space. FORTRAN should expect to
- receive fixed-length strings. Note, however, that C cannot pass
- variable-length strings to FORTRAN; the FORTRAN string data are not placed
- on the stack, but require special low-level variables found only in a
- FORTRAN program.
-
-
- 5.2.4.3 Pascal Strings
-
- Pascal has two types of strings, each of which uses a different format: a
- fixed-length type STRING and the variable-length type LSTRING.
-
- The format used for STRING is identical to the FORTRAN string format. The
- format of an LSTRING stores the length in the first byte. For example,
- consider an LSTRING declared as
-
- VAR STR:LSTRING(14);
- STR := 'String of text'
-
- The string is stored in 15 bytes of memory. The first byte indicates the
- length of the string text. The remaining bytes contain the string text
- itself:
-
- ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
- │14 │ S │ t │ r │ i │ n │ g │ │ o │ f │ │ t │ e │ x │ t │
- └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
- Pascal String Format
-
- The Pascal data type LSTRING is not compatible with the format used by
- FORTRAN. You can pass an LSTRING indirectly, however, by first assigning it
- to a STRING variable. Pascal supports such assignments by performing a
- conversion of the data. The Pascal STRING and the FORTRAN CHARACTER*n types
- are equivalent. Therefore, Pascal fixed-length string variables can be
- freely passed to FORTRAN.
-
-
- 5.2.4.4 FORTRAN Strings
-
- FORTRAN stores strings as a series of bytes at a fixed location in memory.
- Note that there is no delimiter at the end of the string as in C. Consider
- the string declared as follows:
-
- STR = 'String of text'
-
- The string is stored in 14 bytes of memory as:
-
- ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
- │ S │ t │ r │ i │ n │ g │ │ o │ f │ │ t │ e │ x │ t │
- └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
- FORTRAN String Format
-
- Strings are passed by reference, just like other FORTRAN data.
- Variable-length FORTRAN strings of type CHARACTER*(*) (available in
- Versions 4.0 and later) cannot effectively be passed to other languages.
- However, fixed-length strings can be passed without much difficulty; the
- principal limitation is that the FORTRAN INTERFACE must declare the length
- of the string in advance.
-
- By default, FORTRAN passes strings by reference. However, if you apply the C
- or PASCAL attribute to a routine, then the default changes to passing by
- value. The actual string data do not include a delimiter, unless you use the
- C-string feature described below.
-
- FORTRAN cannot directly pass strings to BASIC because BASIC expects to
- receive a string descriptor when passed a string. However, there is the
- following indirect method:
-
- 1. Allocate a fixed-length string in FORTRAN, declare an array of two-byte
- integers, and treat the array as a string descriptor.
-
- 2. Assign the address of the string to the first element (using the LOC
- function), and assign the length of the string to the second element.
-
- 3. Pass the integer array itself by reference. BASIC can receive and
- process this array just as it would a string descriptor.
-
- The C-string feature overrides the normal FORTRAN format and produces
- strings that can be effectively manipulated by C. When the C-string feature
- is used, a null byte is appended to the end of the string, and backslashes
- that appear in a literal-string text are treated as escapes.
-
- You convert FORTRAN strings to C strings by adding C immediately after a
- string constant. Do not insert commas or any other intervening punctuation,
- only spaces. Note that the length of the string increases by one byte
- because of the additional null byte. You need to allow for this when you
- declare string variables.
-
- The following FORTRAN example passes the address of a string to C. The
- string is in the C format.
-
- INTERFACE TO SUBROUTINE CONV [C] (S1)
- CHARACTER*5 S1 [REFERENCE]
- END
- C
- CHARACTER*5 S1
- S1 = 'abcd' C
- CALL CONV (S1)
-
- Note that an additional byte is allocated for S1, in consideration of the
- null byte added by the C-string conversion (done on the line above the
- call). Also note that the REFERENCE keyword was necessary because the C
- attribute in the first line changes the parameter-passing default to calling
- by value.
-
- FORTRAN and Pascal use the same fixed-length string types and can therefore
- easily pass strings between one another.
-
- FORTRAN modules should only pass fixed-length strings to Pascal. The Pascal
- routines, in turn, should expect to receive fixed-length strings. To specify
- a fixed-length string parameter in Pascal, you first need to declare a type,
- as in the example below.
-
- C FORTRAN SOURCE CODE
- C
- INTERFACE TO SUBROUTINE PS (S1)
- CHARACTER*4 S1
- END
- C
- S1 = 'wxyz'
- CALL PS (S1)
- END
-
- { Pascal module }
-
- module Psmod;
- type stype4 = string(4);
- procedure ps (vars str1 : stype4);
-
-
- 5.3 Handling Special Data Types
-
- Special types of data that are either structured (contain more than one
- field) or accessed externally need considerations beyond those already
- discussed. For example, not all languages index arrays in the same fashion.
- Custom structures created in one language may not interact properly with
- another language.
-
-
- 5.3.1 Arrays
-
- When programming with more than one language, be aware of two special
- problems specific to arrays:
-
- 1. Arrays are implemented differently in BASIC, so you must take special
- precautions when you pass an array from BASIC to FORTRAN.
-
- 2. Arrays are declared and indexed differently in each language.
-
- This section considers each of these problems in turn.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- Arrays cannot be passed by value in C, unless declared within a
- structure. However, it is usually most efficient to pass arrays by
- reference.
- ───────────────────────────────────────────────────────────────────────────
-
-
- 5.3.1.1 Cautions for Passing BASIC Arrays
-
- Most Microsoft languages permit you to reference arrays directly. In
- Microsoft FORTRAN, for example, an address name is equivalent to the address
- of the first element. This simple implementation is possible because the
- location of data for an array never changes.
-
- BASIC uses an "array descriptor," however, which is similar in some respects
- to a BASIC string descriptor. The array descriptor is necessary because
- BASIC may shift the location of array data in memory; BASIC handles memory
- allocation for arrays dynamically.
-
- FORTRAN does not have an equivalent to the BASIC array descriptor. More
- importantly, it lacks access to BASIC's space-management routines for
- arrays. Therefore, you may safely pass arrays from BASIC only if you follow
- these three rules:
-
- 1. Pass the array's address by applying the VARPTR function to the first
- element of the array and passing the result by value. To pass the far
- address of the array, apply both the VARPTR and VARSEG functions and
- pass each result by value. The receiving language gets the address of
- the first element and considers it to be the address of the entire
- array. Arrays can then be accessed with the normal array-indexing
- syntax. The example below illus-trates how this works.
-
- 2. The routine that receives the array must not, under any circumstances,
- make a call back to BASIC. If it does, then the location of the array
- data may change, and the address that was passed to the routine will
- become meaningless.
-
- 3. BASIC may pass any member of an array by value. With this method, the
- above precautions do not apply.
-
- The following example demonstrates how a BASIC array can be passed to
- FORTRAN:
-
- REM BASIC SOURCE FILE
- OPTION BASE 1
- DEFINT A-Z
- DIM A(20)
- DECLARE SUB ArrFix(BYVAL Addr AS INTEGER)
- .
- .
- .
- CALL ArrFix(VARPTR(A(1)))
- PRINT A(1)
- END
-
- C FORTRAN SOURCE FILE
- C
- SUBROUTINE ARRFIX (ARR)
- INTEGER*2 ARR [NEAR] (20)
- ARR(1) = 5
- END
-
- In this example, BASIC considers that the argument passed is the near
- address of an array element. FORTRAN considers it to be the near address of
- the array itself. Both languages are correct.
-
- The parameter was declared BYVAL Addr AS INTEGER because a near (two-byte)
- address needed to be passed. If you wanted to pass a far (four-byte)
- address, then the proper code would be the following:
-
- DECLARE SUB ArrFix (BYVAL SegAddr AS INTEGER,
- + BYVAL Addr AS INTEGER)
- CALL ArrFix (VARSEG(A(0)), VARPTR(A(0)))
-
- The first field is the segment returned by VARSEG. If you use CDECL, then be
- sure to pass the offset address before the segment address, because CDECL
- causes parameters to be passed in reverse order:
-
- DECLARE SUB ArrFix CDECL (BYVAL Addr AS INTEGER,
- + BYVAL SegAddr AS INTEGER)
- CALL ArrFix(VARPTR(A((0)), VARSEG(A(0)))
-
- Note that you can apply LBOUND and UBOUND to a BASIC array to determine
- lower and upper bounds and then pass the results to another routine. This
- way, the size of the array does not need to be determined in advance.
-
-
- 5.3.1.2 Array Declaration and Indexing
-
- Each language varies in the way that arrays are declared and indexed. Array
- indexing is purely a source-level consideration and involves no
- transformation of data. Following are the differences in the way elements
- are indexed by each language:
-
- Indexing Method Explanation
-
- Default lower boundary By default, FORTRAN indexes the
- first element of an array as 1.
- BASIC and C index it as 0. Pascal
- lets the programmer begin
- indexing at any integer value.
- Recent versions of Microsoft
- FORTRAN also give you the option
- of specifying lower bounds at any
- integer values.
-
- Row-major order vs. column-major Affects only arrays with more
- order than one dimension. With
- row-major order used by C and
- Pascal, the rightmost dimension
- changes the fastest. With
- column-major order used by
- FORTRAN, and BASIC by default,
- the leftmost dimension changes
- the fastest. Thus, in Pascal the
- first four elements of array
- X(3,3) are:
-
- X[1,1] X[1,2] X[1,3] X[2,1]
-
- In FORTRAN, the four elements
- are:
-
- X(1,1) X(2,1) X(3,1) X(1,2)
-
- The example above assumes that both the Pascal and FORTRAN arrays use lower
- bounds of 1. Table 5.2 shows equivalences for array declarations in each
- language. In this table, r is the number of elements of the row dimension
- (which changes more slowly), and c is the number of elements of the column
- dimension (which changes more quickly).
-
- Table 5.2 Equivalent Array Declarations
-
- Language Array Declaration Comments
-
- FORTRAN type x(c, r) With default lower
- bounds of 1
-
- C type x[r][c] When passed by
- reference
-
- struct When passed by value
- { type x[r][c];}x
-
- Pascal x:array[a..a+r-1, b..b+c-1] With default lower
- of type bounds of 1
-
- BASIC DIM x(c-1, r-1) With default lower
- bounds of 0
-
- The declarations above extend to any number of dimensions. For example, the
- C declaration
-
- int arr1 [2][10][15][20]
-
- is equivalent to the FORTRAN declaration
-
- INTEGER*2 ARR1(20, 15, 10, 2)
-
- Each of the following describes the same place in memory for an array in the
- respective language:
-
- ARR1(9,3) ! in FORTRAN, assuming lower bounds of 1
-
- arr1[2][8] /* in C */
-
- Arr1[3,9] {in Pascal, assuming lower bounds of 1}
-
- ARR1(8,2) (in BASIC, assuming lower bounds of 0)
-
- When you compile BASIC with the BC command line, select the /R compile
- option, specifying that row-major rather than column-major order is to be
- used.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- The constants used in a C array declaration represent dimensions, not
- upper bounds, as they do in other languages. Therefore, the last element
- in the C array declared as int arr[5][5] is not arr[5][5], but
- arr[4][4].
- ───────────────────────────────────────────────────────────────────────────
-
-
- 5.3.2 Structures, Records, and User-Defined Types
-
- The C struct type, the BASIC user-defined type, the FORTRAN STRUCTURE type,
- and the Pascal record type are equivalent. Therefore, these data types can
- be passed between C, Pascal, FORTRAN, and BASIC.
-
- However, these types may be affected by the storage method. By default, C,
- FORTRAN, and Pascal use word alignment (unpacked storage) for all data
- except byte-sized objects and arrays of byte-sized objects. Figure 5.1
- shows the contrast between packed and unpacked storage.
-
- The unpacked storage method specifies that occasional bytes may be added
- as padding, so that the word and double-word objects start on an even
- boundary. In addition, all nested structures and records start on a word
- boundary.
-
- If a structure or record is being passed between a calling routine and the
- called routine, both routines must agree on a storage method. Otherwise,
- data will not be properly received. The simplest method for ensuring
- compatibility between all three languages is to turn on packing for C,
- FORTRAN, and Pascal modules. The packed storage method may sacrifice some
- speed, but it has the advantage of creating smaller executable files.
-
- The following example shows how FORTRAN can create a structure. This same
- structure appears in FGRAPH.FD, the graphics library include file that
- initializes the graphics routines. Several of these graphics routines use
- similar structures for holding coordinates or pieces of related information.
-
- Example
-
- An example of the xycoord structure is shown below.
-
- INTERFACE TO SUBROUTINE getcurrentposition
- + [FAR, C, ALIAS:"__f_getcurrentposition"](s)
- STRUCTURE/xycoord/
- INTEGER*2 xcoord ! This example creates a structure
- INTEGER*2 ycoord ! containing two INTEGER*2 values
- END STRUCTURE
- RECORD/xycoord/s
- END
-
-
- 5.3.3 External Data
-
- You can always share data between FORTRAN and other languages by passing
- parameters. In the case of local variables and all BASIC variables, passing
- parameters is the only convenient way to share data.
-
- However, FORTRAN, C, and Pascal routines can access "external" data (data
- that can be directly accessed by any other module) directly. External refers
- to data that are both static and public──that is, data that you have stored
- in a specific place in memory (static data) and made publicly available to
- other modules. Compilers make a data object (variable, structure, or array)
- available by placing its name, along with size and type information, into
- the object file.
-
- External data can be defined in a FORTRAN, C, Pascal, or assembly module.
- Note that a data definition is distinct from an external declaration. A
- definition causes a compiler to create a data object; an external
- declaration informs a compiler that the object is to be found in another
- module.
-
- There are three requirements for programs that share external data between
- languages:
-
- 1. One of the modules must define the static data.
-
- You can define a static data object in a FORTRAN or C module by
- defining a data object outside all functions and subroutines. (Do not
- use the static keyword in C with a data object you wish to be public.)
-
- 2. The other modules that will access the data must declare the data as
- external.
-
- In FORTRAN and Pascal, you can declare data as external by adding the
- EXTERN attribute to the data declaration. In C, you can declare data as
- external by using an extern declaration, similar to the extern
- declaration for functions.
-
- 3. Naming-convention differences must be resolved.
-
- In FORTRAN and Pascal, you can adopt the C naming convention by
- applying the C attribute to the data declaration. Likewise in C, you
- can adopt the FORTRAN/Pascal/BASIC naming convention by applying
- fortran or pascal to the data declaration.
-
-
- Examples
-
- The examples below illustrate the general language features of external data
- described above.
-
- /* C source code */
-
- int thing1; /* Thing1 is public and static */
- extern int thing2; /* Thing2 is defined in another module */
- static int thing3; /* Thing3 is static, but not public */
-
- ctest()
- {
- .
- .
- .
- C FORTRAN SOURCE CODE
- C
- INTEGER*2 THING1 [C, EXTERN]
- INTEGER*2 THING2 [C]
- C
- C THING1 DEFINED IN ANOTHER MODULE, USING C CONVENTION (_thing1)
- C
- C THING2 DEFINED HERE, USING C CONVENTION (_thing2)
- .
- .
- .
-
- { Pascal source code }
-
- module Ptest;
- procedure Test;
- var
- thing1 [C, EXTERN] : integer; { Both vars defined elsewhere }
- thing2 [C, EXTERN] : integer; { and use C naming convention }
- .
- .
- .
-
- In these examples, the variables thing1 and thing2 are defined and
- declared with the C naming convention so they will be placed into each
- object file as _thing1 and _thing2. However, you can specify the FORTRAN/
- Pascal/BASIC naming convention by using the following C statements:
-
- int fortran thing1;
- extern int fortran thing2;
-
- The C attribute can then be dropped from the FORTRAN and Pascal source code.
- Each object file will contain the names THING1 and THING2.
-
-
- 5.3.4 Pointers and Address Variables
-
- Rather than pass data directly, you may want to pass the address of a piece
- of data. Passing the address is equivalent to passing the data by reference.
- In some cases, such as BASIC arrays (see Section 5.3.1.1), passing an
- address is the only way to share particular kinds of data between two
- languages.
-
- Unlike Pascal and C, FORTRAN does not have formal address types. How-ever,
- FORTRAN does provide ways for storing and passing addresses.
-
- FORTRAN programs determine near and far addresses with the LOC, LOCFAR, and
- LOCNEAR functions. You store the result as INTEGER*2 (with LOCNEAR) or as
- INTEGER*4 (with LOCFAR). LOC has the same purpose as LOCNEAR in the medium
- memory and as LOCFAR in the large memory model.
-
- If you pass the result of LOC, LOCNEAR, or LOCFAR to another language, be
- sure to pass by value.
-
-
- 5.3.5 Common Blocks
-
- You can pass individual members of a FORTRAN or BASIC common block in an
- argument list just as you can with any data. However, you can also give a
- different-language module access to the entire common block at once.
-
- Pascal and C modules can reference the items of a common block by first
- declaring a structure or record, with fields that correspond to the common
- block variables (see Section 5.3.5.1 below). BASIC modules also employ a
- user-defined type to access the fields of a FORTRAN common block.
-
- Having defined a structure, record, or user-defined type with the
- appropriate fields, the Pascal or C module must then connect with the common
- block itself. The next two sections present methods for gaining access to
- common blocks.
-
-
- 5.3.5.1 Passing the Address of the Common Block
-
- To pass the address of a common block, simply pass the address of the first
- variable in the block (that is, pass the first variable by reference.) The
- receiving C or Pascal module should expect to receive a structure or record
- by reference.
-
- Example
-
- In the example below, the C function initcb receives the address of the
- variable N, which it considers to be a pointer to a structure with three
- fields:
-
- C FORTRAN SOURCE CODE
- C
- COMMON /CBLOCK/N,X,Y
- INTEGER*2 N
- REAL*8 X,Y
- .
- .
- .
- CALL INITCB(N)
- .
- .
- .
- /* C source code */
-
- struct block_type {
- int n;
- double x;
- double y;
- };
-
- initcb(block_hed)
- struct block_type *block_hed;
- {
- block_hed->n = 1;
- block_hed->x = 10.0;
- block_hed->y = 20.0;
- }
-
-
- 5.3.5.2 Accessing Common Blocks Directly
-
- You can access FORTRAN common blocks directly by defining a structure (or
- record in Pascal) with the appropriate fields and then using the methods
- described in Section 5.3.3, "External Data."
-
-
- Example
-
- The example below declares cblock as an external structure. You can
- reference the individual fields of cblock which will correspond to those of
- the common block CBLOCK in the FORTRAN source file.
-
- struct block_type {
- int n;
- double x;
- double y;
- };
-
- extern struct block_type fortran cblock;
-
-
- 5.3.6 Using a Varying Number of Parameters
-
- Some C functions, most notably printf, can be called with a different number
- of arguments each time. To call such a function from FORTRAN, you need to
- sup-press the type checking that normally forces a call to be made with a
- fixed number of parameters. You can call such routines with a variable
- number of parameters by including the VARYING attribute in your interface to
- the routine, along with the C attribute. You must use the C attribute
- because a variable number of parameters is only feasible with the C calling
- convention.
-
- The VARYING attribute prevents FORTRAN from enforcing a matching number of
- parameters. Each time you call the routine, you will be able to pass more or
- fewer parameters than are declared in the interface to the routine. However,
- each actual parameter that you pass will be type checked against whatever
- formal parameters you have declared in the interface. FORTRAN compares the
- type of the first actual parameter to the first formal parameter (if any),
- the second actual parameter to the second formal parameter, and so on.
-
- Because the number of parameters is not fixed, the routine you call should
- have some mechanism for determining how many parameters to expect. Often
- this information is indicated by the first parameter. For example, the C
- function printf scans the format string passed as the first parameter. The
- number of fields in the format string determines how many additional
- parameters the function should expect.
-
- Example
-
- The example below demonstrates the use of the VARYING attribute to call
- printf directly from FORTRAN (the program needs to be compiled and linked to
- the C large memory model so that printf is linked in).
-
- INTERFACE TO INTEGER*2 FUNCTION printf [C, VARYING] ()
- END
-
- CHARACTER*30 str1, str2
- INTEGER*2 n, printf
- str1 = 'This is %s string, number %d.'C
- str2 = 'formatted'C
- n = 1
- n = printf(LOC(str1), LOC(str2), n)
- END
-
- In FORTRAN, you can write the interface to printf so that the format string
- can be of varying lengths, by using the LOC feature.
-
-
- Chapter 6 Record Structures: File Formats and Access
- ───────────────────────────────────────────────────────────────────────────
-
- This chapter describes the record structures (structure of files) created by
- Microsoft FORTRAN. The data format (or "form") and file access type define a
- "record structure." Each record structure has its own advantages, and
- depending on the application you have in mind, you may find that the ease of
- use of one type is more important than the greater speed or compact size of
- another.
-
- If you want more general information about FORTRAN input/output and file
- access, see Chapter 3, "The Input-Output System," in the Microsoft FORTRAN
- Reference.
-
-
- 6.1 Understanding Structures: Forms and Access Modes
-
- A "record" refers to one entry in a data file. All of the records within a
- single data file use the same method for storing information. Possible
- methods are:
-
- ■ Formatted
- ■ Unformatted
- ■ Binary
-
- You can send and retrieve information from a data file in one of two "access
- modes":
-
- ■ Sequential
- ■ Direct
-
- You can access sequential data one record after the other; direct data can
- be accessed by specifying which record in the file you want. Altogether, six
- record structures are possible: formatted sequential, formatted direct,
- unformatted sequential, unformatted direct, binary sequential, and binary
- direct. The following sections discuss each of these record structures in
- detail.
-
-
- 6.2 Using Formatted Records
-
- Formatted files are those files opened with FORM='FORMATTED'. They consist
- of a series of formatted records of ASCII characters. Each record ends with
- ASCII carriage-return (CR) and line-feed (LF) characters. If you are not
- concerned about compact size or high-speed data writing and retrieval,
- formatted files are typically the easiest structure to use. All internal
- files (character substrings, character variables, character array elements,
- character arrays, or noncharacter arrays) must be formatted.
-
-
- 6.2.1 Formatted Sequential Records
-
- A formatted sequential file is a series of formatted records written and
- read sequentially. Records may vary in length and may be empty, as shown in
- Figure 6.1.
-
- The following program fragment creates the formatted sequential file shown in
- Figure 6.2:
-
- I=4
- OPEN (33, FILE='FSEQ')
- C (FORMATTED SEQUENTIAL BY DEFAULT)
- WRITE (33, '(A,I3)') 'RECORD', I/3
-
- WRITE (33, '()')
- WRITE (33, '(11HThe 3rd One)')
- CLOSE (33)
- END
-
-
- 6.2.2 Formatted Direct Records
-
- In a formatted direct file, all of the records are exactly the same length
- and may be written or read in any order. The record length equals the length
- specified in the RECL= specifier, plus two bytes for the carriage-return
- (CR) and line-feed (LF) characters that serve as record separators. Prior to
- writing the record, these bytes are all undefined.
-
- If data does not completely fill a record, the compiler pads the remaining
- portion of the record with blank spaces. The blanks ensure that the file
- contains only completely filled records, all of the same length.
-
- The following program fragment creates the sample formatted direct file
- shown in Figure 6.3:
-
- OPEN (33, FILE='FDIR',FORM='FORMATTED',
- + ACCESS='DIRECT',RECL=10)
- WRITE (33, '(A)', REC=1) 'RECORD ONE'
-
- WRITE (33, '(I5)', REC=3) 30303
- CLOSE (33)
- END
-
-
- 6.3 Using Unformatted Records
-
- An unformatted file (FORM='UNFORMATTED') is a series of records composed of
- "physical blocks" as described below. Each record contains a sequence of
- values. The lack of formatting makes files of this type more compact than
- files that store the same information in a formatted form. Access is also
- faster than with formatted files.
-
-
- 6.3.1 Unformatted Sequential Records
-
- Unformatted sequential files must access data sequentially. Records may vary
- in length.
-
- Unformatted sequential files are organized in "chunks" of 130 bytes or less
- called "physical blocks." Each physical block consists of the data you send
- to the file (up to 128 bytes) plus two one-byte "length bytes" inserted by
- the compiler. The length bytes indicate the actual amount of data present.
-
- Figure 6.4 shows the physical block structure; each "L" represents a length
- byte.
-
- A "logical record" refers to an unformatted record, which contains one or
- more physical blocks (see Figure 6.5). Logical records can be as big as you
- like; the compiler will use as many physical blocks as necessary.
-
- When you create a logical record consisting of more than one physical block,
- the compiler sets the length byte to 129 to indicate that the data in the
- current physical block continues on into the next physical block. Then the
- length of the data portion of the last physical block in the record has a
- length (in bytes) of
-
- MOD (length, 128)
-
- where length equals the total data length in that logical record. (MOD is
- the remainder intrinsic function.) For example, if you write 140 bytes of
- data, the logical record has the structure shown in Figure 6.5.
-
- The first and last bytes in an unformatted sequential file are reserved;
- the first contains a value of 75, and the last holds a value of 130.
- FORTRAN uses these bytes for error checking and end-of-file references.
- Figure 6.6 illustrates these bytes in a sample unformatted sequential file.
-
- The following program fragment creates the unformatted sequential file shown
- in Figure 6.6:
-
- CHARACTER XYZ(3)
- INTEGER*4 IDATA (35)
- DATA IDATA /35 * -1/, XYZ /'x', 'y', 'z'/
- C
- C (-1 IS REPRESENTED BY FF FF FF FF HEXADECIMAL)
- C
- OPEN (33, FILE='UFSEQ',FORM='UNFORMATTED')
-
- C SEQUENTIAL BY DEFAULT)
- C
- C WRITE OUT A 140-BYTE RECORD (128 AND THEN 12 MORE)
- C FOLLOWED BY A 3-BYTE RECORD
-
- WRITE (33) IDATA
- WRITE (33) XYZ
- CLOSE (33)
- END
-
-
- 6.3.2 Unformatted Direct Records
-
- An unformatted direct file is a series of unformatted records. You can write
- or read the records in any order you choose. All records have the same
- length, given by the RECL= specifier. No delimiting bytes separate records
- or otherwise indicate record structure.
-
- You can write a partial record to an unformatted direct file. Version 5.0 of
- Microsoft FORTRAN pads these records to the fixed record length with ASCII
- NUL characters; in files created by versions of FORTRAN prior to 4.0, random
- values may be used to pad records. Unwritten records in the file contain
- undefined data, as shown in the sample unformatted direct file in Figure
- 6.7.
-
- The following program fragment creates the sample unformatted direct file
- shown in Figure 6.7:
-
- OPEN (33, FILE='UFDIR', RECL=10,
- + FORM = 'UNFORMATTED', ACCESS = 'DIRECT')
- WRITE (33, REC=3) .TRUE., 'abcdef'
- WRITE (33, REC=1) 2049
- CLOSE (33)
- END
-
-
- 6.4 Using Binary Records
-
- Specifying FORM='BINARY' is particularly useful when a FORTRAN program reads
- a file created by a program written in another language. Usually, such files
- do not have an internal structure or a file structure that corresponds to
- one of the standard FORTRAN file structures. Additionally, binary files are
- compact; if you store large amounts of data, consider a binary file format.
-
-
- 6.4.1 Binary Sequential Records
-
- A binary sequential file is a series of values written and read in the same
- order, and stored as binary numbers. No discernible record boundaries exist,
- and no special bytes indicate file structure. Data are read and written
- without changes in form or length. For any I/O list item, the sequence of
- bytes in memory is the sequence of bytes in the file (see Figure 6.8
- below).
-
-
- The following program creates the sample binary sequential file shown in
- Figure 6.8:
-
- $STORAGE:4
- INTEGER*1 BELLS(4)
- INTEGER IWYS(3)
- CHARACTER*4 CVAR
- DATA BELLS /4*7/
- DATA CVAR /' is '/,IWYS/'What',' you',' see'/
-
- C THIS PROGRAM WRITES THE SENTENCE
- C 'What you see is what you get!'
- C FOLLOWED BY FOUR BELL CHARACTERS (07 HEXADECIMAL)
-
- OPEN (33, FILE='BSEQ',FORM='BINARY')
-
- C (SEQUENTIAL BY DEFAULT)
-
- WRITE (33) IWYS, CVAR
- WRITE (33) 'what ', 'you get!'
- WRITE (33) BELLS
- CLOSE (33)
- END
-
-
- 6.4.2 Binary Direct Records
-
- A binary direct file stores records as a series of binary numbers,
- accessible in any order. Each record in the file has the same length, as
- specified by the RECL= argument to the OPEN statement.
-
- You can write partial records to binary direct files; any unused portion of
- the record will contain undefined data.
-
- A single read or write operation can transfer more data than a record
- contains by continuing the operation into the next record(s) of the file.
- Performing such an operation on an unformatted direct file would cause an
- error. Valid I/O operations for unformatted direct files produce identical
- results when they are performed on binary direct files, provided the
- operations do not depend on zero padding in partial records (see Figure
- 6.9 below).
-
- The following program fragment creates the sample binary direct file
- shown in Figure 6.9:
-
- $STORAGE:4
- OPEN (33, FILE='BDIR',RECL=10,
- + FORM='BINARY',ACCESS='DIRECT')
- WRITE (33, REC=1) 'abcdefghijklmno'
- WRITE (33) 4,5
- WRITE (33,REC=40) 'pq'
- CLOSE (33)
- END
-
-
- Chapter 7 Optimizing Programs
-
- ───────────────────────────────────────────────────────────────────────────
-
- This chapter discusses techniques for creating smaller and faster executable
- files with the Microsoft FORTRAN Compiler. Although some of these ideas
- apply to only a particular class of programs, others are general coding
- practices that can be used in virtually all programs.
-
- The topics covered include program structure and compiler options that
- improve the compiler's efficiency; coding strategies that decrease the size
- of data files created by a program; linking and memory usage strategies;
- conditions for using integer versus real variables; and the efficient use of
- arrays.
-
-
- 7.1 Compiling and Linking Strategies
-
- The various FORTRAN compiling and linking options enhance program control
- and debugging, but some of these options provide this control at the expense
- of size and speed. With a few judicious choices, you can shrink the size of
- your program files and sometimes increase their execution speed. The
- following sections cover the compiling and linking options that reduce the
- size of executable files and increase their speed.
-
-
- 7.1.1 Using Debugging and Integer-Size Options
-
- Three FL command-line options can significantly affect the amount of memory
- your source program requires: the /4Yb (debug), /Zi (CodeView debugging),
- and /4I2 (integer-size) options.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- The /4Yb and /4I2 options correspond to the $DEBUG and $STORAGE:2
- metacommands, respectively, and have the same effects.
- ───────────────────────────────────────────────────────────────────────────
-
- A program that includes the information generated by the debug option can
- contain up to 40 percent more code than the same program without the
- debugging information. After you successfully compile, link, and run a
- program, you can reduce its size and improve its execution speed by
- recompiling without the /4Yb option (or by removing the $DEBUG metacommands
- and recompiling).
-
- Similarly, the /Zi option prepares the code for debugging with the CodeView
- debugger. It produces an object file containing full symbolic debugging
- information──including the symbol table and line numbers──for use with the
- Microsoft CodeView window-oriented debugger. If you completed debugging with
- the CodeView debugger, you can reduce the file size by recompiling the
- finished program without the /Zi option.
-
- If your program does not require four bytes of storage for INTEGER and
- LOGICAL variables (that is, you do not explicitly need long integers or
- logicals), you can include the /4I2 option at compile time to reduce the
- size of gen-erated code. This option allocates two bytes (instead of four,
- the default) for each INTEGER and LOGICAL variable that you declare without
- an explicit length specification. This allocation shrinks program size
- because two-byte arithmetic operations require less supporting code than
- four-byte operations.
-
- The $DEBUG and $STORAGE metacommands are discussed in Chapter 6 in the
- Microsoft FORTRAN Reference.
-
-
- 7.1.2 Using 8087/287/387 Math Options
-
- When you compile your program, you can specify a floating-point option that
- selects the math package the program will use and the default library for
- linking. If you have an 8087, 80287, or 80387 math coprocessor, you can
- choose the /FPi87 or /FPc87 option, both of which generate instructions in
- your executable file for the coprocessor. If you link with a library that
- supports 8087/287/387 coprocessors (LLIBFOR7.LIB or MLIBFOR7.LIB), the
- resulting executable files will be smaller than executable files resulting
- from other math options. The math coprocessor also speeds up programs which
- make extensive use of floating-point calculations.
-
- Software emulation of the floating-point processors adds to the program's
- size. You may reduce the size of executable files by as much as 7K by
- choosing one of these coprocessor options. See Chapter 1, "Controlling
- Floating-Point Operations," for more information.
-
-
- 7.1.3 Using Overlays
-
- At link time, specifying appropriate program modules as overlays reduces
- file size. An overlay refers to two or more modules that use the same memory
- space when they execute. For example, assume two different modules, A and
- B, both contain routines needed by a main program (see Figure 7.1). If the
- main program calls a routine in module A, the program loads A from the
- disk into a particular space in memory. If the program later calls a routine
- in module B, the program loads module B into the same space previously
- occupied by module A.
-
- The program loads overlaid modules into the same memory space only when (and
- if) they are needed. In general, programs that use overlays are smaller and
- require less memory than programs that do not. However, programs that use
- overlays may run more slowly because of the additional time needed to read
- and reread the overlay code from disk into memory. (See Chapter 7 in the
- Microsoft FORTRAN Reference for more information about overlays.)
-
-
- 7.2 Coding Strategies
-
- The manner in which you write a program can dramatically affect both its
- speed and its size. The types and sizes of files, variables, and arrays you
- create──and how efficiently you use them──can enhance or detract from your
- program's performance.
-
- The following sections describe ways in which you can write source code to
- minimize the amount of data space the compiler needs and to minimize the
- object and executable file sizes.
-
-
- 7.2.1 Removing Error-Message Text during SETUP
-
- SETUP gives you two options for handling error messages: to build a library
- that displays the entire error message (the default) or a library that
- displays only the number of the error message, which you can then look up in
- Appendix D of the Microsoft FORTRAN Reference. Using a library without the
- error-message text results in an executable file approximately 2K smaller
- than the default.
-
-
- 7.2.2 Using Consistent File-Access and Format Types
-
- Each file format (formatted, unformatted, or binary) and access type
- (sequential or direct) requires that the compiler incorporate specific
- supporting code in your program. If the design of your program permits, try
- to restrict file access to the smallest number of access types and formats.
-
-
- 7.2.3 Specifying Edit Lists
-
- The edit lists you specify for I/O statements significantly affect the
- number of run-time routines supporting your program. If you remove
- formatting information or reference the same specifier for multiple calls,
- such as three WRITE statements referencing the same FORMAT statement, you
- decrease the space of your program. The following sections offer specific
- hints for reducing code size.
-
-
- 7.2.3.1 Left Tabbing
-
- The TL edit descriptor (or using the T edit descriptor to do left tabbing)
- increases the size of your executable files. The run-time code used to
- support left tabbing is included whenever the compiler detects the explicit
- use of these edit descriptors, or when a variable is used to contain the
- format string using the descriptor. As a result, you can reduce the size of
- your executable files if you avoid using left tabbing whenever possible.
- (See Chapter 3 of the Microsoft FORTRAN Reference for a description of the
- TL and T edit descriptors.)
-
-
- 7.2.3.2 Formatted or List-Directed I/O
-
- You will create smaller executable files if you consistently use either
- formatted or list-directed I/O statements and avoid mixing the two. This
- will require fewer run-time routines to support your program and therefore
- decrease its size.
-
-
- 7.2.3.3 Character Variables as Format Specifiers
-
- Microsoft FORTRAN translates format strings into a more compact internal
- form wherever possible. However, if the format is specified as a character
- vari-able, this translation must occur at run time instead of compile time.
- The associated run-time code for this adds significantly to the size of the
- executable file. As a result, you create smaller executable files if you use
- character constants or FORMAT statements as format specifiers. (See Chapter
- 3 of the Microsoft FORTRAN Reference for a description of these
- alternatives.)
-
-
- 7.2.4 Using the BLOCKSIZE Option
-
- Using the BLOCKSIZE option in OPEN statements allows you to choose an
- appropriate trade-off between execution speed and memory requirements for
- your program.
-
- The BLOCKSIZE option gives you control over the size of the internal buffer
- associated with each file your program opens. This buffer is designed to
- speed up execution time when your program reads or writes a large number of
- small items to a file. By default, the run-time system assigns a buffer size
- of 1,024 bytes for sequential-access files. However, you can use the
- BLOCKSIZE option to allocate a buffer of a different size.
-
- Using the BLOCKSIZE option gives you the following trade-off between program
- speed and memory requirements:
-
- ■ Larger buffer sizes speed up I/O operations but increase the amount of
- memory allocated for these operations.
-
- ■ Smaller buffer sizes result in slower I/O, but they save memory for
- other purposes.
-
- Since the buffers are only allocated when the file is opened, using the
- option BLOCKSIZE will not affect the size of the program's executable file.
- However, as a program approaches the memory limits of the machine, a smaller
- buffer size might allow the program to stay within those limits.
-
- The value that you specify for the BLOCKSIZE option only indirectly
- determines the buffer. The value is rounded up to a multiple of 512 for a
- sequential-access file for performance reasons. DOS normally formats disks
- into 512-byte sectors and performs I/O operations to and from disk files in
- accordance with these sector boundaries. Therefore, the most efficient I/O
- occurs when the buffer size is also a multiple of 512 for sequential-access
- files. (See Chapter 3 of the Microsoft FORTRAN Reference for an explanation
- of the rules for determining the actual buffer sizes of direct-access and
- terminal files.)
-
- Therefore, if you specify BLOCKSIZE = 1800 when you open a sequential file,
- the actual buffer size will be the next multiple of 512 not less than 1,800,
- or 2,048 (4 * 512). BLOCKSIZE will support buffers up to a maximum of 32,256
- bytes; any values passed to BLOCKSIZE larger than this will result in a
- buffer of 32,256 bytes.
-
-
- 7.2.5 Using Integer and Real Variables
-
- Although most FORTRAN programs use both floating-point and integer data,
- programs that use only integer data are considerably smaller than programs
- that use floating-point data. Remember, too, that in some situations you can
- use integers in place of floating-point numbers. Depending on the situation,
- you may be able to multiply your numbers by a known factor to convert them
- to integers, perform any manipulations, and convert them back for final
- printing.
-
- If you write a program that uses only integer data (for example, a program
- that prints out the time but does nothing else), remember either to
- explicitly declare variables with type INTEGER, or to use variable names
- that begin with letters that default to INTEGER type. By default, these are
- the letters "I" through "N." Use the IMPLICIT statement to specify different
- default letters for each type. (See Chapter 4 of the Microsoft FORTRAN
- Reference for more information.)
-
-
- 7.2.6 Using Arrays and EQUIVALENCE Statements
-
- The ways in which you declare arrays and use them in EQUIVALENCE statements
- can significantly affect the amount of information needed to compile your
- program. The use of arrays may affect whether the compiler runs out of
- memory when processing your source files. The fewer assumptions the compiler
- must make about the types and uses of arrays, the more efficient the
- compilation.
-
- The following sections offer suggestions for using arrays in ways that
- minimize the amount of data the compiler requires.
-
-
- 7.2.6.1 Minimizing Constant Use in Array Declarations
-
- If possible, minimize the number of different constants you use in array
- declarations. Also, place array declarations that use the most constants
- first. These actions improve efficiency during compilation because the
- compiler saves copies of the constants and reuses the copies, if possible.
-
- The two examples below illustrate this. You compile the declarations shown
- in the first example more efficiently by declaring the variables X, Y, and Z
- with the same bounds, as shown in the second example:
-
- INTEGER X(11), Y(10), Z(11)
-
- INTEGER X(11), Y(11), Z(11)
-
- If it is necessary to declare array Y with a bound of 10, the program would
- compile more efficiently by placing the declarations of X and Z──which have
- the same constant bounds──first, as in the example below:
-
- INTEGER X(11), Z(11)
-
- INTEGER Y(10)
-
-
- 7.2.6.2 Minimizing Items Declared in Each Type Statement
-
- Declare as few items as possible in each type statement. This reduces the
- complexity of each declaration and, as a result, saves the compiler data
- space when processing each declaration. This technique has an especially
- significant effect for array declarations.
-
-
- 7.2.6.3 Declaring Array Types before Dimensioning
-
- Explicitly declare an array's type before you dimension it. Also, before you
- use arrays in EQUIVALENCE statements, make sure that each array in the
- statement list has been completely declared, dimensioned, and (if necessary)
- declared in a COMMON statement.
-
- The examples below show how to declare the array A to use memory most
- efficiently during compilation.
-
- INTEGER A(10,20)
-
- INTEGER A
- DIMENSION A(10,20)
-
- INTEGER A
- COMMON A(10,20)
-
- In the declarations shown below, the compiler requires extra data space
- because the type of the array X is not given before X is used in the
- EQUIVALENCE statement.
-
- DIM X(20)
- EQUIVALENCE (X(1), J)
- INTEGER X
-
- In the following declarations, the compiler requires extra data space
- because it cannot determine the types of A and B until it has processed
- the second line; it does not know that B is an array until it has processed
- the second line, and it does not know that A and B are in a common block
- until it has processed the third line:
-
- EQUIVALENCE (A(10,20), B)
- INTEGER A, B(20,30)
- COMMON /CBA/A, /CBB/B
-
- In each case, the compiler must make assumptions that increase the amount of
- processing and the amount of data space it needs to hold intermediate
- processing results. To improve efficiency, rewrite the declarations as
- follows:
-
- INTEGER A(10,20), B(20,30)
- COMMON /CBA/A, /CBB/B
- EQUIVALENCE (A(10,20), B(1,1))
-
- In this series of declarations, the compiler knows immediately that A and B
- refer to two-dimensional integer arrays and the size of each. The subsequent
- references to A and B leave no ambiguities for the compiler.
-
-
- ───────────────────────────────────────────────────────────────────────────
-
- Part 2 The Microsoft FORTRAN Graphics Library
-
- Part 2 introduces the Microsoft FORTRAN Graphics Library and its use. The
- graphics library supports traditional pixel-based routines such as line
- drawing, in addition to a collection of font routines that can scale and
- print text in a variety of typefaces. Numerous examples in the chapters and
- reference section show how the routines are actually used.
-
-
- Chapter 8 Graphics Library Routines
- ───────────────────────────────────────────────────────────────────────────
-
- The Microsoft FORTRAN DOS run-time graphics library includes a complete set
- of graphics functions. It supports pixel-based graphics, real-coordinate
- graphics, and character fonts. In addition, the associated text-based
- routines are also available under OS/2. This chapter introduces the major
- categories of library routines and their use. Chapters 9 and 10 cover
- graphics and fonts, respectively, in more detail. For a complete description
- of the syntax and use of each individual routine, see Chapter 11, "Graphics
- Library Reference."
-
- Review the contents of this chapter carefully. It provides an overview of
- all of the routines, and introduces some important fundamental concepts.
- Several of the routines affect the output of other routines; reading the
- entire chapter will give you an understanding of how the different classes
- of routines interact.
-
- You can access this graphics library from Microsoft FORTRAN as well as other
- Microsoft languages that support the FORTRAN calling conventions. The
- graphics package supports the IBM(R) (and compatible) Enhanced Graphics
- Adapter (EGA) ; the Color Graphics Adapter (CGA) ; the Multicolor Graphics
- Array (MCGA); certain operating modes of the Video Graphics Array (VGA)
- hardware configuration; and the Olivetti(R) video mode present on AT&T
- personal computers. The package also supports the Hercules(R) Graphics Card,
- Graphics Card Plus, InColor Card, and 100-percent compatible cards.
-
-
- 8.1 Using Graphics and Character-Font Functions
-
- The graphics and font routines are supplied in a run-time library, named
- GRAPHICS.LIB, that you must link to your programs using graphics; the OS/2
- library GRTEXTP.LIB supports the text-based graphics routines. Graphics
- routines are functions and subroutines that draw lines, rectangles,
- ellipses, and similar graphic elements on the screen. The font routines
- allow your computer to create text in a variety of styles, sizes, and
- colors.
-
- Every program using the graphics library must also explicitly declare any
- routines it uses. This means that you will need to either write an interface
- to each routine you call, or reference the include files FGRAPH.FI and
- FGRAPH.FD; the OS/2 library GRTEXTP.LIB uses these same files. The FGRAPH.FI
- include file contains procedure declarations in INTERFACE statements; the
- include file FGRAPH.FD contains both structure and symbolic constant
- declarations and EXTERNAL statement declarations for the graphics
- procedures. Together, they contain the declarations necessary to access all
- of the graphics library routines. To use them, include FGRAPH.FI at the
- beginning of your program's source files, and FGRAPH.FD in every subprogram
- that calls a graphics routine.
-
- The GRAPHICS.LIB run-time library includes routines corresponding to the
- various tasks involved in creating and manipulating graphics:
-
- Category Task
-
- Configuring mode and drawing Selects the proper display mode
- environment for the hardware and establishes
- memory areas for the writing and
- displaying of images
-
- Setting coordinates Specifies the origin and the
- display area on the screen
-
- Setting graphics palettes Specifies colors available to
- graphics routines
-
- Setting attributes Specifies background and
- foreground colors and mask and
- line styles for graphics routines
-
- Displaying images Draws and fills figures on the
- screen
-
- Outputting text Writes text to the screen
-
- Transferring images Stores images in memory and
- retrieves them
-
- Displaying fonts Displays text in specified fonts
- compatible with Microsoft Windows
- 286/386
-
- The following sections explain each of these tasks in detail. Note that many
- of the graphics routine names exceed 6 characters, so avoid using the
- $TRUNCATE metacommand in programs that call graphics routines.
-
-
- 8.2 Defining Graphics Characteristics
-
- Before you are actually ready to create graphics on your screen, you must
- invoke routines that define the way both text and graphics will be
- displayed. Sections 8.2.1-8.2.4 discuss four groups of these routines.
-
-
- 8.2.1 Selecting Display Options
-
- The Microsoft FORTRAN run-time graphics library contains a number of
- routines that let you define how you want to display text and graphics.
- These routines determine the graphics environment characteristics, establish
- operational modes (text or graphics), and control the cursor.
-
- Routine Use
-
- displaycursor Turns the cursor back on or
- leaves the cursor off after
- executing a graphics routine
-
- getvideoconfig Obtains information about the
- current graphics environment
-
- setactivepage Sets the memory location for the
- working page; lets you animate
- objects
-
- settextrows Sets the number of rows available
- for standard text output
-
- setvideomode Sets a display mode for the
- screen
-
- setvideomoderows Sets the display mode and the
- number of rows available for
- standard text output
-
- setvisualpage Sets a memory location for the
- display page
-
- The displaycursor routine lets you control whether the cursor will be
- restored after completing a graphics routine. Either setting you choose
- remains in effect until the next time you call the routine.
-
- The getvideoconfig routine returns information about the current hardware
- environment. This information is used by several of the other routines. (For
- example, getvideoconfig returns the value of screen size needed by
- videoconfig.)
-
- The setactivepage and setvisualpage routines set aside memory for the
- working page and the displayed page, respectively, in configurations that
- support multiple video pages.
-
- The setvideomode routine selects an operating mode (such as the resolution)
- for the monitor. The settextrows routine sets the number of text rows to be
- displayed. The setvideomoderows routine combines the two previous functions;
- it sets the display mode and the number of text rows available.
-
-
- 8.2.2 Setting Graphics Coordinates
-
- The coordinate-setting routines control where graphics may appear on the
- screen. Microsoft FORTRAN graphics routines recognize three sets of
- coor-dinates:
-
- 1. Fixed "physical coordinates," which are determined by the hardware and
- the configuration routines used
-
- 2. "Viewport coordinates," which you define in the application
-
- 3. "Window coordinates," which you define to simplify scaling of
- floating-point data values
-
- Unless you change it, the viewport-coordinate system is identical to the
- physical- coordinate system. The physical origin (0, 0) is always in the
- upper left corner of the display. The x-axis extends in the positive
- direction left to right, while the y-axis extends in the positive direction
- top to bottom.
-
- The routines also let you convert between physical-, viewport-, and
- window-coordinate systems. (For more detailed information on coordinate
- graphics, see Chapter 9, "Drawing Graphic Elements.")
-
- Routine Use
-
- getcurrentposition Determines current position in
- viewport coordinates
-
- getcurrentposition_w Determines current position in
- window coordinates
-
- getphyscoord Converts viewport coordinates to
- physical coordinates
-
- getviewcoord Converts physical coordinates to
- viewport coordinates
-
- getviewcoord_w Converts window coordinates to
- viewport coordinates in xycoord
- structure
-
- getwindowcoord Converts viewport coordinates to
- window coordinates
-
- setcliprgn Limits graphic output to part of
- the screen
-
- setvieworg Positions the viewport-coordinate
- origin
-
- setviewport Limits graphic output and
- positions the viewport-coordinate
- origin within a limited area
-
- setwindow Defines a window-coordinate
- system
-
- The dimensions of the x- and y-axes depend on the configuration routine
- used and the current mode (text or graphics). These values are accessible
- through the numxpixels and numypixels values returned by getvideoconfig.
- Similarly, getvideoconfig also returns the range of colors available in the
- current mode through the bitsperpixel value.
-
- The origin of the viewport-coordinate system can be moved to a new position
- relative to the physical origin with the setvieworg routine. However, you
- can still determine the location of any point with the getcurrentposition
- and getcurrentposition_w routines.
-
- The window-coordinate system lets you easily scale any set of data to fit on
- the screen. You define whatever range of coordinates works well for your
- data (such as 0 to 5,000) as the range for the window-coordinate axes. By
- telling the program that you want the window-coordinate system to fit in a
- particular area on the screen (map to a particular set of viewport
- coordinates), you can scale a chart or drawing to any size you wish. The
- setwindow routine defines a window-coordinate system bound by the specified
- values.
-
- The getphyscoord routine converts any viewport coordinates to physical
- coordinates, and the getviewcoord routine translates from physical
- coordinates to viewport coordinates. Similarly, getviewcoord_w changes
- window coordinates to viewport coordinates, and getwindowcoord translates
- viewport coordinates into window coordinates.
-
- The setcliprgn routine defines a restricted active display area on the
- screen (a "clipping region"). The setviewport function does the same thing
- and also resets the viewport origin to the upper left corner of the clipping
- region.
-
-
- 8.2.3 Setting Palettes
-
- Each color on the screen is represented by a unique value called a "color
- index." To associate a color index with the color on the screen, the
- graphics library uses the concept of a "palette." A palette is simply a
- "mapping" (association) of color indexes to the actual display colors.
-
- The palette routines assign colors to the functions and subroutines that
- draw in color. They can also alter the colors of items already drawn on the
- screen.
-
- The three palette routines determine the mapping between the color indexes
- and the colors drawn on the screen.
-
- Routine Use
-
- remapallpalette Assigns a color index to all of
- the displayable colors
-
- remappalette Assigns a color index to a
- specific color
-
- selectpalette Selects a predefined palette
-
- Depending on the particular graphics mode, a one-, two-, four-, or eight-bit
- value represents each screen pixel. This bit-value representation of a
- color called the "color value," is often required by routines as one of
- their arguments.
-
- Most video modes support only one palette. If you select the
- medium-resolution graphics mode $MRES4COLOR, $MRESNOCOLOR, or $ORESCOLOR,
- however, you can access multiple palettes. (In these modes, the palette
- consists of a background color and three other colors.) The selectpalette
- routine selects a particular palette from the available palettes.
-
- EGA and VGA hardware also provide the capability of remapping a palette,
- allowing any available color index to be mapped to any color value. Two
- routines allow the EGA and VGA to provide this capability: the remappalette
- function remaps one color value, and remapallpalette remaps the entire
- palette.
-
- The remappalette, remapallpalette, setbkcolor, and getbkcolor routines are
- the only routines that recognize color values defined for the EGA or VGA.
-
- Many graphics routines operate only on certain hardware or in certain
- graphics modes. These routines return an error code if you use them on an
- invalid hardware environment. The reference section (Chapter 11) indicates
- which routines return error information; if you use these routines, be sure
- to check the returned value for any errors.
-
-
- 8.2.4 Setting Figure Attributes
-
- The output routines that draw arcs, ellipses, and other primitive figures do
- not specify color or line-style information. Instead, they rely on several
- "attributes" set independently by the routines listed below.
-
- Routine Use
-
- getbkcolor Returns the current background
- color
-
- getcolor Returns the current color
-
- getlinestyle Returns the current line style
-
- getfillmask Returns the current fill mask
-
- setbkcolor Sets the current background color
- to a new color
-
- setcolor Sets the current color to a new
- color
-
- setfillmask Sets the current fill mask to a
- new color
-
- setlinestyle Sets the current line style to a
- new line style
-
- The getcolor and setcolor routines obtain or set the "current color"
- attribute, which the floodfill routine and the closed-figure drawing
- routines all use. Similarly, the getbkcolor and setbkcolor routines retrieve
- or set the "current background color," used by the clearscreen function.
-
- The getfillmask and setfillmask routines return or set the "current fill
- mask" attribute. The mask is an 8-by-8-bit array with each bit representing
- a pixel. If a bit is 0, the pixel in memory is left untouched: the mask is
- transparent to that pixel. If a bit is 1, the pixel is assigned the current
- color value. The array acts as a template that repeats over the entire fill
- area. It "masks" the background with a pattern of pixels drawn in the
- current color, creating a large number of fill patterns. These routines are
- particularly useful for shading and slight color-variation effects.
-
- The getlinestyle and setlinestyle routines retrieve and set the "current
- line style." The line style is determined by a 16-bit-long template with
- each bit cor-responding to a pixel. If a bit is 0, the pixel keeps the
- current background color (that is, appears transparent). If a bit is 1, the
- pixel appears in the current color. The template repeats over the entire
- length of the line. The two routines let you create a wide variety of dashed
- lines.
-
-
- 8.3 Displaying Graphics Output
-
- The remaining graphics routines actually allow you to draw geometric
- features, display text, display font-based characters, and transfer images
- between memory and the screen. These routines are described in Sections
- 8.3.1-8.3.3.
-
-
- 8.3.1 Creating a Graphics Display
-
- The Microsoft FORTRAN run-time graphics library routines draw geometric
- figures using the coordinate system you specify. They use the current line
- style, fill mask, background color, and foreground color.
-
- If you want anything other than the default line style (solid), mask (no
- mask), background color (green), or foreground color (highest index on the
- current palette), you must call the appropriate routine prior to calling the
- drawing routine. Subsequent output routines employ the same attributes until
- they are changed.
-
- The name of each routine describes its task or the figure it draws.
-
- Routine Use
-
- arc, arc_w Draws an arc
-
- clearscreen Erases the screen (fills it with
- the current background color)
-
- ellipse, ellipse_w Draws an ellipse or circle
-
- floodfill, floodfill_w Fills an area of the screen with
- the current mask in the current
- color
-
- getcurrentposition, Finds the coordinates of the
- getcurrentposition_w current graphic-output position
-
- getpixel, getpixel_w Returns a pixel's value
-
- lineto, lineto_w Draws a line from the current
- graphic-output position to a
- specified point
-
- moveto, moveto_w Moves the current graphic-output
- position to a specified point
-
- pie, pie_w Draws a pie-slice-shaped figure
-
- rectangle, rectangle_w Draws a rectangle
-
- setpixel, setpixel_w Sets a pixel's value
-
- Most of these routines have multiple forms. Routine names that end with "_w"
- use the window-coordinate system and DOUBLE PRECISION argument values.
- Routines without this suffix use the viewport-coordinate system.
-
- Curved figures, such as arcs and ellipses, are centered within a "bounding
- rectangle," which is specified by the upper left and lower right corners of
- the rectangle. The center of the rectangle becomes the center for the
- figure, and the rectangle's borders determine the size of the figure. In
- Figure 8.1 the points (x1, y1) and (x2, y2) define the bounding rectangle.
-
-
- 8.3.2 Displaying Text
-
- These routines let you send text to the screen in both graphics and text
- modes. The routines for outputting text in specialized fonts are described
- in Chapter 10, "Using Fonts from the Graphics Library." Unlike the standard
- I/O statements, these routines recognize the text-window boundaries used in
- applications that use windows.
-
- Routine Use
-
- displaycursor Sets the cursor on or off after
- leaving a graphics routine
-
- gettextcolor Returns the current text color
-
- gettextcursor Returns the current cursor
- attribute (text modes only)
-
- gettextposition Returns the current text-output
- position
-
- outtext Sends text to the screen at the
- current position
-
- settextcolor Sets the current text color to a
- new color
-
- settextcursor Sets the current cursor attribute
- (text modes only)
-
- settextposition Relocates the current text
- position
-
- settextwindow Sets the current text-display
- window
-
- wrapon Turns line wrapping on or off
-
- These routines do not provide text-formatting capabilities. If you want to
- print integer or floating-point values, you must convert the values into a
- string (using an internal WRITE statement) before calling these routines.
- The text routines specify all screen positions in character-row and column
- coordinates.
-
- The settextwindow routine is the text equivalent to the setcliprgn graphics
- routine, except that it restricts only the display area for text printed
- with outtext. It does not affect the standard I/O statements, such as WRITE.
- The outtext routine displays a string on the screen. You can retrieve or
- alter the current text color with the gettextcolor and settextcolor
- routines, respectively. The routines gettextposition and settextposition let
- you determine or change the location of the next text sent to the screen.
-
- ───────────────────────────────────────────────────────────────────────────
- WARNING
- The WRITE statement sends its carriage return (CR) and line feed (LF) to
- the screen at the beginning of the first I/O statement following the
- WRITE statement. This can cause unpredictable text positioning if you mix
- the graphics routines settextposition and settext with the WRITE
- statement. Minimize this effect by using the backslash (\) format
- descriptor (suppress CR-LF) in the associated FORMAT statement.
- ───────────────────────────────────────────────────────────────────────────
-
- The wrapon function enables or disables automatic "line wrapping." Line
- wrapping ends a line of text and starts a new one when a word at the end of
- a line is too long. Without line wrapping the same word would be split,
- often incoherently, at the end of the first line, with the remainder
- appearing on the next line.
-
-
- 8.3.3 Transferring Images
-
- The getimage and putimage groups of routines transfer images between mem-ory
- and the screen. When you hold an image in memory, the application allocates
- a buffer (that is, it sets aside part of the computer's memory) for the
- image. The imagesize routines calculate the size in bytes of the buffer
- needed to store a given image.
-
- Routines that end with "_w" use window coordinates; the other functions in
- this set use viewport coordinates.
-
- Routine Use
-
- getimage, getimage_w Stores a screen image in memory
-
- imagesize, imagesize_w Returns image size in bytes
-
- putimage, putimage_w Retrieves an image from memory
- and displays it
-
- In systems that support multiple pages, you can send graphics to a page in
- memory while displaying another page. Once you complete the page in memory,
- display it on the screen and begin drawing a new page in memory. By
- repeating this process you can animate objects on the screen.
-
-
- 8.3.4 Displaying Font-Based Characters
-
- Since the FORTRAN Graphics Library provides a variety of fonts, indicate
- which font you wish to use when displaying font-based characters. Once you
- select a font, you can make inquiries about the width of a string or the
- current font characteristics. The following functions control the display of
- font-based characters.
-
- Routine Use
-
- getfontinfo Returns the current font
- characteristics
-
- getgtextextent Determines the width of specified
- text in the current font
-
- outgtext Sends text in the current font to
- the screen at the specified pixel
- position
-
- registerfonts Initializes the font library
-
- setfont Finds a single font that matches
- a specified set of
- characteristics and makes this
- font the current font for use by
- the outgtext function
-
- unregisterfonts Frees memory allocated by
- registerfonts
-
- Characters may be drawn ("mapped") in one of two ways: as bit-mapped letters
- (a "picture" of the letter) or as vector-mapped characters (a series of
- lines and arcs that make up a letter). See Chapter 10, "Using Fonts from
- the Graphics Library," for detailed explanations and examples of how to
- apply fonts and the characteristics of the fonts supplied with Microsoft
- FORTRAN.
-
-
- 8.4 Routines Available under OS/2
-
- The OS/2 graphics library, GRTEXTP.LIB, contains the text-based routines
- available under DOS. The functionality and use of the OS/2 routines are the
- same as DOS, and the descriptions in Chapter 11, "Graphics Library
- Reference," all apply. When linking, however, you need to supply GRTEXTP.LIB
- in place of the DOS GRAPHICS.LIB. Note that both DOS and OS/2 use the same
- graphics include files.
-
- The library GRTEXTP.LIB supports the following routines:
-
- clearscreen getvisualpage settextwindow
- displaycursor outtext setvideomode
- getactivepage setactivepage setvideomoderows
- getbkcolor setbkcolor setvisualpage
- gettextcolor settextcolor wrapon
- gettextcursor settextcursor
- gettextposition settextposition
- getvideoconfig settextrows
-
-
-
- Chapter 9 Drawing Graphic Elements
- ───────────────────────────────────────────────────────────────────────────
-
- Graphics can make your screens and data more understandable and informative.
- All of the building blocks needed to create a wide variety of drawings are
- discussed in this chapter. The chapter assumes you have read the overview
- presented in Chapter 8. Note that the OS/2 graphics library, GRTEXTP.LIB,
- does not support font-based routines. Refer to Chapter 8 for a list of the
- OS/2 routines available under DOS.
-
- The DOS graphics routines provided with the Microsoft FORTRAN Compiler set
- points, draw lines, change colors, and draw shapes such as circles,
- rectangles, and arcs. The first section defines some basic graphics terms,
- lists the steps to using high-resolution graphics, and works through a
- sample program step by step, showing how to use the elementary routines. The
- remaining sections explain coordinate systems in detail and how to display
- graphics inside viewports and windows.
-
-
- 9.1 Working with Graphics Modes
-
- Before your program can begin drawing graphic elements, you must specify the
- type of monitor being used, the desired screen resolution, and whether to
- display in color or black and white──in short, the "mode" you want to use
- when displaying graphics. This section shows you how to determine an
- appropriate graphics mode; how to make that mode active; and how to write a
- typical graphics program.
-
- This chapter refers to the following terms frequently. Be sure you are
- familiar with them:
-
- ■ The "origin" (point 0,0) is the upper left corner of your screen. The
- x- and y-axes start at the origin. You can change the origin in some
- coordinate systems.
-
- ■ The horizontal direction is represented by the x-axis. The maximum
- number of horizontal "pixels" (picture elements) varies between 320 and
- 720, depending on the graphics card installed and the graphics mode in
- effect.
-
- ■ The vertical direction is represented by the y-axis. The number of
- vertical pixels ranges from 200 to 480.
-
- ■ Each graphics mode offers a color palette. You may access 2, 4, 8, 16,
- or 256 "color indexes" (an index number associated with a specific
- screen color), depending on the graphics card in the computer and the
- graphics mode in effect.
-
- ■ The CGA modes use four fixed "palettes" containing predefined colors
- that cannot be changed. The EGA, MCGA, and VGA modes allow you to
- change any of the color indexes by providing a color value that
- describes the mix of colors you want to use.
-
- ■ A color index is always an INTEGER*2 number. A color value is always an
- INTEGER*4 value. When you call graphics routines that require
- color-related parameters, be aware of the difference between color
- indexes and color values. (See Section 9.2.1.2, "Color Mixing.")
-
- To prepare a system to display graphics, you need to
-
- 1. Use the getvideoconfig procedure to find the type of video adapter
- installed. (See Section 9.1.1, "Checking the Current Video Mode.")
-
- 2. Set the desired graphics mode for the adapter with the setvideomode
- procedure. (See Section 9.1.2, "Setting the Video Mode.")
-
- 3. Draw the graphics. (See Section 9.1.3, "Writing a Graphics Program.")
-
- When you finish creating the graphics, remember to return to the default
- text mode before leaving the program.
-
- ───────────────────────────────────────────────────────────────────────────
- WARNING
- You must always explicitly link the graphics library. See Chapter 7, "The
- FL Command," of the Microsoft FORTRAN Reference for information about
- linking libraries.
- ───────────────────────────────────────────────────────────────────────────
-
-
- 9.1.1 Checking the Current Video Mode
-
- In order to avoid compatibility problems, call the getvideoconfig routine
- before entering a video mode. Information about the current system is
- returned in the videoconfig structure defined in FGRAPH.FD and outlined in
- the program example below.
-
- The videoconfig structure is defined below. You need to recognize the fields
- and their usage because several other graphics routines require them as
- arguments:
-
- STRUCTURE/videoconfig/
- INTEGER*2 numxpixels ! Number of pixels on x-axis
- INTEGER*2 numypixels ! Number of pixels on y-axis
- INTEGER*2 numtextcols ! Number of text columns available
- INTEGER*2 numtextrows ! Number of text rows available
- INTEGER*2 numcolors ! Number of color indexes
- INTEGER*2 bitsperpixel ! Number of bits per pixel
- INTEGER*2 numvideopages ! Number of available video pages
- INTEGER*2 mode ! Current video mode
- INTEGER*2 adapter ! Active display adapter
- INTEGER*2 monitor ! Active display monitor
- INTEGER*2 memory ! Adapter video memory in K bytes
- END STRUCTURE
-
- You initialize the fields in a structure variable of type videoconfig when
- you call getvideoconfig.
-
-
- 9.1.2 Setting the Video Mode
-
- Once you know the current video configuration, you must tell the graphics
- adapter to switch from text mode to graphics mode. To do this, call the
- setvideomode routine. This routine will pass a constant to the adapter that
- tells the adapter which mode to display (see Table 9.1)
-
- The include file FGRAPH.FD defines these names as symbolic constants with
- the appropriate values. The screen dimensions for each mode are listed in
- pixels for graphics modes and in columns for text modes. The mode
- type/hardware column indicates the expected environment.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- If you use a Hercules adapter, you must run the MSHERC.COM program before
- attempting to display any graphics.
- ───────────────────────────────────────────────────────────────────────────
-
- If setvideomode returns a 0, the hardware does not support the selected
- mode. You can continue to select alternate video modes until the routine
- returns a nonzero value. You might use a sequence of high- to low-resolution
- calls to the setvideomode routine in order to choose the highest resolution
- available. The SELECT CASE constructs work particularly well. If the
- hardware configuration does not support any of the selected video modes, the
- program cannot display graphics.
-
- Table 9.1 below shows the names for the different video modes.
-
- Table 9.1 Video Modes for Text and Graphics
-
- Constant Video Mode Mode Type/Hardware
-
- $DEFAULTMODE Restores to original mode Both/All
-
- $TEXTBW40 40 column text, 16 gray Text/CGA
-
- $TEXTC40 40 column text, 16/8 color Text/CGA
-
- $TEXTBW80 80 column text, 16 gray Text/CGA
-
- $TEXTC80 80 column text, 16/8 color Text/CGA
-
- $MRES4COLOR 320 x 200, 4 color Graphics/CGA
-
- $MRESNOCOLOR 320 x 200, 4 gray Graphics/CGA
-
- $HRESBW 640 x 200, BW Graphics/CGA
-
- $TEXTMONO 80 column text, BW Text/MDA
-
- $HERCMONO 720 348, BW for HGC Graphics/HGC
-
- $MRES16COLOR 320 x 200, 16 color Graphics/EGA
-
- $HRES16COLOR 640 x 200, 16 color Graphics/EGA
-
- $ERESNOCOLOR 640 x 350, BW Graphics/EGA
-
- $ERESCOLOR 640 x 350, 4 or 16 color Graphics/EGA
-
- $VRES2COLOR 640 x 480, BW Graphics/VGA/
- MCGA
-
- $VRES16COLOR 640 x 480, 16 color Graphics/VGA
-
- $MRES256COLOR 320 x 200, 256 color Graphics/VGA/
- MCGA
- $ORESCOLOR 640 400, 1 of 16 colors
-
- $MAXCOLORMODE See Tables R.5 and R.6 for Graphics/CGA
- maximum colors
-
- $MAXRESMODE See Tables R.5 and R.6 for Graphics/CGA
- maximum resolution
-
-
- 9.1.3 Writing a Graphics Program (SINE)
-
- Like many programs, graphics programs work well in modular form. The use of
- discrete routines aids debugging by isolating the separate functional
- components of the program. The following program and its associated
- subroutines illustrate the processes involved in initializing, drawing, and
- closing a graphics program.
-
- The SINE program creates a sine wave. Its procedures use many of the common
- graphics routines. The main program (see below) follows a modular structure,
- calling five functions which carry out the actual graphics commands. All of
- the functions are defined later in this chapter.
-
- CC SINE.FOR - Illustrates basic graphics commands.
-
- INCLUDE 'FGRAPH.FI'
-
- CALL graphicsmode()
- CALL drawlines()
- CALL sinewave()
- CALL drawshapes()
- CALL endprogram()
- END
-
- C Definitions of subroutines go here
- .
- .
- .
-
- The SINE program's output appears in Figure 9.1.
-
-
- 9.1.3.1 Activating a Graphics Mode
-
- Before your program can display graphics, you must specify a graphics mode.
- Your program can then call setvideomode to set the video adapter to the
- appropriate graphics mode.
-
- SINE turns on the graphics mode by calling the subroutine graphicsmode
- below. The subroutine selects the highest possible resolution for the
- current video adapter (such as CGA and VGA).
-
- SUBROUTINE graphicsmode()
-
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy, maxx, maxy
- RECORD /videoconfig/ myscreen
- COMMON maxx, maxy
-
- C
- C Find graphics mode.
- C
- CALL getvideoconfig( myscreen )
- SELECT CASE( myscreen.adapter )
- CASE( $CGA )
- dummy = setvideomode( $HRESBW )
- CASE( $OCGA )
- dummy = setvideomode( $ORESCOLOR )
- CASE( $EGA, $OEGA )
- IF( myscreen.monitor .EQ. $MONO ) THEN
- dummy = setvideomode( $ERESNOCOLOR )
- ELSE
- dummy = setvideomode( $ERESCOLOR )
- END IF
- CASE( $VGA, $OVGA, $MCGA )
- dummy = setvideomode( $VRES2COLOR )
- CASE( $HGC )
- dummy = setvideomode ( $HERCMONO )
- CASE DEFAULT
- dummy = 0
- END SELECT
-
- IF( dummy.EQ.0) STOP 'Error: cannot set graphics mode'
-
- C
- C Determine the minimum and maximum dimensions.
- C
- CALL getvideoconfig( myscreen )
- maxx = myscreen.numxpixels - 1
- maxy = myscreen.numypixels - 1
- END
-
- The subroutine begins by calling getvideoconfig and passes the address of
- the videoconfig structure myscreen. In videoconfig, the element called
- "adapter" tells the subroutine the type of adapter in use. Given that
- information and a SELECT CASE block, the program enters the appropriate
- graphics mode.
-
- To find the resolution of the video mode the program chose, you must pass
- the videoconfig structure to the getvideoconfig routine, using the same
- structure:
-
- CALL getvideoconfig( myscreen )
- maxx = myscreen.numxpixels - 1
- maxy = myscreen.numypixels - 1
-
- If your computer uses an EGA card, the subroutine graphicsmode sets the
- video mode to $ERESNOCOLOR. The horizontal screen size is 640 pixels and the
- vertical screen size is 350. The two assignments give these values
- to maxx and maxy, less 1. The horizontal resolution might be 640, but the
- pixels are numbered 0-639. Thus, the maxx variable──the highest available
- pixel number──must be 1 less than the total number of pixels:
-
- myscreen.numxpixels - 1.
-
- Two short functions convert from an imaginary 1,000-by-1,000-pixel screen to
- whatever video mode is in effect. From now on, the program assumes it has
- 1,000 pixels in each direction. To draw the points on the
- screen, newx and newy change each point to their physical (pixel)
- coordinates, as follows:
-
- CC NEWX - This function finds new x-coordinates.
-
- INTEGER*2 FUNCTION newx( xcoord )
-
- INTEGER*2 xcoord, maxx, maxy
- REAL*4 tempx
- COMMON maxx, maxy
-
- tempx = maxx / 1000.0
- tempx = xcoord * tempx + 0.5
- newx = tempx
- END
-
- CC NEWY - This function finds new y-coordinates.
-
- INTEGER*2 FUNCTION newy( ycoord )
-
- INTEGER*2 ycoord, maxx, maxy
- REAL*4 tempy
- COMMON maxx, maxy
-
- tempy = maxy / 1000.0
- tempy = ycoord * tempy + 0.5
- newy = tempy
- END
-
-
- 9.1.3.2 Drawing Lines on the Screen
-
- SINE calls the subroutine drawlines next. As the name implies, this
- subroutine draws several lines on the screen. In this case, a rectangle
- around the outer edges of the screen and three horizontal lines that divide
- the screen into quarters are drawn (see Figure 9.1 above).
-
- CC DRAWLINES - This subroutine draws a box and
- CC several lines.
-
- SUBROUTINE drawlines()
-
- INCLUDE 'FGRAPH.FD'
-
- EXTERNAL newx,newy
- INTEGER*2 dummy, newx, newy, maxx, maxy
- RECORD /xycoord/ xy
- COMMON maxx, maxy
-
- C
- C Draw the box.
- C
- dummy = rectangle( $GBORDER, 0, 0, maxx, maxy )
- CALL setvieworg( 0, newy( INT2( 500 ) ), xy )
- C
- C Draw the lines.
- C
- CALL moveto( 0, 0, xy )
- dummy = lineto( newx( INT2( 1000 ) ), 0 )
- CALL setlinestyle( #AA3C )
- CALL moveto( 0, newy( INT2( -250 ) ), xy )
- dummy = lineto(newx(INT2( 1000 ) ),
- + newy( INT2( -250 ) ) )
- CALL setlinestyle( #8888 )
- CALL moveto( 0, newy( INT2( 250 ) ), xy )
- dummy = lineto( newx( INT2( 1000 ) ),
- + newy( INT2( 250 ) ) )
- END
-
- The first argument to the rectangle routine is the "fill flag," which may be
- either $GBORDER or $GFILLINTERIOR. Choose $GBORDER if you want a rectangle
- of four lines (a border only, in the current line style). Choose
- $GFILLINTERIOR if you want a solid rectangle (filled in with the current
- color and fill pattern). Choosing the color and fill pattern is discussed
- later in this chapter (see Tables 9.1-9.3).
-
- The second and third arguments are the x- and y-coordinates of the upper
- left corner of the rectangle. The fourth and fifth arguments are the
- coordinates for the opposite (lower right) corner. Since the coordinates for
- the two corners are ( 0, 0 ) and ( maxx, maxy ), the call to rectangle
- frames the screen:
-
- dummy = rectangle( $GBORDER, 0, 0, maxx, maxy )
-
- The call to the setlinestyle routine changes the line style from a solid
- line to a dashed line. A series of 16 bits tells the routine the pattern to
- follow. A "1" indicates a solid line segment and "0" an empty segment.
- Therefore, to the computer, a solid line looks like 1111 1111 1111 1111. A
- dashed line might look like 1111 1111 0000 0000 (long dashes) or 1111 0000
- 1111 0000 (short dashes). You may choose any combination of 1s and 0s. The
- 16-bit binary number also may be represented as a hexadecimal or decimal
- number. In the example below, the hexadecimal constant #AA3C equals the
- binary value 1010 1010 0011 1100. However you could use the decimal value
- 43,580 as the argument just as effectively.
-
- To draw lines, first set any appropriate line style. Then move to where you
- want the line to begin and draw from that point to where you want the line
- to end. The SINE program, for example, uses the following:
-
- CALL setlinestyle( #AA3C )
- CALL moveto( 0, newy( INT2( -250 ) ), xy )
- dummy = lineto( newx( INT2( 1000 ) ),
- + newy( INT2( -250 ) ) )
-
- The moveto routine positions an imaginary pixel cursor at a spot on the
- screen (nothing visible appears on the screen), and the lineto routine draws
- a line. The negative value -250 might seem to be an impossible screen
- coordinate. How-ever, the program calls setvieworg and changes the
- viewport-coordinate system to run from -500 at the top of the screen to +500
- at the bottom. Admittedly, this goes against intuitive convention, but
- illustrates the routine's ability to alter the viewport coordinates (or, to
- "viewport") to whatever dimensions or orientation you prefer. (Viewports and
- the setvieworg routine are explained in more detail in Section 9.3.2.1.)
-
-
- 9.1.3.3 Drawing the Sine Curve
-
- With the axes and frame in place, SINE is ready to draw the sine curve. The
- sinewave routine calculates the x and y positions for two cycles of the sine
- wave and plots them on the screen:
-
- CC SINEWAVE - This subroutine calculates and plots a sine
- CC wave.
-
- SUBROUTINE sinewave()
-
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy, newx, newy, locx, locy, i
- DOUBLE PRECISION rad, PI
- EXTERNAL newx, newy
-
- PARAMETER ( PI = 3.14159 )
-
- C
- C Calculate each position and display it on the screen.
- C
- DO i = 0, 999, 3
- rad = -SIN( PI * i / 250.0 )
- locx = newx( i )
- locy = newy( INT2( rad * 250.0 ) )
- dummy = setpixel( locx, locy )
- END DO
- END
-
- The graphics routine setpixel takes the two location parameters, locx and
- locy, and turns on the pixel at that position.
-
-
- 9.1.3.4 Adding Shapes
-
- After drawing the sine curve, the SINE program calls drawshapes to put two
- rectangles and two ellipses on the screen. The fill flag alternates between
- $GBORDER and $GFILLINTERIOR:
-
- CC DRAWSHAPES - Draws two boxes and two ellipses.
-
- SUBROUTINE drawshapes()
-
- INCLUDE 'FGRAPH.FD'
-
- EXTERNAL newx, newy
- INTEGER*2 dummy, newx, newy
-
- C
- C Create a masking (fill) pattern.
- C
- INTEGER*1 diagmask(8), linemask(8)
- DATA diagmask / #93, #C9, #64, #B2, #59, #2C,
- + #96, #4B /
- DATA linemask / #FF, #00, #7F, #FE, #00, #00,
- + #00, #CC /
- C
- C Draw the rectangles.
- C
-
- CALL setlinestyle( #FFFF )
- CALL setfillmask( diagmask )
- dummy = rectangle( $GBORDER,
- + newx( INT2( 50 ) ), newy( INT2( -325 ) ),
- + newx( INT2( 200 ) ), newy( INT2( -425 ) ) )
- dummy = rectangle( $GFILLINTERIOR,
- + newx( INT2( 550 ) ), newy( INT2( -325 ) ),
- + newx( INT2( 700 ) ), newy( INT2( -425 ) ) )
- C
- C Draw the ellipses.
- C
- CALL setfillmask( linemask )
- dummy = ellipse( $GBORDER,
- + newx( INT2( 50 ) ), newy( INT2(325 ) ),
- + newx( INT2( 200 ) ), newy( INT2(425 ) ) )
- dummy = ellipse( $GFILLINTERIOR,
- + newx( INT2( 550 ) ), newy( INT2( 325 ) ),
- + newx( INT2( 700 ) ), newy( INT2( 425 ) ) )
- END
-
- Note that setlinestyle resets the line pattern to solid. If you omit this
- routine, the first rectangle would be drawn with dashes instead of a solid
- line.
-
- The ellipse routine draws an ellipse using parameters similar to those for
- the rectangle routine, both requiring a fill flag and two corners of a
- bounding rectangle. (Figure 8.1 in Chapter 8 shows how an ellipse uses a
- bounding rectangle.)
-
- The $GFILLINTERIOR flag fills the shape with the current fill pattern. To
- create a pattern, you must pass the address of an eight-byte array of
- unsigned bytes to the setfillmask routine. Then diagmask is initialized with
- the pattern shown in Table 9.1.
-
- Table 9.1 Fill Patterns
- ───────────────────────────────────────────────────────────────────────────
-
- Bit Pattern Value in diagmask
- Bit No. 7 6 5 4 3 2 1 0
-
- █ █ █ █ diagmask(0) = #93
-
- █ █ █ █ diagmask(1) = #C9
-
- █ █ █ diagmask(2) = #64
-
- █ █ █ █ diagmask(3) = #B2
-
- █ █ █ █ diagmask(4) = #59
-
- █ █ █ diagmask(5) = #2C
-
- █ █ █ █ diagmask(6) = #96
-
- █ █ █ █ diagmask(7) = #4B
-
-
- 9.1.3.5 Exiting Graphics Mode
-
- The final routine called by the SINE program, the endprogram, waits for the
- ENTER key to be pressed and then sets the screen back to normal:
-
- CC ENDPROGRAM - This subroutine waits for the ENTER key to
- CC be pressed, then resets the screen before
- CC returning.
-
- SUBROUTINE endprogram()
-
- INCLUDE 'FGRAPH.FD'
- INTEGER*2 dummy
-
- READ (*,*) ! Wait for ENTER to be pressed
- dummy = setvideomode( $DEFAULTMODE )
- END
-
- Note that resetting the screen is an important step in any graphics program.
- Other applications may make assumptions about your monitor and its
- resolution with unpredictable results. These assumptions could conflict with
- any changes your program made to the current graphics mode. Resetting to the
- original mode resolves any potential conflicts.
-
-
- 9.2 Adding Color
-
- The Microsoft FORTRAN Graphics Library supports CGA, EGA, and VGA color
- graphics. Color can add variety and impact to your graphics, but it must be
- suited to your application.
-
- Color graphics can be an improvement over black and white, but using color
- requires a compromise. When you request the maximum number of colors, you
- sacrifice some resolution──a maximum resolution of 320-by-200 pixels instead
- of a higher resolution. For example, the program COLOR (see Section
- 9.2.1.5) always selects the highest possible resolution. In a color mode,
- the program always creates a screen only 320 pixels wide and 200 pixels
- high.
-
-
- 9.2.1 Color Graphics Modes
-
- The Microsoft FORTRAN Graphics Library has graphics modes particular to each
- of the CGA, EGA, and VGA adapters. In addition, higher resolution hardware
- can support the lower resolution modes. That is, EGA and VGA hardware can
- both display the CGA modes, and VGA hardware can also display EGA modes. Any
- hardware that supports color graphics modes also supports the
- black-and-white graphics modes.
-
-
- 9.2.1.1 CGA Color Graphics Modes
-
- The CGA color graphics modes $MRES4COLOR and $MRESNOCOLOR display four
- colors selected from one of several predefined color palettes. They display
- these foreground colors against a background color, which can be any one of
- the 16 available colors. With the CGA hardware, the palette of foreground
- colors is predefined and cannot be changed. Each palette number is an
- integer, as shown in Table 9.2.
-
- Table 9.2 Available CGA Colors
-
- Color Index
-
- Palette
- Number 1 2 3
- 0 Green Red Brown
- 1 Cyan Magenta Light gray
- 2 Light green Light red Yellow
- 3 Light cyan Light magenta White
-
- On black-and-white monitors, the $MRESNOCOLOR graphics mode produces
- palettes containing various shades of gray. It displays colors when used
- with a color display. However, only two palettes are available with a color
- display. You can use the selectpalette routine to select one of these
- predefined palettes. Table 9.3 shows the $MRESNOCOLOR color indexes and
- palettes.
-
- Table 9.3 CGA Colors: $MRESNOCOLOR Mode
-
- Color Index
- Palette
- Number 1 2 3
- 0 Blue Red Light gray
- 1 Light blue Light red White
-
- The selectpalette routine works only with the graphics modes $MRES4COLOR and
- $MRESNOCOLOR. To change palettes in other graphics modes, use the
- remappalette or remapallpalette functions.
-
- The following program sets the video mode to $MRES4COLOR and then cycles
- through the background colors and palette combinations. It works on
- computers equipped with CGA, EGA, MCGA, or VGA cards and requires a color
- monitor.
-
- CC CGA.FOR - Demonstrates CGA colors.
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy2, i, j, k
- INTEGER*4 dummy4
- INTEGER*4 bkcolor(8) /
- + $BLACK, $BLUE , $GREEN, $CYAN,
- + $RED , $MAGENTA, $BROWN, $WHITE /
-
- CHARACTER*7 bkcolorname(8) /
- + 'BLACK', 'BLUE' , 'GREEN', 'CYAN',
- + 'RED' , 'MAGENTA', 'BROWN', 'WHITE' /
-
- RECORD / rccoord / curpos
-
- IF( setvideomode( $MRES4COLOR ) .EQ. 0 )
- + STOP 'Error: cannot set CGA graphics mode'
-
- DO i = 0, 3
- dummy2 = selectpalette( i )
- DO k = 1, 8
- dummy4 = setbkcolor( bkcolor(k) )
- DO j = 0, 3
- CALL settextposition( 1, 1, curpos )
- WRITE (*, 9000) bkcolorname(k), i, j
- dummy2 = setcolor( INT4( j ) )
- dummy2 = rectangle( $GFILLINTERIOR,
- + 160, 100, 320, 200 )
- READ (*,*) ! Wait for ENTER to be pressed
- END DO
- END DO
- END DO
- dummy2 = setvideomode( $DEFAULTMODE )
-
- 9000 FORMAT( ' background color: ', A / ' palette:', I3 /
- + ' color: ', I3 / )
-
- END
-
-
- 9.2.1.2 Color Mixing
-
- At the beginning of this chapter, we mentioned the difference between color
- indexes and color values. Imagine an analogy: a painter owns 64 tubes of
- paint but has a palette only large enough to hold 16 globs of paint. A
- painting created under these constraints could contain only 16 colors
- (selected from a total of 64).
-
- One of the EGA graphics modes ($ERESCOLOR) is similar: 16 color indexes
- chosen from a total of 64 color values. Color indexes are sometimes called
- "color attributes," or "pixel values"; color values are sometimes called
- "actual colors."
-
- The VGA offers the widest variety of color values: 262,144 (256K). The VGA
- palette size may contain 2, 16, or 256 color indexes, depending on the
- graphics mode. When you select a color value, you specify a level of
- intensity with a range of 0-63 for each of the red, green, and blue color
- values. The long integer that defines a color value consists of four bytes
- (32 bits),
-
- MSB LSB
- zzzzzzzz zzBBBBBB zzGGGGGG zzRRRRRR
-
- where z refers to zero and B, G, and R represent the bit values for blue,
- green, and red intensities. The most significant byte (MSB ) must contain
- all zeros. The two high bits in the remaining three bytes must also be 0. To
- mix a light red (pink), turn red all the way up and mix in some green and
- blue:
-
- 00000000 00100000 00100000 00111111
-
- In hexadecimal notation this number equals #0020203F. You could also use the
- statement function
-
- RGB (r,g,b) = (#3f3f3f.AND.(ISHFT(b,16).OR.ISHFT(9,8).OR.r))
-
- where r, g, and b were previously declared as integers.
-
- You can pass decimal values (more familiar and intuitive to most of us) to
- this macro. Keep in mind that 1 (binary 00000001) represents a low color
- intensity and that 63 (binary 00111111) equals full color intensity. Then,
- to create pure yellow (100-percent red plus 100-percent green) and assign it
- to a variable y1, use this line:
-
- y1 = RGB( 63, 63, 0 )
-
- For white, turn all of the colors on:
-
- RGB( 63, 63, 63 )
-
- For black, set all of the colors to 0:
-
- RGB( 0, 0, 0 )
-
- Mixing colors in EGA modes is similar to the mixing described above, but
- there are fewer intensities for the red, green, and blue components. In the
- modes that offer 64 colors, the R, G, and B values cover only two bits and
- can therefore range from decimal 0 to 3. The integer that defines an RGB
- color looks like this:
-
- MSB LSB
- zzzzzzzz zzBB???? zzGG???? zzRR????
-
- The bits marked z must be zeros and the bits marked with question marks can
- be any value (although zeros tend to improve readability). To form a pure
- red color value, you would use the hexadecimal constant #00000030. For cyan
- (blue plus green), use #00303000. The RGB statement function defined above
- is easily modified for EGA monitors:
-
- EGARGB (r,g,b) = ( #303030 .AND.1 ( ISHFT( b,20 )
- + .OR.ISHFT( g,12 ).OR.ISHFT( r,4 ) ) )
-
- In this statement function, you would pass values in the range of 0-3
- instead of 0-63. You could now assign the pure red as
-
- r1 = EGARGB( 0,0,3 )
-
-
- 9.2.1.3 EGA Color Graphics Modes
-
- The $MRES16COLOR, $HRES16COLOR, or $ERESCOLOR video modes display color
- graphics best with an EGA adapter. The CGA modes will also display on the
- EGA adapter, but with lower resolution and decreased color options.
-
- The remappalette routine assigns a new color value to a color index. For
- example, when you first enter an EGA graphics mode, color index 1 equals the
- color value blue. To reassign the pure red color value to color index 1, you
- could use this line:
-
- dummy4 = remappalette( 1, #000030 )
-
- Or, use the symbolic constant $RED, which is defined in the FGRAPH.FI file:
-
- dummy4 = remappalette( 1, $RED )
-
- After this routine call, any object currently drawn in color index 1 will
- instantly switch from blue to red.
-
- For EGA graphics, the first value is an integer in the range of 0-15, and
- the second value is an INTEGER*4 defined as a mixture of red, green, and
- blue.
-
- The remapallpalette routine changes all of the color indexes simultaneously.
- You pass it an array of color values. The first color value in the list
- becomes the new color associated with the color index 0, the second becomes
- associated with the color index 1, and so on.
-
- The argument passed to routines that set colors (such as setcolor) is the
- index for a color in the current palette. In the default text palette, an
- index of 1 refers to blue. When a palette changes, a color's index number
- also changes. As a result, the color produced by a given index number also
- changes. If you create a drawing in one palette and then change the palette,
- the color indexes will suddenly refer to different colors and the entire
- drawing will change color. The number of color indexes available depends on
- the number of colors supported by the current video mode.
-
- The remappalette and remapallpalette routines work in all modes but only
- with the EGA, MCGA, or VGA hardware. The routines remappalette and
- remapallpalette fail and return a value of -1 if you attempt to remap a
- palette without the necessary hardware.
-
- The following program draws a rectangle with a red interior. In the default
- EGA palette, color index 4 is red. In the program EGA, this color index is
- changed to $BLUE.
-
- CC EGA.FOR - Demonstrates use of EGA palettes.
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy2
- INTEGER*4 dummy4
- RECORD /xycoord/ xy
-
- dummy2 = setvideomode( $ERESCOLOR )
- dummy2 = setcolor( 4 )
- dummy2 = rectangle( $GFILLINTERIOR, 50, 50, 200, 200 )
- C
- C Display normal palette message.
- C
- CALL settextposition( 1, 1, xy )
- CALL outtext( 'Normal palette ')
- CALL outtext( 'Press ENTER to continue')
- READ (*,*) ! Wait for ENTER to be pressed
- dummy4 = remappalette( 4, $BLUE )
- C
- C Display new palette message.
- C
- CALL settextposition( 1, 1, xy )
- CALL outtext( 'Remapped palette ')
- CALL outtext( 'Press ENTER to continue')
- READ (*,*)
- dummy4 = remappalette( 4, $RED )
- C
- C Display original palette message.
- C
- CALL settextposition( 1, 1, xy )
- CALL outtext( 'Restored palette ')
- CALL outtext( 'Press ENTER to clear the screen')
- READ (*,*)
- C
- C Return to original video mode.
- C
- CALL clearscreen( $GCLEARSCREEN )
- dummy2 = setvideomode( $DEFAULTMODE )
- END
-
-
- 9.2.1.4 VGA Color Graphics Modes
-
- The VGA card adds graphics modes $VRES2COLOR, $VRES16COLOR, and
- $MRES256COLOR to your repertoire. EGA and CGA modes are available with the
- VGA hardware, providing either lower resolution or fewer color choices.
-
- The VGA color graphics modes operate with a range of 262,144 (256K) color
- values. The graphics mode $VRES2COLOR displays 2 colors, the graphics mode
- $VRES16COLOR displays 16 colors, and the graphics mode $MRES256COLOR
- displays 256 colors from the available VGA colors.
-
- The remappalette routine changes a color index to a specified color value.
- The following function remaps the color index 1 to the color value given by
- the symbolic constant $RED. After this statement is executed, whatever was
- displayed as blue will now appear as red:
-
- remappalette( 1, dummy 4=$RED ) ! Reassign color index 1
- ! to VGA red
-
- The remapallpalette routine remaps one or more color indexes simultaneously.
- The routine's argument references an array of color values that reflect the
- remapping. The first color number in the list becomes the new color
- associated with color index 0, the second with color index 1, and so on.
-
- Symbolic constants (names) for the default color numbers are supplied so
- that the remapping of VGA colors is compatible with EGA practice. The names
- are self-descriptive: the color numbers for black, light yellow, and red are
- represented by the symbolic constants $BLACK, $LIGHTYELLOW, and $RED.
-
- All of the VGA display modes operate with any VGA monitor. Colors appear as
- shades of gray on compatible monochrome monitors.
-
- The example program HORIZON illustrates the impact possible with the full
- range of 256 colors available with a VGA card:
-
- CC HORIZON.FOR - Illustrates VGA graphics with cycling of
- CC 256 colors.
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 MYRED, MYBLU, MYWHT, STEP
- PARAMETER ( MYRED = #000003FF )
- PARAMETER ( MYBLU = #003F0000 )
- PARAMETER ( MYWHT = #003F3F3F )
- PARAMETER ( STEP = 21 )
-
- INTEGER*2 dummy, i, j
- INTEGER*4 rainbow(0:511), col, ngray
-
-
- RECORD /rccoord/ curpos
- RECORD /xycoord/ xy
- C
- C Check to see if adapter can handle 256 colors.
- C
- IF( setvideomode( $MRES256COLOR ) .EQ. 0 )
- + STOP 'This program requires a VGA card.'
- C
- C Create the colors.
- C
- DO col = 0, 63
- ngray = ( col .OR. ISHFT( col,8 ) )
- + .OR. ISHFT( col,16 )
- rainbow( col) = MYBLU .AND. ngray
- rainbow( col + 256) = rainbow( col )
- rainbow( col + 64) = MYBLU .OR. ngray
- rainbow( col + 64 + 256) = rainbow( col + 64 )
- rainbow( col + 128) = MYRED .OR.
- + ( MYWHT .AND. .NOT. ngray )
- rainbow( col + 128 + 256) = rainbow( 64 + 128 )
- rainbow( col + 192) = MYRED .AND. .NOT. ngray
- rainbow( col + 192 + 256) = rainbow( col + 192 )
- END DO
- CALL setvieworg( 160, 85, xy )
- C
- C Draw shapes on screen.
- C
- DO i = 0, 254
- dummy = setcolor( INT4( 255 - i ) )
- CALL moveto( i, i - 255, xy )
- dummy = lineto( -i, 255 - i )
- CALL moveto( -i, i - 255, xy )
- dummy = lineto( i, 255 - i )
- dummy = ellipse( $GBORDER, -i, -i / 2, i, i / 2 )
- END DO
- C
- C Cycle through the colors.
- C
- i = 0
- DO j = 1, 256
- dummy = remapallpalette( rainbow(i) )
- i = MOD( i + STEP, 256 )
- END DO
-
- dummy = settextcolor( 15 )
- CALL settextposition( 25, 1, curpos )
- CALL outtext( 'Press ENTER to exit')
- READ (*,*)
- dummy = setvideomode( $DEFAULTMODE )
- END
-
-
- 9.2.1.5 Color Graphics Programs (COLOR and GRAPHIC)
-
- The sample program COLOR sets a mode with as many colors as possible for the
- available hardware:
-
- CC COLOR.FOR - Sets a medium resolution mode
- CC with maximum color choices.
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy
- RECORD /videoconfig/ vc
-
- C
- C Set mode for maximum number of colors.
- C
- IF( setvideomode( $MAXCOLORMODE ) .EQ. 0 )
- + STOP 'Error: no color graphics capability'
- CALL getvideoconfig( vc )
-
- WRITE (*, 9000) vc.numcolors, vc.numxpixels,
- + vc.numypixels
- READ (*,*) ! Wait for ENTER to be pressed
- CALL clearscreen( $GCLEARSCREEN )
- dummy = setvideomode( $DEFAULTMODE )
-
- 9000 FORMAT( ' available colors: ', I5 /
- + ' horizontal pixels:', I5 /
- + ' vertical pixels: ', I5 )
- END
-
- Use the routine clearscreen, which clears the screen in any video mode). To
- view every possible graphics mode, run the program GRAPHIC shown below.
- Explanations of various color graphics modes (CGA, EGA, and VGA) follow.
-
- CC GRAPHIC.FOR - Displays every graphics mode.
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 key
- EXTERNAL printmenu
- EXTERNAL showmode
-
- CALL printmenu( key )
- DO WHILE( key .NE. 0 )
- CALL showmode( key )
- END DO
- END
-
- SUBROUTINE printmenu( key )
-
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy, key
-
- key = -1
- DO WHILE( (key .LT. 0) .OR. (key .GT. 12) )
- dummy = setvideomode( $DEFAULTMODE )
- WRITE (*, 9000)
- READ (*,*) key
- END DO
-
- 9000 FORMAT( ' Please ENTER a graphics mode.' /
- + ' ( To exit, ENTER 0. )' /// ' 0 Exit' /
- + ' 1 $MRES4COLOR' / ' 2 $MRESNOCOLOR' /
- + ' 3 $HRESBW' / ' 4 $HERCMONO' /
- + ' 5 $MRES16COLOR' / ' 6 $HRES16COLOR' /
- + ' 7 $ERESNOCOLOR' / ' 8 $ERESCOLOR' /
- + ' 9 $VRES2COLOR' / ' 10 $VRES16COLOR' /
- + ' 11 $MRES256COLOR' / ' 12 $ORESCOLOR' / )
- END
-
-
- SUBROUTINE showmode( which )
-
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 which, dummy, i, height, width
- INTEGER*2 modes(12) /
- + $MRES4COLOR, $MRESNOCOLOR, $HRESBW, $HERCMONO ,
- + $MRES16COLOR, $HRES16COLOR, $ERESNOCOLOR,
- + $ERESCOLOR, $VRES2COLOR, $VRES16COLOR,
- + $MRES256COLOR, $ORESCOLOR /
-
- RECORD /videoconfig/ screen
-
- IF( setvideomode( modes(which) ) .NE. 0 ) THEN
- CALL getvideoconfig( screen )
- width = screen.numxpixels / screen.numcolors
- height = screen.numypixels / 2
- DO i = 0, screen.numcolors - 1
- dummy = setcolor( INT4( i ) )
- dummy = rectangle( $GFILLINTERIOR, i * width, 0,
- + ( i + 1 ) * width, height )
- END DO
- ELSE
- WRITE (*, 9000)
- END IF
-
- READ (*,*) ! Wait for ENTER to be pressed
- dummy = setvideomode( $DEFAULTMODE )
- CALL printmenu( which )
-
- 9000 FORMAT ( ' Video mode is not available.' /
- + ' Please press ENTER. ' / )
- END
-
-
- 9.2.2 Using the Color Video Text Modes
-
- Two color video text modes, $TEXTC40 and $TEXTC80, work with the CGA, EGA,
- and VGA displays. These modes display steady or blinking text in any one of
- the 16 foreground colors with any one of the 8 background colors.
-
- In a video text mode, each displayed character requires two bytes of video
- memory. The first byte contains the ASCII code representing the character;
- the second byte contains the display attribute. In the CGA color video text
- modes, the attribute byte determines the color and whether or not it will
- blink. Sixteen colors are available: the CGA color values, and the default
- EGA and VGA color values. Since the EGA and VGA palette can be remapped,
- these values can correspond to any set of 16 colors with the appropriate
- palette mapping.
-
-
- 9.2.2.1 Using Text Colors
-
- Use gettextcolor and getbkcolor to find the current text mode's foreground
- and background colors. Values in the range 0-15 represent normal colors.
- Values in the range of 16-31 are the same colors as those in the range 0-15,
- but with blinking text. Set the foreground and background colors with
- settextcolor and setbkcolor. Both use a single argument specifying the color
- value for text displayed with outtext. The text mode color indexes are
- defined in Table 9.4.
-
- Table 9.4 Text Colors
-
- Number Color Number Color
-
- 0 Black 8 Dark gray
- 1 Blue 9 Light blue
- 2 Green 10 Light green
- 3 Cyan 11 Light cyan
- 4 Red 12 Light red
- 5 Magenta 13 Light magenta
- 6 Brown 14 Light brown
- 7 White 15 Light white
-
- Use settextposition to move the cursor to a particular row and column for
- displaying text. The outtext routine prints the text on the screen.
-
-
- 9.2.2.2 Text Color Program (COLTEXT)
-
- The following program displays a chart showing all possible combinations of
- text and background colors.
-
- CC COLTEXT.FOR - Displays text color with various color or
- CC monochrome attributes.
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy2, blink, fgd
- INTEGER*4 dummy4, bgd
- CHARACTER*2 str
- RECORD / rccoord / curpos
-
- CALL clearscreen( $GCLEARSCREEN )
- CALL outtext('Text color/monochrome attributes:')
-
- DO blink = 0, 16, 16
- DO bgd = 0, 7
- dummy4 = setbkcolor( bgd )
- CALL settextposition( INT2( bgd ) +
- + ( ( blink / 16 ) * 9) + 3, 1, curpos )
- dummy2 = settextcolor( 15 )
- WRITE (str, '(I2)') bgd
- CALL outtext( 'Back:' // str // ' Fore:')
- C
- C Loop through 16 foreground colors. For monochrome,
- C these will be underscore and low/high intensity.
- C
- DO fgd = 0, 15
- dummy2 = settextcolor( fgd + blink )
- WRITE ( str, '(I2)' ) fgd + blink
- CALL outtext( ' ' // str )
- END DO
- END DO
- END DO
-
- WRITE (*, '(///// A \)') ' Press ENTER to exit . . . '
- READ (*,*)
- dummy2 = setvideomode( $DEFAULTMODE )
- END
-
-
- 9.3 Understanding Coordinate Systems
-
- Chapter 8, "Graphics Library Routines," introduced the general concepts
- behind the different coordinate systems available to the Microsoft FORTRAN
- Graphics Library. Each system performs a particular task and uses
- coordinates appropriate to that function. Text coordinates work in rows and
- columns; physical coordinates serve as an absolute reference and as a
- starting place for creating custom window and viewport coordinates. As a
- convenience, the Microsoft FORTRAN Graphics Library supports several
- routines for converting to the different coordinate systems.
-
-
- 9.3.1 Text Coordinates
-
- Before you can write a program to print a word on the screen, you need a
- system that describes to the compiler where you want to write the text. The
- text modes divide the text screen into rows and columns (see Figure 9.2).
-
- Keep in mind these text-mode conventions:
-
- ■ Numbering starts at 1. An 80-column screen contains columns 1-80.
- ■ The row is always listed before the column.
-
- If the screen supports a video text mode that displays 25 rows and 80
- columns (as in Figure 9.2), the rows are numbered 1-25 and the columns are
- numbered 1-80. The text-positioning routines, such as settextposition, use
- row and column coordinates.
-
-
- 9.3.2 Graphics Coordinates
-
- As stated in Chapter 8, "Graphics Library Routines," there are three
- coordinate systems for describing the location of pixels on the screen:
- physical coordinates, viewport coordinates, and window coordinates. The
- coordinate systems identify pixel locations on the screen. They all apply
- the following conventions:
-
- ■ Numbering starts at 0, not 1. If there are 640 pixels, they are
- numbered 0-639.
- ■ The - x-coordinate is listed before the y-coordinate.
-
- Sections 9.3.2.1-9.3.2.3 describe each coordinate system in detail.
-
-
- 9.3.2.1 Physical Coordinates
-
- Suppose you write a program that calls setvideomode and puts the screen into
- the VGA graphics mode $VRES16COLOR. This gives you a screen containing 640
- horizontal pixels and 480 vertical pixels. Each individual pixel is referred
- to by its location relative to the x-axis and y-axis, as shown in Figure
- 9.3 below.
-
- The upper left corner is the "origin." The x- and y-coordinates for the
- origin are always (0, 0).
-
- Physical coordinates refer to each pixel directly and are therefore integers
- (that is, the screen cannot display a fractional pixel). If you use
- variables to refer to pixel locations, declare them as integers.
-
- When you first enter graphics mode, the "viewport" or drawing area is
- equivalent to the physical screen. The setvieworg routine changes the
- location of the viewport's origin. You pass it two integers, which represent
- the x and y physical screen coordinates for the new origin. For example, the
- following line moves the origin to the physical screen location (50, 100):
-
- CALL setvieworg(50, 100)
-
- The effect on the screen is illustrated in Figure 9.4 below.
-
- The number of pixels hasn't changed, but the coordinates used to refer to
- the points have changed. The x axis now ranges from -50 to +589 instead of 0
- to 639. The y axis now covers the values -100 to +379. If you use an adapter
- other than the VGA, the numbers are different but the effect is the same.
-
- All graphics routines that use viewport coordinates are affected by the new
- origin, including moveto, lineto, rectangle, ellipse, arc, and pie. For
- example, if you call the rectangle routine after relocating the viewport
- origin, and pass it the values (0, 0) and (40, 40), the upper left corner of
- the rectangle would appear 50 pixels from the left edge of the screen and
- 100 pixels from the top. It would not appear in the upper left corner of the
- screen.
-
- The setcliprgn routine creates an invisible rectangular area on the screen
- called a "clipping region." You can draw inside the clipping region, but
- attempts to draw outside the region fail (that is, nothing appears outside
- the clipping region).
-
- The default clipping region occupies the entire screen. The graphics library
- ignores any attempts to draw outside the screen.
-
- Change the clipping region by calling setcliprgn. For example, suppose you
- entered the CGA graphics mode $MRES4COLOR, which has a screen resolution of
- 320 by 200 pixels. If you draw a diagonal line from (0, 0) to (319, 199),
- the top left to the bottom right corner, the screen looks like Figure 9.5.
-
- You could create a clipping region by entering
-
- CALL setcliprgn(10, 10, 309, 189)
-
- With the clipping region in effect, the same lineto command would put the
- line shown in Figure 9.6 on the screen. The dashed lines indicate the outer
- bounds of the clipping region and do not actually print on the screen.
-
-
- 9.3.2.2 Viewport Coordinates
-
- The viewport is the area on the screen where you actually draw. Viewport
- coordinates represent the pixels within the current viewport. The
- setviewport routine establishes a new viewport within the boundaries of the
- physical screen. A standard viewport has two distinguishing features:
-
- 1. The origin of a viewport is in the upper left corner.
-
- 2. The default clipping region matches the outer boundaries of the
- viewport.
-
- The setviewport routine has the same effect as the setvieworg and setcliprgn
- routines combined.
-
- In Figure 9.5 the clipping region allows a call to lineto to draw a line
- that touches the rectangle's opposite corners. Figure 9.6 uses the same
- lineto call, but a smaller clipping region keeps the line from touching the
- surrounding rectangle.
-
- Note that you must first establish a viewport if you wish to use window
- coordinates. Window coordinates use the current viewport as their
- boundaries. The sample program REALG.FOR in Section 9.3.3 shows how to
- create multiple window-coordinate sets, each in a separate viewport, on a
- single screen.
-
-
- 9.3.2.3 Window Coordinates
-
- Functions that refer to coordinates on the physical screen and within the
- viewport require integer values. However, in many applications you may need
- to use floating-point values──for frequency, viscosity, mass, and so on. The
- setwindow routine allows you to scale the screen to almost any size. In
- addition, window-related functions accept double-precision values.
-
- A window "overlays" the current viewport; window graphics appear in the
- portion of screen defined as the current viewport.
-
- For example, you may want to graph 12 months of average Venusian
- temperatures that range from -50 to +450. You could do so by adding the
- following line to your program:
-
- dummy = setwindow(.TRUE., 1.0, -50.0, 12.0, 450.0)
-
- The first argument is the invert flag, which puts the lowest y value in the
- bottom left corner. The minimum x- and y- and maximum x- and y-coordinates
- follow; the decimal point marks them as floating-point values. The new
- organization of the screen is shown in Figure 9.7.
-
- Note that January and December plot on the left and right edges of the
- screen. In an application like this, it might be better to number the x-axis
- from 0.0 to 13.0, to provide some extra space.
-
- If you next plot a point with setpixel_w or draw a line with lineto_w, the
- values are automatically scaled to the established window.
-
- To use window coordinates with floating-point values, take the following
- steps:
-
- 1. Enter a graphics mode with setvideomode.
-
- 2. Use setviewport to create a viewport area. This step is optional if you
- plan to use the entire screen.
-
- 3. Create a real-coordinate window with setwindow, passing a LOGICAL
- invert flag and four DOUBLE PRECISION x- and y-coordinates for the
- minimum and maximum values.
-
- 4. Draw graphics shapes with rectangle_w and similar routines. Do not
- confuse rectangle (the viewport routine) with rectangle_w (the window
- routine for drawing rectangles). All window functions end with an
- underscore (_) and the letter "w."
-
- Real-coordinate graphics give you much flexibility. For example, you can fit
- either axis into a small range (such as 151.25-151.45) or into a large range
- (-50000.-+80000.), depending on the type of data you graph. In addition, by
- changing the window coordinates, you can create the effects of zooming in or
- panning across a figure.
-
-
- 9.3.3 Real Coordinates Program (REALG)
-
- The program below illustrates some ways to use the real-coordinate windowing
- functions.
-
- CC REALG.FOR - Illustrates real coordinate graphics.
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- LOGICAL fourcolors
- EXTERNAL fourcolors
-
- IF( fourcolors() ) THEN
- CALL threegraphs()
- ELSE
- WRITE (*,*) ' This program requires a CGA, EGA, or',
- + ' VGA graphics card.'
- END IF
- END
-
- C Additional functions defined below
- .
- .
- .
-
-
- The main body of the program is very short. It calls the fourcolors
- function (defined below), which attempts to enter a graphics mode with at
- least four colors. If it succeeds, the threegraphs subroutine is called,
- which will draw three graphs. See the program output in Figure 9.8.
-
- Note that the gridshape subroutine (defined below) which draws the graphs
- uses the same data in each case. However, the program uses three different
- real-coordinate windows. The two viewports in the top half are the same size
- in physical coordinates, but they have different window sizes. Each window
- uses different maximum and minimum values. In all three cases, the grid is 2
- units wide. In the upper left corner, the window is 4 units wide; in the
- upper right, the window is 6 units wide, which makes the graph appear
- smaller.
-
- In two of the three graphs, one of the lines goes off the edge, outside the
- clipping region. The lines do not intrude into the other viewports, since
- defining a viewport creates a clipping region.
-
- Finally, note that the graph on the bottom inverts the data with respect to
- the two graphs above it.
-
-
- 9.3.3.1 Checking the Adapter
-
- The first step in any graphics program is to enter a graphics mode. The
- function fourcolors performs this step:
-
- CC FOURCOLORS - Function to enter graphics mode for REALG.
-
- LOGICAL FUNCTION fourcolors()
-
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy
- RECORD /videoconfig/ screen
- COMMON screen
-
- C
- C Set to maximum number of available colors.
- C
- CALL getvideoconfig( screen )
- SELECT CASE( screen.adapter )
- CASE( $CGA, $OCGA )
- dummy = setvideomode( $MRES4COLOR )
- CASE( $EGA, $OEGA )
- dummy = setvideomode( $ERESCOLOR )
- CASE( $VGA, $OVGA )
- dummy = setvideomode( $VRES16COLOR )
- CASE DEFAULT
- dummy = 0
- END SELECT
-
- CALL getvideoconfig( screen )
- fourcolors = .TRUE.
- IF( dummy .EQ. 0 ) fourcolors = .FALSE.
- END
-
- The getvideoconfig routine transfers screen information into the videoconfig
- structure screen. Then the element screen.adapter in the SELECT CASE
- construct turns on the matching graphics mode. The modes containing the
- letter "O" are Olivetti modes.
-
- The function fourcolors returns .TRUE. if the computer supports color.
- Otherwise it returns .FALSE., which causes the program to skip the
- subroutine threegraphs.
-
-
- 9.3.4 Drawing the Graphs
-
- If the fourcolors function returns .TRUE., the main program calls the
- subroutine below, which prints the three graphs.
-
- CC THREEGRAPHS - Displays three graphs for REALG.
-
- SUBROUTINE threegraphs()
-
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy, halfx, halfy
- INTEGER*2 xwidth, yheight, cols, rows
- RECORD /videoconfig/ screen
- COMMON screen
-
- CALL clearscreen( $GCLEARSCREEN )
- xwidth = screen.numxpixels
- yheight = screen.numypixels
- cols = screen.numtextcols
- rows = screen.numtextrows
- halfx = xwidth / 2
- halfy = (yheight / rows) * ( rows / 2 )
- C
- C First window
- C
- CALL setviewport( 0, 0, halfx - 1, halfy - 1 )
- CALL settextwindow( 1, 1, rows / 2, cols / 2 )
- dummy = setwindow( .FALSE., -2.0, -2.0, 2.0, 2.0 )
- CALL gridshape( INT2( rows / 2 ) )
- dummy = rectangle( $GBORDER, 0, 0, halfx-1, halfy-1 )
- C
- C Second window
- C
- CALL setviewport( halfx, 0, xwidth - 1, halfy - 1 )
- CALL settextwindow( 1, (cols/2) + 1, rows/2, cols)
- dummy = setwindow( .FALSE., -3.0, -3.0, 3.0, 3.0 )
- CALL gridshape( INT2( rows / 2 ) )
- dummy = rectangle_w( $GBORDER, -3.0, -3.0, 3.0, 3.0 ) C
- C Third window
- C
- CALL setviewport( 0, halfy, xwidth - 1, yheight - 1 )
- CALL settextwindow( (rows / 2 ) + 1, 1, rows, cols )
- dummy = setwindow( .TRUE., -3.0, -1.5, 1.5, 1.5 )
- CALL gridshape( INT2( (rows / 2) + MOD( rows, 2 ) ) )
- dummy = rectangle_w( $GBORDER, -3.0, -1.5, 1.5, 1.5 )
-
- READ (*,*) ! Wait for ENTER to be pressed
- dummy = setvideomode( $DEFAULTMODE )
- END
-
- Although entering a graphics mode automatically clears the screen, it
- doesn't hurt to be sure, so threegraphs calls the clearscreen routine:
-
- CALL clearscreen( $GCLEARSCREEN )
-
- The $GCLEARSCREEN constant clears the entire physical screen. Other options
- include $GVIEWPORT and $GWINDOW, which clear the current viewport and the
- current text window, respectively.
-
- After assigning values to some variables, the threegraphs routine creates
- the first window:
-
- CALL setviewport( 0, 0, halfx - 1, halfy - 1 )
- CALL settextwindow( 1, 1, rows / 2, cols / 2 )
- dummy = setwindow( .FALSE., -2.0, -2.0, 2.0, 2.0 )
-
- The first line defines a viewport which covers the upper left quarter of the
- screen. Next, a text window is defined within the boundaries of that border.
- Note that the numbering starts at 1 and the row location precedes the
- column. Finally, the third line creates a window with both x and y values
- ranging from -2.0 to 2.0. The .FALSE. constant forces the y-axis to increase
- from top to bottom, which is the reverse of the "normal" convention.
-
- Next, the function gridshape inserts the grid and plots the data, and a
- border is added to the window:
-
- CALL gridshape( INT2( rows / 2 ) )
- dummy = rectangle( $GBORDER, 0, 0,
- + halfx - 1, halfy - 1 )
-
- Note that this is the standard rectangle routine, which takes coordinates
- relative to the viewport, not window coordinates.
-
- The two other windows are similar to the first. All three windows call the
- gridshape function (defined below), which draws a grid from location (-1.0,
- -1.0) to (1.0, 1.0). The grid appears in different sizes because the
- coordinates in the windows vary. The second window ranges from (-3.0, -3.0)
- to (3.0, 3.0), and the third from (-3.0,-1.5) to (1.5, 1.5), so the widths
- change accordingly.
-
- Also note that the third window contains a .TRUE. inversion argument. This
- causes the y-axis to increase from bottom to top, instead of top to bottom.
- As a result, this graph appears upside down with respect to the other two.
-
- After calling gridshape, the program frames each window, using a statement
- such as the following:
-
- dummy = rectangle_w( $GBORDER, -3.0, -1.5, 1.5, 1.5 )
-
- All three functions contain a fill flag as the first argument. The routine
- rectangle takes integer arguments that refer to the viewport coordinates.
- The rectangle_w routine takes four double-precision floating-point values
- referring to window coordinates: upper left x, upper left y, lower right x,
- and lower right y.
-
- The gridshape subroutine plots the data on the screen:
-
- CC GRIDSHAPE - This subroutine plots data for the REALG
- CC program.
-
- SUBROUTINE gridshape( numc )
-
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy, numc, i
- CHARACTER*2 str
- DOUBLE PRECISION bananas(21), x
- RECORD /videoconfig/ screen
- RECORD /wxycoord/ wxy
- RECORD /rccoord/ curpos
- COMMON screen
- C
- C Data for the graph:
- C
- DATA bananas/ -0.3 , -0.2 , -0.224, -0.1, -0.5 ,
- + 0.21 , 2.9 , 0.3 , 0.2, 0.0 ,
- + -0.885, -1.1 , -0.3 , -0.2, 0.001,
- + 0.005, 0.14, 0.0 , -0.9, -0.13 ,
- + 0.31 /
-
- C
- C Print colored words on the screen.
- C
- IF(screen.numcolors .LT. numc)
- + numc = screen.numcolors-1
- DO i = 1, numc
- CALL settextposition( i, 2, curpos )
- dummy = settextcolor( i )
- WRITE ( str, '(I2)' ) i
- CALL outtext( 'Color ' // str )
- END DO
- C
- C Draw a bordered rectangle around the graph.
- C
-
- dummy = setcolor( 1 )
- dummy = rectangle_w( $GBORDER, -1.00, -1.00, 1.00,
- + 1.00 )
- dummy = rectangle_w( $GBORDER, -1.02, -1.02, 1.02,
- + 1.02 )
- C
- C Plot the points.
- C
- x = -0.90
- DO i = 1, 19
- dummy = setcolor( 2 )
- CALL moveto_w( x, -1.0, wxy )
- dummy = lineto_w( x, 1.0 )
- CALL moveto_w( -1.0, x, wxy )
- dummy = lineto_w( 1.0, x )
- dummy = setcolor( 14 )
- CALL moveto_w( x - 0.1, bananas( i ), wxy )
- dummy = lineto_w( x, bananas( i + 1 ) )
- x = x + 0.1
- END DO
-
- CALL moveto_w( 0.9, bananas( i ), wxy )
- dummy = lineto_w( 1.0, bananas( i + 1 ) )
- dummy = setcolor( 3 )
- END
-
- First, the number of available color indexes is assigned to the rows
- variable and a DO loop displays all of the available colors:
-
- IF(screen.numcolors .LT. numc) numc = screen.numcolors - 1
- DO i = 1, numc
- CALL settextposition( i, 2, curpos )
- dummy = settextcolor( i )
- WRITE ( str, '(I2)' ) i
- CALL outtext( 'Color ' // str )
- END DO
-
- The names of the functions are self-explanatory. Using outtext in graphics
- mode allows you to control the text color and position (unlike WRITE).
-
- The routine names that end with "_w" work the same as their viewport
- equivalents, except that you pass double-precision floating-point values
- instead of integers. For example, you pass integers to lineto, but double
- precision values to lineto_w.
-
- Once you create various graphic elements, you may wish to use the
- font-oriented routines to polish the appearance of titles, headings,
- comments, or labels. The next chapter describes in more detail how to print
- text in the various fonts supplied with the Microsoft FORTRAN Graphics
- Library.
-
-
- Chapter 10 Using Fonts from the Graphics Library
- ───────────────────────────────────────────────────────────────────────────
-
- The Microsoft FORTRAN Graphics Library includes DOS routines that print text
- in various sizes and type styles. These routines provide much more control
- over the appearance of your text than the WRITE statement; they add visual
- interest to your screen displays.
-
- A "font" is a set of stylized text characters of a particular size. This
- chapter assumes you have read Chapter 9, "Drawing Graphics Elements," and
- that you understand the general terminology it introduces. You should also
- be familiar with the basic properties of both the setvideomode and moveto
- routines.
-
- The first section of this chapter reviews the fonts provided with the
- FORTRAN Graphics Library and some of the associated terminology. The next
- two sections cover the actual process of registering, setting, and using
- fonts in the graphics environment. The last section describes problems
- commonly encountered in using fonts and suggests solutions.
-
-
- 10.1 Available Typefaces
-
- The Microsoft FORTRAN Graphics Library includes six typefaces. A "typeface"
- (or "type style") refers to the style of the displayed text──Courier, for
- example, or Times Roman. The list below shows the typefaces available with
- Microsoft FORTRAN.
-
- "Type size" measures the screen area occupied by individual characters. The
- term comes from the printer's lexicon, but uses screen pixels as the unit of
- measure rather than the traditional "points." For example, "Courier 129"
- denotes the Courier typeface, with each character occupying a screen area of
- 12 vertical pixels by 9 horizontal pixels. The word "font," therefore,
- implies both a typeface and a type size.
-
- The graphic library's font routines use two methods to create fonts. The
- first technique generates Courier, Helv, and Tms Rmn fonts through a
- "bit-mapping" (or "raster-mapping") technique. Bit-mapping describes each
- character in a binary data "map." Each bit in the map corresponds to a
- screen pixel. If the bit equals 1, its associated pixel is set to the
- current screen color. Bit values of 0 appear in the current background
- color. Video adapters use this same technique to display text in graphics
- mode.
-
- The three remaining type styles──Modern, Script, and Roman──use a
- "vector-mapping" technique to create the fonts. Vector-mapping represents
- each of the characters as lines and arcs. In a literal sense, the computer
- draws each vector-mapped character on the screen. In contrast, bit-mapping
- resembles stenciling or placing a picture of each character on the screen.
-
- Each method has advantages and disadvantages. Bit-mapped characters appear
- smoother because of the predetermined pixel-mapping. However, they cannot be
- scaled. You can scale vector-mapped text to any size, but the characters
- tend to lack the solid appearance of the bit-mapped characters.
-
- Table 10.1 lists available sizes for each font. Notice that the bit-mapped
- fonts come in preset sizes measured in pixels. The exact size of any font
- character depends on screen resolution and display type.
-
- Table 10.1 Typefaces and Type Sizes in the FORTRAN Graphics Library
-
- Typeface Mapping Size (in pixels) Spacing
-
- Courier Bit 108, 129, 1512 Fixed
- Helv Bit 105, 127, 158 Proportional
- 189, 2212, 2816
- Tms Rmn Bit 105, 126, 158 Proportional
- 169, 2012, 2616
- Modern Vector Scaled Proportional
- Script Vector Scaled Proportional
- Roman Vector Scaled Proportional
-
-
- A.2 Using Microsoft FORTRAN Fonts
-
- Disk files with the .FON extension contain the data for both bit-mapped and
- vector-mapped fonts. The base names of the files indicate their content. For
- example, the files MODERN.FON, SCRIPT.FON, and ROMAN.FON hold data for the
- three vector-mapped fonts.
-
- FORTRAN's .FON files are identical to the .FNT files used in the Microsoft
- Windows operating environment. If you run Windows, you can use any of its
- .FNT files with FORTRAN's font functions. (You can also purchase Windows
- .FNT files separately.) In addition, several vendors offer software that
- create or modify .FNT files, allowing you to design your own fonts.
-
- To use the fonts in your program, you should
-
- 1. Register the fonts
- 2. Set a current font from the register
- 3. Display text using the current font
-
- The following sections describe each of the steps in detail. See Section
- 10.3 for an example program that demonstrates these steps.
-
-
- 10.2.1 Registering Fonts
-
- You must first organize the fonts you want to use into a list in memory, a
- process called "registering." The register list gives the computer
- information about the available .FON files. Register the fonts by calling
- registerfonts. The routine reads header information from specified .FON
- files and builds a list of file information, but the routine does not read
- mapping data from the files.
-
- The FGRAPH.FD file declares the registerfonts routine as
-
- INTERFACE TO FUNCTION registerfonts(filename)
- INTEGER*2 registerfonts
- + [FAR, C, ALIAS:"__f_registerfonts"]
- CHARACTER*(*) filename[FAR, REFERENCE]
- END
-
- The argument refers to the file name of the desired .FON file. The name can
- include wild cards, which allow you to register several fonts with one call
- to the registerfonts routine.
-
- If the computer successfully reads one or more .FON files, registerfonts
- returns the number of fonts registered. If the function fails, it returns a
- negative error code. (Refer to Appendix D of the Microsoft FORTRAN Reference
- for a description of the error codes.)
-
-
- 10.2.2 Setting the Font and Displaying Text
-
- Before the computer can display text in a particular font, it must know
- which of the fonts you want to use. After you register the fonts you expect
- to use, setfont makes one of the registered fonts the current (or "active")
- font. It then reads the mapping data from the appropriate .FON file into
- memory.
-
- The FGRAPH.FD include file declares the setfont routine as
-
- INTERFACE TO FUNCTION setfont(options)
- INTEGER*2 setfont[FAR, C, ALIAS:"__f_setfont"]
- CHARACTER*(*) options[FAR, REFERENCE]
- END
-
- The function's argument consists of letter codes that describe the desired
- font.
-
- Option Meaning
-
- t'fontname' Typeface of the font in single
- quotes. The fontname may be one
- of the following:
-
- courier modern
- helv script tms
- rmn roman
-
- Notice the space in the name "tms
- rmn." Additional font files use
- other names for fontname. Refer
- to the vendor's documentation for
- these names.
-
- hy Character height, where y is the
- height in pixels.
-
- wx Character width, where x is the
- width in pixels.
-
- f Select only a fixed-spaced font.
-
- p Select only a proportional-spaced
- font.
-
- v Select only a vector-mapped font.
-
- r Select only a bit-mapped (or
- "raster-mapped") font.
-
- b Select the best fit from the
- registered fonts. The b option
- instructs setfont to accept the
- closest-fitting font if a font of
- the specified size is not
- registered.
-
- If at least one font is
- registered, the b option always
- sets a current font. If you do
- not specify the b option and an
- exact matching font is not
- registered, setfont will fail. In
- this case, any existing current
- font remains current.
-
- The best fit is based on four
- criteria: pixel height, typeface,
- pixel width, and spacing (fixed
- or proportional). If you request
- a vector-mapped font, setfont
- sizes the font to correspond with
- the specified pixel height and
- width; a bit-mapped font, setfont
- chooses the closest available
- size. If the requested type size
- fits exactly between two
- registered fonts, the smaller
- size takes precedence.
-
- nx Select font number x, where x is
- less than or equal to the value
- returned by registerfonts. For
- example, the option n3 makes the
- third registered font the current
- font (provided three or more
- fonts are registered).
-
- You can list the option codes in any order and in upper- or lowercase. The
- options may be separated with spaces.
-
- The setfont routine updates a data area with specifics about the current
- font. The data area stores the information in a structure defined by the
- include file FGRAPH.FD to have the following form:
-
- STRUCTURE/fontinfo/
- INTEGER type ! Set = vector,clear = bit map
- INTEGER ascent ! Pix dist from top to base
- INTEGER pixwidth ! Character width in pixels
- INTEGER pixheight ! Character height in pixels
- INTEGER avgwidth ! Average character width
- CHARACTER*81 filename ! Filename including path
- CHARACTER*32 facename ! Font name
- END STRUCTURE
-
- If you want the parameters of the current font, call the getfontinfo
- routine. Once you register the fonts you want and make one the active font,
- follow these two steps to display the text on the screen:
-
- 1. Select a starting position for the text with the moveto routine.
-
- 2. Send the text to the screen at that position (in the current font) with
- outgtext.
-
- The moveto routine takes pixel coordinates as arguments. Those coordinates
- are for the upper left corner of the cell of the first character in the
- string. The following section describes a sample program included with
- Microsoft FORTRAN that displays the provided fonts.
-
-
- 10.3 Example Program (SAMPLER)
-
- SAMPLER displays sample text in the available fonts, returning to DOS when
- you press a key. First, make sure the .FON files are in the current
- directory.
-
- CC SAMPLER.FOR - Displays sample text in various fonts.
- CC
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 NFONTS
- INTEGER*2 dummy, i, iend
- CHARACTER*30 list
- CHARACTER*64 fontpath
- RECORD /videoconfig/ vc
- RECORD /xycoord/ xy
-
- PARAMETER ( NFONTS = 6 )
-
- CHARACTER* ( 7 ) text ( 2 * NFONTS )/
- + "COURIER", "courier" ,
- + "HELV" , "helv" ,
- + "TMS RMN", "tms rmn" ,
- + "MODERN" , "modern" ,
- + "SCRIPT" , "script" ,
- + "ROMAN" , "roman" /
-
- CHARACTER*( 10 ) option (NFONTS) /
- + "t'courier'", "t'helv'" ,
- + "t'tms rmn'", "t'modern'",
- + "t'script'" , "t'roman'" /
- C
- C Locate .FON files and register fonts by reading header
- C information from all files.
- C
- IF( registerfonts( '*.FON' ). LT. 0 ) THEN
- + WRITE (*, '(A/)') ' Enter directory for .FON files:'
- READ (*, '(A )') fontpath
- iend = INDEX( fontpath, ' ' )
- fontpath(iend:iend + 5) = '\*.FON'
- IF( registerfonts( fontpath ). LT. 0 )
- + STOP 'Error: cannot find font files'
- ENDIF
-
- C
- C Find graphics mode.
- C
- IF( setvideomode( $MAXRESMODE ) .EQ. 0 )
- + STOP 'Error: cannot set graphics mode'
-
- C
- C Copy video configuration into structure vc.
- C
- CALL getvideoconfig( vc )
-
- C
- C Display six lines of sample text.
- C
- DO i = 1, NFONTS
- list = option(i) // 'h30w24b'
- IF( setfont( list ) .EQ. 0 ) THEN
- dummy = setcolor( INT4( i ) )
- CALL moveto( 0, (i - 1) *
- + vc.numypixels / NFONTS, xy )
- CALL outgtext( text((i * 2) - 1) )
-
- CALL moveto( vc.numxpixels/2,
- + (i - 1) * vc.numypixels / NFONTS, xy )
- CALL outgtext( text(i * 2) )
- ELSE
- dummy = setvideomode( $DEFAULTMODE )
- STOP 'Error: cannot set font'
- END IF
- END DO
-
- READ (*,*)
- dummy = setvideomode( $DEFAULTMODE )
- C
- C Return memory when finished with fonts.
- C
- CALL unregisterfonts()
- END
-
- Notice that SAMPLER calls the setfont routine to specify the typeface and
- best fit for a character height of 30 pixels and a width of 24 pixels. Then
- the graphics routine moveto establishes the starting point for each text
- string. When the program finds the font, it sends a message to the screen.
-
-
- 10.4 Using Fonts Effectively
-
- Printing with fonts is straightforward, and using fonts requires little
- programming effort. However, keep the following in mind when working with
- fonts:
-
- ■ The video mode should be set only once. If you create an image and want
- to incorporate font-based text into it, do not reset the video mode
- prior to calling the font routines. Doing so will clear the screen,
- which destroys the original image.
-
- ■ The setfont function reads specified .FON files to obtain mapping data
- for the current font. Each call to setfont overwrites the old font data
- in memory. If you want to show text of different styles on the same
- screen, display all of the text of one font before moving on to the
- others. Minimizing the number of calls to setfont reduces the time
- spent in disk I/O and memory reloads.
-
- ■ When your program finishes with the fonts library, you might wish to
- free the memory occupied by the register list. Call the subroutine
- unregisterfonts to do this. As its name implies, this subroutine frees
- the memory allocated by registerfonts. The register information for
- each type size of each font takes up approximately 140 bytes of memory,
- so the amount of memory returned by unregisterfonts is significant only
- if you have many fonts registered.
-
- For additional syntax and usage information on each of the font routines,
- read the appropriate material on individual routines in the following
- chapter, "Graphics Library Reference."
-
-
- Chapter 11 Graphics Library Reference
- ───────────────────────────────────────────────────────────────────────────
-
- This chapter describes each routine in the Microsoft FORTRAN DOS graphics
- library, GRAPHICS.LIB, in alphabetical order. The text-based routines are
- also supported under OS/2 by the library GRTEXTP.LIB, as noted in the text
- and in Chapter 8. In some cases, similar or related routines are clustered
- in the same description, with differences noted where appropriate.
-
- The name of each routine appears at the top of the page. The Interface
- section shows the complete interface needed in order to use the routine,
- although you will find it more convenient to reference the include file
- FGRAPH.FD──which contains the same declarations──than to recreate each
- interface yourself. The Description section outlines what the routine does,
- along with any pertinent additional information. The Return Value section
- describes any values returned by the routine. Such values can help in
- testing for errors before you use the results of the routine call. The See
- Also section lists similar or related routines. Finally, the Example section
- provides a typical application of the routine, or refers you to a routine
- with the same or similar application. (This section does not appear with
- every reference entry.)
-
-
- arc, arc_w
-
- ■ Interface
-
- INTERFACE TO FUNCTION arc(x1, y1, x2, y2, x3, y3, x4, y4)
- INTEGER*2 arc[FAR,
- C, ALIAS:"__arc"] INTEGER*2 x1, y1 ! Upper left corner of bounding
- INTEGER*2 x2, y2 ! Lower right corner of bounding
- INTEGER*2 x3, y3 ! Start vector
- INTEGER*2 x4, y4 ! End vector
- END
-
- INTERFACE TO FUNCTION arc_w(wx1, wy1, wx2, wy2, wx3, wy3, wx4, wy4)
- INTEGER*2 arc_w[FAR, C, ALIAS:"__f_arc_w"]
- DOUBLE PRECISION wx1, wy1 ! Upper left corner of bounding
- DOUBLE PRECISION wx2, wy2 ! Lower right corner of bounding
- DOUBLE PRECISION wx3, wy3 ! Start vector
- DOUBLE PRECISION wx4, wy4 ! End vector
- END
-
- ■ Description
-
- The arc routines draw elliptical arcs.
-
- The arc routine uses the viewport-coordinate system. The center of the arc
- is the center of the bounding rectangle defined by the points (x1, y1) and
- (x2, y2). The arc starts at the point where it intersects the vector defined
- by (x3, y3) and ends where it intersects the vector defined by (x4, y4).
-
- The arc_w routine uses the window-coordinate system. The center of the arc
- is the center of the bounding rectangle defined by the window-coordinate
- pairs (wx1, wy1) and (wx2, wy2). The arc starts at the point where it
- intersects the vector defined by (wx3, wy3) and ends where it intersects
- the vector defined by (wx4, wy4).
-
- In both cases, the arc is drawn using the current color, moving
- counterclockwise. Since an arc does not define a closed area, it is not
- filled.
-
- ■ Return value
-
- The arc and arc_w routines return a nonzero value if the arc is successfully
- drawn; otherwise, they return 0.
-
- ■ See also
-
- ellipse, lineto, pie, rectangle, setcolor
-
- ■ Example
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
- INTEGER*2 dummy
-
- dummy = setvideomode( $MRES16COLOR )
- dummy = arc( 80, 50, 240, 150, 0, 50, 240, 150 )
- READ (*,*) ! Press ENTER to exit
- dummy = setvideomode( $DEFAULTMODE )
- END
-
- This program draws the arc shown in Figure R.1.
-
- See also the example program for setpixel.
-
-
- clearscreen
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + clearscreen[FAR, C, ALIAS:"__clearscreen"](area)
- INTEGER*2 area ! Target area
- END
-
- ■ Description
-
- The clearscreen subroutine erases the target area, filling it with the
- current background color. The area parameter can be one of the following
- symbolic constants (defined in FGRAPH.FD):
-
- Constant Action
-
- $GCLEARSCREEN Clears and fills the entire
- screen
-
- $GVIEWPORT Clears and fills only within the
- current viewport
-
- $GWINDOW Clears and fills only within the
- current text window
-
- This subroutine is also available under OS/2.
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- getbkcolor, setbkcolor
-
- ■ Example
-
- See the example program for gettextcolor and setvieworg.
-
-
- displaycursor
-
- ■ Interface
-
- INTERFACE TO FUNCTION displaycursor(toggle)
- INTEGER*2 displaycursor[FAR, C, ALIAS:"__displaycursor"]
- INTEGER*2 toggle ! Cursor state
- END
-
- ■ Description
-
- On entry into each graphics routine, the screen cursor is turned off. The
- displaycursor function determines whether the cursor will be turned back on
- when programs exit graphic routines. If toggle is set to $GCURSORON, the
- cursor will be restored on exit. If toggle is set to $GCURSOROFF, the cursor
- will be left off.
-
- This function is also available under OS/2.
-
- ■ Return value
-
- Returns the previous value of toggle.
-
- ■ See also
-
- gettextcursor, settextcursor
-
- ■ Example
-
- See the example program for settextcursor.
-
-
- ellipse, ellipse_w
-
- ■ Interface
-
- INTERFACE TO FUNCTION ellipse(control, x1, y1, x2, y2)
- INTEGER*2 ellipse[FAR, C, ALIAS:"__ellipse"]
- INTEGER*2 control ! Fill flag
- INTEGER*2 x1, y1 ! Upper left corner of bounding recta
- INTEGER*2 x2, y2 ! Lower right corner of bounding rect
- END
-
- INTERFACE TO FUNCTION ellipse_w(control, wx1, wy1, wx2, wy2)
- INTEGER*2 ellipse_w[FAR, C, ALIAS:"__f_ellipse_w"]
- INTEGER*2 control ! Fill flag
- DOUBLE PRECISION wx1, wy1 ! Upper left corner of bounding recta
- DOUBLE PRECISION wx2, wy2 ! Lower right corner of bounding rect
- END
-
- ■ Description
-
- The ellipse functions draw an ellipse. The border is drawn in the current
- color. In the ellipse function, the center of the ellipse is the center of
- the bounding rectangle defined by the viewport-coordinate points (x1, y1)
- and (x2, y2).
-
- In the ellipse_w function, the center of the ellipse is the center of the
- bounding rectangle defined by the window-coordinate points (wx1, wy1) and
- (wx2, wy2).
-
- If the bounding-rectangle arguments define a point or a vertical or
- horizontal line, no figure is drawn.
-
- The control argument can be one of the following symbolic constants:
-
- Constant Action
-
- $GFILLINTERIOR Fills the ellipse using the
- current fill mask
-
- $GBORDER Does not fill the ellipse
-
- The control option given by $GFILLINTERIOR is equivalent to a subsequent
- call to the floodfill function using the center of the ellipse as the start
- point and the current color (set by setcolor) as the boundary color.
-
- ■ Return value
-
- The ellipse and ellipse_w functions return a nonzero value if the ellipse is
- drawn successfully; otherwise, they return 0.
-
- ■ See also
-
- arc, floodfill, lineto, pie, rectangle, setcolor, setfillmask
-
- ■ Example
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
- INTEGER*2 dummy
-
- dummy = setvideomode( $MRES16COLOR )
- dummy = ellipse( $GFILLINTERIOR, 80, 50, 240, 150 )
- READ (*,*) ! Press ENTER to exit
- dummy = setvideomode( $DEFAULTMODE )
- END
-
- This program draws the shape shown in Figure R.2.
-
- See also the example program for setpixel and setvieworg.
-
-
- floodfill, floodfill_w
-
- ■ Interface
-
- INTERFACE TO FUNCTION floodfill(x, y, boundary)
- INTEGER*2 floodfill[FAR, C, ALIAS:"__floodfill"]
- INTEGER*2 x, y ! Start point
- INTEGER*2 boundary ! Fills boundary color
- END
-
- INTERFACE TO FUNCTION floodfill_w(wx, wy, boundary)
- INTEGER*2 floodfill_w[FAR, C, ALIAS:"__f_floodfill_w"]
- DOUBLE PRECISION wx, wy ! Start point
- INTEGER*2 boundary ! Fills boundary color
- END
-
- ■ Description
-
- These functions fill an area using the current color and fill mask.
-
- The floodfill function begins filling at the viewport-coordinate point (x,
- y).
-
- The floodfill_w function begins filling at the window-coordinate point (wx,
- wy).
-
- If this point lies inside a figure, the interior is filled; if it lies
- outside a figure, the background is filled. The point must be inside or
- outside the figure to be filled, not on the figure boundary itself. Filling
- occurs in all directions, stopping at the color of boundary.
-
- ■ Return value
-
- The floodfill and floodfill_w functions return a nonzero value if the fill
- is successful. They return 0 if the fill could not be completed; if the
- start point lies on the boundary color; or if the start point lies outside
- the clipping region.
-
- ■ See also
-
- ellipse, getcolor, getfillmask, pie, setcliprgn, setcolor, setfillmask
-
- ■ Example
-
- See the example program for setlinestyle.
-
-
- getactivepage
-
- ■ Interface
-
- INTERFACE TO FUNCTION getactivepage()
- INTEGER*2 getactivepage[FAR, C, ALIAS:"__getactivepage"]
- END
-
- ■ Description
-
- The getactivepage function returns the current active page number.
-
- ■ Return value
-
- Returns the page number of the current active page. All hardware
- combinations support at least one page (page number 0).
-
- This function is also available under OS/2.
-
- ■ See also
-
- getactivepage, gettextcolor, gettextposition, getvisualpage,
- outtext, settextcolor, settextposition, settextwindow, setvideomode,
- setvisualpage, wrapon
-
- ■ Example
-
- CC PAGE.FOR - Illustrates animation effects by changing the video pag
- CC The video page functions demonstrated include:
- CC getactivepage getvisualpage setactivepage setvisualpag
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy, oldapage, oldvpage
- INTEGER*2 i, j, k, l
- CHARACTER*3 jumper(4,3)
- RECORD /rccoord/ curpos
-
- DATA jumper / '\o/', '_o_', ' o ', ' o ',
- + ' O ', ' O ', '/O\', ' O ',
- + '/ \', '( )', '/ \', '( )' /
-
- oldapage = getactivepage()
- oldvpage = getvisualpage()
- IF( setvideomode( $TEXTBW40 ) .EQ. 0 )
- + STOP 'Error: cannot set 40-column mode'
- dummy = displaycursor( $GCURSOROFF )
-
- C
- C Draw 24 images on each page.
- C
- DO i = 1, 4
- dummy = setactivepage( i - 1 )
- DO j = 1, 22, 7
- DO k = 1, 36, 7
- DO l = 0, 2
-
- CALL settextposition( j + l, k, curpos )
- CALL outtext( jumper(i,l + 1) )
- END DO
- END DO
- END DO
- END DO
-
- C
- C Cycle 10 times through pages 0-3.
- C
- DO i = 1, 10
- DO j = 0, 3
- dummy = setvisualpage( j )
- CALL delay( INT2( 10 ) )
- END DO
- END DO
-
- C
- C Restore original page.
- C
- dummy = setvideomode( $DEFAULTMODE )
- dummy = setactivepage( oldapage )
- dummy = setvisualpage( oldvpage )
- END
-
-
- CC DELAY - Pauses for a specified number of 1/100 seconds.
- CC
- CC Params: Wait - pause time in 0.01 seconds
-
- SUBROUTINE delay( wait )
- INTEGER*2 wait, tick0, tick1, tick, kount, dummy
-
- kount = 0
- CALL GETTIM( dummy, dummy, dummy, tick0 )
- DO WHILE( kount .LT. wait )
- CALL GETTIM( dummy, dummy, dummy, tick1 )
- tick = tick1 - tick0
- IF( tick .LT. 0 ) tick = tick + 100
- tick0 = tick1
- kount = kount + tick
- END DO
- RETURN
- END
-
- This program fills the screen with animated figures.
-
-
- getbkcolor
-
- ■ Interface
-
- INTERFACE TO FUNCTION getbkcolor()
- INTEGER*4 getbkcolor[FAR, C, ALIAS:"__getbkcolor"]
- END
-
- ■ Description
-
- The getbkcolor function retrieves the pixel value of the current background
- color. The default is 0.
-
- In a color text mode (such as $TEXTC80), setbkcolor accepts (and getbkcolor
- returns) a color index. For example, setbkcolor(2) sets the background color
- to pixel value 2. The actual color displayed depends on the palette mapping
- for color index 2. The default is green in a color text-mode.
-
- In a color graphics mode (such as $ERESCOLOR), setbkcolor accepts (and
- getbkcolor returns) a color value (as used in remappalette). The value for
- the background color is given by the symbolic constants defined in the
- FGRAPH.FD include file. For example, setbkcolor($GREEN) sets the background
- color in a graphics mode to green. These symbolic constants are provided as
- a convenience in defining and manipulating the most common colors. The
- actual range of colors is, in general, much greater.
-
- The function setcolor accepts an INTEGER*2 value as an argument. It is a
- color index.
-
- Whenever an argument is INTEGER*4, it refers to a color value, and whenever
- it is INTEGER*2, it refers to a color index. The two exceptions are the
- functions setbkcolor and getbkcolor, described above. A more complete
- discussion of colors is given in the reference page for the remappalette
- function.
-
- This function is also available under OS/2.
-
- ■ Return value
-
- Returns the current background color value.
-
- ■ See also
-
- remappalette, setbkcolor
-
- ■ Example
-
- See the example program for gettextcolor.
-
-
- getcolor
-
- ■ Interface
-
- INTERFACE TO FUNCTION getcolor()
- INTEGER*2 getcolor[FAR, C, ALIAS:"__getcolor"]
- END
-
- ■ Description
-
- The getcolor function returns the current color index. The default is the
- highest legal value of the current palette.
-
- ■ Return value
-
- Returns the current color index.
-
- ■ See also
-
- setcolor
-
- ■ Example
-
- PROGRAM colors
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 loop, loop1, dummy2 REAL rnd1, rnd2
-
- dummy2 = setvideomode( $MRES16COLOR )
- DO loop1 = 1, 20
- dummy2 = setcolor
- + ( MOD( getcolor()+1, 16 ) ) ! Set next color
- DO loop = 1, 3200
- C
- C Set a random pixel, normalized to be on the screen C
-
- CALL RANDOM( rnd1 )
- CALL RANDOM( rnd2 )
- dummy2 = setpixel( INT2( rnd1*320 ),
- + INT2( rnd2*200 ) )
- END DO
- END DO
-
- dummy2 = setvideomode( $DEFAULTMODE )
- END
-
- This program assigns different colors to randomly selected pixels.
-
-
- getcurrentposition, getcurrentposition_w
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + getcurrentposition[FAR, C, ALIAS:"__f_getcurrentposition"](s)
- STRUCTURE/xycoord/
- INTEGER*2 xcoord ! x-coordinate
- INTEGER*2 ycoord ! y-coordinate
- END STRUCTURE
- RECORD/xycoord/s [FAR, REFERENCE] ! Returns with current posit
- END
-
- INTERFACE TO SUBROUTINE
- + getcurrentposition_w[FAR, C, ALIAS:"__f_getcurpos_w"](s)
- STRUCTURE/wxycoord/
- DOUBLE PRECISION wx ! x-window coordinate
- DOUBLE PRECISION wy ! y-window coordinate
- END STRUCTURE
- RECORD/wxycoord/s [FAR, REFERENCE] ! Returns with current posit
- END
-
- ■ Description
-
- The getcurrentposition functions return the coordinates of the current
- graphics output position in s. The getcurrentposition function returns the
- position as an xycoord structure, defined in FGRAPH.FD. The
- getcurrentposition_w function returns the position as the wxycoord
- structure, defined in FGRAPH.FD.
-
- The current position can be changed by the arc, lineto, and moveto
- functions.
-
- Only graphics output starts at the current position; it does not affect text
- output, which begins at the current text position, a separate concept (see
- settextposition).
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- moveto
-
- ■ Example
-
- PROGRAM Movept
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- RECORD/xycoord/ position
-
- CHARACTER*255 buffer
- INTEGER*2 dummy2
- REAL rnd1, rnd2
-
- dummy2 = setvideomode( $MRES16COLOR )
- CALL RANDOM( rnd1 )
- CALL RANDOM( rnd2 )
- CALL moveto( INT2( rnd1*160+80 ),
- + INT2( rnd2*100+50 ), position )
- CALL getcurrentposition( position )
- WRITE( buffer,"( ' x=',I3,', y=',I3,\ )" ) position.xcoord,
- + position.ycoord
- CALL settextposition( position.xcoord/8, position.ycoord/8,
- + position )
- CALL outtext( buffer( 1:LEN_TRIM(buffer ) ) )
-
- READ(*, *) ! Wait for ENTER to be pressed
- dummy2 = setvideomode( $DEFAULTMODE )
- END
-
- This program moves the current graphics output position to a random point,
- calls getcurrentposition to obtain the coordinates, and then writes the
- coordinates to a buffer. It then sets the current text position to those
- coordinates and outputs the coordinates to the screen, beginning at the
- current position.
-
-
- getfillmask
-
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + getfillmask[FAR, C, ALIAS:"__getfillmask"](mask)
- INTEGER*1 mask [FAR, REFERENCE](8)
- END
-
- ■ Description
-
- Some graphics routines (floodfill, pie, ellipse, and rectangle) can fill
- part or all of the screen with the current color or background color. The
- filling can be controlled with the current fill mask.
-
- The getfillmask subroutine returns the current fill mask. The mask is an
- 8-by-8-bit array, where each bit represents a pixel. A 1 bit sets the
- corresponding pixel to the current color, while a 0 bit leaves the pixel
- unchanged. The mask is repeated over the entire fill area. If no fill mask
- is set, or mask is all zeros, only the current color is used in fill
- operations. If no mask is present, the subroutine sets mask to all zeros.
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- floodfill, ellipse, pie, rectangle, setfillmask
-
- ■ Example
-
- PROGRAM Fill
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*1 style( 8,6 )/ #78,#30,#30,#78,#30,#30,#78,#30,
- + #78,#32,#30,#78,#30,#38,#78,#32,
- + #78,#39,#38,#78,#63,#36,#78,#33,
- + #78,#65,#36,#78,#33,#38,#78,#62,
- + #78,#66,#63,#78,#65,#65,#78,#37,
- + #78,#66,#65,#78,#66,#65,#78,#66 /
-
- INTEGER*1 oldstyle( 8 ) ! Placeholder for old style
- INTEGER loop
-
- dummy2 = setvideomode( $MRES4COLOR )
- CALL getfillmask( oldstyle )
- C
- C Draw an ellipse under the middle few rectangles in a
- C different color.
- C
-
- dummy2 = setcolor( 2 )
- dummy2 = ellipse( $GFILLINTERIOR, 120, 75, 200, 125 )
- dummy2 = setcolor( 3 )
- DO loop = 1,6
- C
- C Make six rectangles.
- C
- CALL setfillmask( style( 1,loop ) )
- dummy2 = rectangle( $GFILLINTERIOR, loop*40+5, 90,
- + ( loop+1 )*40, 110 )
- END DO
-
- CALL setfillmask( oldstyle ) ! Restore old style
- READ (*,*) ! Wait for ENTER to be pressed
- dummy2 = setvideomode( $DEFAULTMODE )
- END
-
- This program draws an ellipse overlaid with six rectangles, each with a
- different fill mask.
-
-
- getfontinfo
-
- ■ Interface
-
- INTERFACE TO FUNCTION getfontinfo(font)
- INTEGER*2 getfontinfo
- + [FAR, C, ALIAS:"__f_getfontinfo"]
- STRUCTURE/fontinfo/
- INTEGER*2 type ! Set=vector, clear=bit map
- INTEGER*2 ascent ! Pixel distance from top to baseline
- INTEGER*2 pixwidth ! Character width in pixels, 0=prop
- INTEGER*2 pixheight ! Character height in pixels
- INTEGER*2 avegwidth ! Average width in pixels
- CHARACTER*81 filename ! File name including path
- CHARACTER*32 facename ! Font name
- END STRUCTURE
- RECORD/fontinfo/font [FAR, REFERENCE]
- END
-
- ■ Description
-
- The getfontinfo function sets the current font characteristics in a fontinfo
- structure, defined in FGRAPH.FD.
-
- The fontinfo structure contains the following elements:
-
- Element Contents
-
- type Specifies vector (1) or bit-map
- (0) font
-
- ascent Specifies pixel distance from top
- to baseline
-
- pixwidth Specifies the character width in
- pixels; a 0 indicates a
- proportional font
-
- pixheight Specifies the character height in
- pixels
-
- avgwidth Specifies the average character
- width in pixels
-
- filename Specifies the file name including
- the path
-
- facename Specifies the font name
-
-
- ■ Return value
-
- Returns zero if font is returned successfully.
-
- ■ See also
-
- getgtextextent, outgtext, registerfonts, setfont, unregisterfonts
-
-
- getgtextextent
-
- ■ Interface
-
- INTERFACE TO FUNCTION getgtextextent(text)
- INTEGER*2 getgtextextent
- + [FAR, C, ALIAS:"__f_getgtextextent"]
- CHARACTER *(*)text [FAR, REFERENCE] ! Text to be analyzed
- END
-
- ■ Description
-
- The getgtextextent function returns the width in pixels that would be
- required to print the text string, including any trailing blanks, with the
- current font using outgtext.
-
- This function is particularly useful for determining the size of text that
- uses proportional-spaced fonts.
-
- ■ Return value
-
- Returns the width of a text string in pixels.
-
- ■ See also
-
- getfontinfo, outgtext, registerfonts, setfont, unregisterfonts
-
- ■ Example
-
- See the example program for registerfonts.
-
-
- getimage, getimage_w
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + getimage[FAR, C, ALIAS:"__getimage"](x1, y1, x2, y2, image)
- INTEGER*2 x1, y1 ! Upper left corner of bounding rectangle
- INTEGER*2 x2, y2 ! Lower right corner of bounding rectangle
- INTEGER*1 image [FAR, REFERENCE](*)
- END
-
- INTERFACE TO SUBROUTINE
- + getimage_w[FAR, C, ALIAS:"__f_getimage_w"](wx1, wy1, wx2, wy2, image)
- DOUBLE PRECISION wx1, wy1 ! Upper left corner of bounding rectangle
- DOUBLE PRECISION wx2, wy2 ! Lower right corner of bounding rectangle
- INTEGER*1 image [FAR, REFERENCE](*)
- END
-
- ■ Description
-
- The getimage subroutines store the screen image defined by a specified
- bounding rectangle into the buffer that image points to.
-
- The getimage subroutine defines the bounding rectangle with the
- viewport-coordinate points (x1, y1) and (x2, y2).
-
- The getimage_w subroutine defines the bounding rectangle with the
- window-coordinate points (wx1, wy1) and (wx2, wy2).
-
- The buffer must be large enough to hold the image. Determine the size by
- calling the appropriate imagesize function at run time, or by using the
- formula described on the imagesize reference page.
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- imagesize, putimage
-
- ■ Example
-
- See the example program for imagesize.
-
-
- getlinestyle
-
- ■ Interface
-
- INTERFACE TO FUNCTION getlinestyle()
- INTEGER*2 getlinestyle[FAR, C, ALIAS:"__getlinestyle"]
- END
-
- ■ Description
-
- Some graphics routines (lineto, pie, and rectangle) output straight lines to
- the screen. The type of line can be controlled with the current line-style
- mask.
-
- The getlinestyle function returns the current line-style-mask number. The
- mask is a 16-bit array, where each bit represents a pixel in the line being
- drawn. If the bit is 1, then the corresponding pixel is set to the color of
- the line (the current color). If the bit is 0, the corresponding pixel is
- left unchanged. The mask is repeated over the length of the line. The
- default mask is #FFFF (a solid line).
-
- ■ Return value
-
- If a mask has been set, returns the current line-style mask number. If no
- mask has been set, getlinestyle returns the default mask.
-
- ■ See also
-
- lineto, pie, rectangle, setlinestyle
-
- ■ Example
-
- See the example program for setlinestyle.
-
-
- getphyscoord
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + getphyscoord[FAR, C, ALIAS:"__f_getphyscoord"](x, y, s)
- INTEGER*2 x, y
- STRUCTURE/xycoord/
- INTEGER*2 xcoord ! x-coordinate
- INTEGER*2 ycoord ! y-coordinate
- END STRUCTURE
- RECORD/xycoord/s [FAR, REFERENCE] ! Returns the physical coord
- END
-
- ■ Description
-
- The getphyscoord subroutine translates the viewport-coordinate point (x, y)
- to physical coordinates, returning them in the xycoord structure s, defined
- in FGRAPH.FD.
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- getviewcoord
-
- ■ Example
-
- See the example program for setviewport.
-
-
- getpixel, getpixel_w
-
- ■ Interface
-
- INTERFACE TO FUNCTION getpixel(x, y)
- INTEGER*2 getpixel[FAR, C, ALIAS:"__getpixel"]
- INTEGER*2 x, y ! Pixel position
- END
-
- INTERFACE TO FUNCTION getpixel_w(wx, wy)
- INTEGER*2 getpixel_w[FAR, C, ALIAS:"__f_getpixel_w"]
- DOUBLE PRECISION wx, wy ! Pixel position in window coordinates
- END
-
- ■ Description
-
- The getpixel functions retrieve the pixel value at a specified location. The
- getpixel function uses the viewport coordinate (x, y). The getpixel_w
- function uses the window coordinate (wx, wy). The range of possible pixel
- values and their color translation is determined by the current video mode
- and palette, respectively.
-
- ■ Return value
-
- If successful, the getpixel and getpixel_w functions return the pixel value.
- If the function fails (for example, the point lies outside the clipping
- region, or the program is in a text mode), it returns -1.
-
- ■ See also
-
- remapallpalette, remappalette, selectpalette, setpixel, setvideomode
-
- ■ Example
-
- PROGRAM colors
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 loop, dummy2
- REAL rnd1, rnd2
-
- dummy2 = setvideomode( $MRES16COLOR )
- dummy2 = rectangle( $GFILLINTERIOR, 80, 50, 240, 150 )
- DO loop = 1, 8000
- dummy2 = setcolor( MOD( getcolor()+1, 16 ) ) ! Set next
- + color
- C
- C Set a random pixel, but only if it is already on.
- C
- CALL RANDOM( rnd1 )
- CALL RANDOM( rnd2 )
- IF ( getpixel( INT2( rnd1*320 ), INT2( rnd2*200 ) )
- + .NE. 0 ) THEN
- dummy2 = setcolor( MOD( loop, 16 ) )
- dummy2 = setpixel( INT2( rnd1*320 ), INT2( rnd2*200 ) )
- END IF
- END DO
-
- dummy2 = setvideomode( $DEFAULTMODE )
- END
-
- This program assigns different colors to randomly selected pixels.
-
-
- gettextcolor
-
- ■ Interface
-
- INTERFACE TO FUNCTION gettextcolor()
- INTEGER*2 gettextcolor[FAR, C, ALIAS:"__gettextcolor"]
- END
-
- ■ Description
-
- The gettextcolor function returns the color index of the current text color.
- The text color is set only by the settextcolor function and affects text
- output with the outtext function only. The setcolor function sets the color
- for text output using the outgtext function.
-
- The default is the highest legal color index of the current palette.
-
- This function is also available under OS/2.
-
- ■ Return value
-
- Returns the color index of the current text color.
-
- ■ See also
-
- selectpalette, setcolor, settextcolor
-
- ■ Example
-
- CC TEXT.FOR - Illustrates text output functions including:
- CC clearscreen getbkcolor gettextcolor
- CC gettextposition outtext setbkcolor
- CC settextcolor settextposition
- CC
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy2, blink, fgd, oldfgd
- INTEGER*4 dummy4, bgd, oldbgd
- CHARACTER*4 str
- RECORD / rccoord / curpos
-
- C
- C Save original foreground, background, and text position.
- C
- oldfgd = gettextcolor()
- oldbgd = getbkcolor()
- CALL clearscreen( $GCLEARSCREEN )
- C
- C First time no blink, second time blinking.
- C
- DO blink = 0, 16, 16
- C
- C Loop through 8 background colors.
- C
- DO bgd = 0, 7
- dummy4 = setbkcolor( bgd )
- CALL settextposition( INT2( bgd )
- + ( ( blink / 16 ) * 9 )+ 3, 1, curpos )
- dummy2 = settextcolor( 15 )
- WRITE ( str, '( I4 )' ) bgd
- CALL outtext( 'Back:' // str(3:4) // ' Fore:', 14 )
- C
- C Loop through 16 foreground colors.
- C
- DO fgd = 0, 15
- dummy2 = settextcolor( fgd + blink )
- WRITE ( str, '( I4 )' ) fgd + blink
- CALL outtext( str )
- END DO
- END DO
- END DO
-
- WRITE (*, '(///// A \)') ' Press ENTER to exit . . . '
- READ (*,*)
-
- C
- C Restore original foreground and background.
- C
- dummy2 = settextcolor( oldfgd )
- dummy4 = setbkcolor( oldbgd )
- CALL clearscreen( $GCLEARSCREEN )
- END
-
- This program prints different text colors on a variety of colored
- backgrounds.
-
-
- gettextcursor
-
- ■ Interface
-
- INTERFACE TO FUNCTION gettextcursor()
- INTEGER*2 gettextcursor[FAR, C, ALIAS:"__gettextcursor"]
- END
-
- ■ Description
-
- The gettextcursor function returns the current cursor attribute (the shape).
- Note that this function works in text video modes only.
-
- This function is also available under OS/2.
-
- ■ Return value
-
- Returns the current cursor attribute or -1 if an error occurs (such as
- calling the function in a non-text video mode).
-
- ■ See also
-
- displaycursor, settextcursor
-
- ■ Example
-
- See the example program for settextcursor.
-
-
- gettextposition
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + gettextposition[FAR, C, ALIAS:"__f_gettextposition"](s)
- STRUCTURE/rccoord/
- INTEGER*2 row ! Row coordinate
- INTEGER*2 col ! Column coordinate
- END STRUCTURE
- RECORD/rccoord/s [FAR, REFERENCE] ! Returns the current text pos
- END
-
- ■ Description
-
- The gettextposition function returns the current text position in s, an
- rccoord structure defined in FGRAPH.FD.
-
- The text position given by the coordinates (1, 1) is defined as the upper
- left corner of the text window.
-
- Text output from the outtext function begins at the current text position.
- Font text is not affected by the current text position. Graphics output
- begins at the current graphics output position, which is a separate
- position.
-
- This function is also available under OS/2.
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- settextposition
-
- ■ Example
-
- See the example program for gettextcolor.
-
-
- getviewcoord, getviewcoord_w
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + getviewcoord[FAR, C, ALIAS:"__f_getviewcoord"](x, y, s)
- INTEGER*2 x, y
- STRUCTURE/xycoord/
- INTEGER*2 xcoord ! x-coordinate
- INTEGER*2 ycoord ! y-coordinate
- END STRUCTURE
- RECORD/xycoord/s [FAR, REFERENCE] ! Returns the viewpor
- END
-
- INTERFACE TO SUBROUTINE
- + getviewcoord_w[FAR, C, ALIAS:"__f_getviewcoord_w"](wx, wy, s)
- DOUBLE PRECISION wx, wy
- STRUCTURE/xycoord/
- INTEGER*2 xcoord ! x-coordinate
- INTEGER*2 ycoord ! y-coordinate
- END STRUCTURE
- RECORD/xycoord/s [FAR, REFERENCE] ! Returns the viewpor
- END
-
- ■ Description
-
- The getviewcoord subroutines translate the specified coordinates (x, y) from
- one coordinate system to viewport coordinates and returns them in the
- xycoord structure s, defined in FGRAPH.FD.
-
- The getviewcoord subroutines translate in the following manner:
-
- Routine Translation
-
- getviewcoord Physical coordinates (x, y) to
- viewport coordinates
-
- getviewcoord_w Window coordinates (wx, wy) to
- viewport coordinates
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- getphyscoord, getwindowcoord
-
- ■ Example
-
- See the example program for setviewport.
-
-
- getvideoconfig
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + getvideoconfig[FAR, C, ALIAS:"__getvideoconfig"](s)
- STRUCTURE/videoconfig/
- INTEGER*2 numxpixels ! Number of pixels on x-axis
- INTEGER*2 numypixels ! Number of pixels on y-axis
- INTEGER*2 numtextcols ! Number of text columns available
- INTEGER*2 numtextrows ! Number of text rows available
- INTEGER*2 numcolors ! Number of actual colors
- INTEGER*2 bitsperpixel ! Number of bits per pixel
- INTEGER*2 numvideopages ! Number of available video pages
- INTEGER*2 mode ! Current video mode
- INTEGER*2 adapter ! Active display adapter
- INTEGER*2 monitor ! Active display monitor
- INTEGER*2 memory ! Video adapter memory in K bytes
- END STRUCTURE
- RECORD/videoconfig/s [FAR, REFERENCE]
- END
-
- ■ Description
-
- The getvideoconfig function returns the current graphics environment
- configuration in s, a videoconfig structure defined above and in FGRAPH.FD.
-
- The values returned reflect the currently active monitor as well as the
- currently specified video mode.
-
- The videoconfig structure contains the following elements:
-
- Element Contents
-
- numxpixels Number of pixels on the x-axis
-
- numypixels Number of pixels on the y-axis
-
- numtextcols Number of text columns available
-
- numtextrows Number of text rows available
-
- numcolors Number of actual colors available
-
- bitsperpixel Number of bits per pixel
-
- numvideopages Number of available video pages
-
- mode Current video mode
-
- adapter Active display adapter
-
- monitor Active display monitor
-
- memory Video adapter memory (in
- kilobytes)
-
- The values for the adapter element of the videoconfig structure are given by
- the symbolic constants shown in the list below. For any applicable adapter
- ($CGA, $EGA, or $VGA), the corresponding Olivetti adapter ($OCGA, $OEGA, or
- $OVGA) represents a superset of graphics capabilities.
-
- Adapter Constant Meaning
-
- $MDPA Monochrome Display Adapter
-
- $CGA Color Graphics Adapter
-
- $OCGA Olivetti(R) (AT&T) Color Graphics
- Adapter
-
- $EGA Enhanced Graphics Adapter
-
- $OEGA Olivetti (AT&T) Enhanced Graphics
- Adapter
-
- $VGA Video Graphics Array
-
- $OVGA Olivetti (AT&T) Video Graphics
- Array
-
- $MCGA Multicolor Graphics Array
-
- $HGC Hercules Graphics Card
-
- The values for the monitor element of the videoconfig structure are given by
- the symbolic constants listed below:
-
- Monitor Constant Meaning
-
- $MONO Monochrome monitor
-
- $COLOR Color (or
- enhanced-monitor-emulating color)
-
- $ENHCOLOR Enhanced color
-
- $ANALOG Analog
-
- In every text mode, including monochrome, getvideoconfig returns the value
- 32 for the number of available colors. The value 32 indicates the range of
- values (0-31) accepted by the settextcolor function. This includes 16 normal
- colors (0-15) and 16 blinking colors (16-31). Blinking is selected by adding
- 16 to the normal color value. Monochrome text mode has fewer unique display
- attributes, so some color values are redundant. However, because blinking is
- selected in the same manner, monochrome text mode has the same range (0-31)
- as other text modes.
-
- This subroutine is also available under OS/2.
-
- ■ Return value
-
- Returns the current graphics environment configuration.
-
- ■ Example
-
- See the example program for setvideomoderows.
-
-
- getvisualpage
-
- ■ Interface
-
- INTERFACE TO FUNCTION getvisualpage()
- INTEGER*2 getvisualpage[FAR, C, ALIAS:"__getvisualpage"]
- END
-
- ■ Description
-
- The getvisualpage function returns the current visual page number.
-
- ■ Return value
-
- Returns the page number of the current visual page. All hardware
- combinations support at least one page (page number 0).
-
- This function is also available under OS/2.
-
- ■ See also
-
- getactivepage, gettextcolor, gettextposition, outtext, settextcolor,
- settextposition, settextwindow, setvideomode, setvisualpage, wrapon
-
- ■ Example
-
- See the example program for getactivepage
-
-
- getwindowcoord
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + getwindowcoord[FAR, C, ALIAS:"__getwindowcoord"](x, y, s)
- INTEGER*2 x, y ! Physical point to translate
- STRUCTURE/wxycoord/
- DOUBLE PRECISION wx ! x-coordinate
- DOUBLE PRECISION wy ! y-coordinate
- END STRUCTURE
- RECORD/wxycoord/s [FAR, REFERENCE] ! Returns the window coordina
- END
-
- ■ Description
-
- The getwindowcoord subroutine translates the viewport coordinates (x, y) to
- window coordinates and returns them in the wxycoord structure variable s,
- defined in FGRAPH.FD.
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- getphyscoord, getviewcoord, getviewcoordw, getviewcoordwxy, moveto
-
- ■ Example
-
- See the example program for setviewport.
-
-
- imagesize, imagesize_w
-
- ■ Interface
-
- INTERFACE TO FUNCTION imagesize(x1, y1, x2, y2)
- INTEGER*4 imagesize[FAR, C, ALIAS:"__imagesize"]
- INTEGER*2 x1, y1 ! Upper left corner of image
- INTEGER*2 x2, y2 ! Lower right corner of image
- END
-
- INTERFACE TO FUNCTION imagesize_w(wx1, wy1, wx2, wy2)
- INTEGER*4 imagesize[FAR, C, ALIAS:"__f_imagesize_w"]
- DOUBLE PRECISION wx1, wy1 ! Upper left corner of image
- DOUBLE PRECISION wx2, wy2 ! Lower right corner of image
- END
-
-
- ■ Description
-
- The imagesize functions return the number of bytes needed to store the image
- defined by the bounding rectangle, which is specified by the coordinates
- given in the function call. The imagesize function defines the bounding
- rectangle in terms of viewport-coordinate points (x1, y1) and (x2, y2). This
- size is determined by the following formula:
-
- xwid = abs( x1-x2 )+1
- ywid = abs( y1-y2 )+1
- size = 4 + INT( ( xwid*bits_per_pixel+7 )/8 )*INT( ywid ) )
-
- The bits_per_pixel value returns from a call to getvideoconfig as
- bitsperpixel.
-
- The imagesize_w function defines the bounding rectangle in terms of
- window-coordinate points (x1, y1) and (x2, y2).
-
-
- ■ Return value
-
- The imagesize and imagesize_w functions return the storage size of an image
- in bytes.
-
-
- ■ See also
-
- getvideoconfig
-
-
- ■ Example
-
- CC ANIMATE.FOR - Illustrates animation functions including:
- CC imagesize getimage putimage
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*1 buffer[ALLOCATABLE] (:)
- INTEGER*2 dummy, x, y, error, action(5)
- INTEGER*4 imsize
- CHARACTER*6 descrip(5)
- RECORD /rccoord/ curpos
-
- DATA action / $GPSET, $GPRESET, $GXOR, $GOR, $GAND /
- DATA descrip / 'PSET ', 'PRESET', 'XOR ', 'OR ', 'AND ' /
-
- C
- C Find graphics mode.
- C
- IF( setvideomode( $MAXRESMODE ) .EQ. 0 )
- + STOP 'Error: cannot set graphics mode'
-
- dummy = setcolor( 3 )
- y = 30
- DO i = 1, 5
- x = 50
- y = y + 40
- C
- C Display action type.
- C
- CALL settextposition( 1, 1, curpos )
- CALL outtext( descrip(i) )
- C
- C Draw and measure ellipse, allocate memory for image.
- C
- dummy = ellipse( $GFILLINTERIOR, x - 15, y - 15, x + 15,
- + y + 15 )
- imsize = imagesize( x - 16, y - 16, x + 16, y + 16 )
- ALLOCATE( buffer( imsize ), STAT = error )
- IF( error .NE. 0 ) THEN
- dummy = setvideomode( $DEFAULTMODE )
- STOP 'Error: insufficient memory'
- END IF
- C
- C Get master copy of ellipse.
- C
- CALL getimage( x - 16, y - 16, x + 16, y + 16, buffer )
- C
- C Copy row of ellipses with specified action.
- C
- DO x = 55, 255, 5
- CALL putimage( x - 16, y - 16, buffer, action(i) )
- END DO
-
- C
- C Free memory, wait for ENTER key to continue.
- C
- DEALLOCATE( buffer )
- READ (*,*)
- END DO
-
- dummy = setvideomode( $DEFAULTMODE )
- END
-
- This program shows different methods of animating an image on the screen.
-
-
- lineto, lineto_w
-
- ■ Interface
-
- INTERFACE TO FUNCTION lineto(x, y)
- INTEGER*2 lineto[FAR, C, ALIAS:"__lineto"]
- INTEGER*2 x, y ! End point
- END
-
- INTERFACE TO FUNCTION lineto_w(wx, wy)
- INTEGER*2 lineto[FAR, C, ALIAS:"__f_lineto_w"]
- DOUBLE PRECISION wx, wy ! End point
- END
-
- ■ Description
-
- The lineto functions draw a line from the current position up to and
- including the destination point. The destination point for lineto is given
- by the viewport-coordinate point (x, y). The destination point for the
- lineto_w function is given by the window-coordinate point (wx, wy).
-
- The line is drawn using the current color and line style. If no error
- occurs, lineto sets the current position to the view point (x, y) and
- lineto_w sets the current position to the window point (wx, wy).
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- If you use floodfill to fill in a closed figure drawn with lineto calls,
- the figure must be drawn with a solid line-style pattern.
- ───────────────────────────────────────────────────────────────────────────
-
- ■ Return value
-
- The lineto and lineto_w routines return a nonzero value if the line is drawn
- successfully; otherwise, they return 0.
-
- ■ See also
-
- getcurrentposition, setlinestyle
-
- ■ Example
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
- INTEGER*2 dummy
- RECORD /xycoord/ xy
-
- dummy = setvideomode( $MRES16COLOR )
- CALL moveto( 80, 50, xy )
- dummy = lineto( 240, 150 )
- dummy = lineto( 240, 50 )
- READ (*,*) ! Press ENTER to exit
- dummy = setvideomode( $DEFAULTMODE )
- END
-
- This program draws the figure shown in Figure R.3.
-
- See also the example program for setpixel and setviewport.
-
-
- moveto, moveto_w
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE moveto[FAR, C, ALIAS:"__f_moveto"](x, y, s)
- INTEGER*2 x, y
- STRUCTURE/xycoord/
- INTEGER*2 xcoord ! x-coordinate
- INTEGER*2 ycoord ! y-coordinate
- END STRUCTURE
- RECORD/xycoord/s [FAR, REFERENCE] ! Returns the previous position
- END
-
- INTERFACE TO SUBROUTINE
- + moveto_w[FAR, C, ALIAS:"__f_moveto_w"](wx, wy, s)
- INTEGER*2 wx, wy
- STRUCTURE/wxycoord/
- DOUBLE PRECISION wx ! x-window coordinate
- DOUBLE PRECISION wy ! y-window coordinate
- END STRUCTURE
- RECORD/wxycoord/s [FAR, REFERENCE] ! Returns the previous position
- END
-
- ■ Description
-
- The moveto functions move the current position to the specified point. The
- moveto function uses the view-coordinate point (x, y) as the current
- position. The moveto_w function use the window-coordinate point (wx, wy) as
- the current position. No drawing takes place.
-
- The function assigns the coordinates of the previous position to s. The
- moveto function assigns the coordinates in s, an xycoord structure defined
- in FGRAPH.FD. The function moveto_w assigns the coordinates in s, a wxycoord
- structure defined in FGRAPH.FD.
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- lineto
-
- ■ Example
-
- See the example program for setpixel and setviewport.
-
-
- outgtext
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + outgtext[FAR, C, ALIAS:"__f_outgtext"](text)
- CHARACTER*(*) text [FAR, REFERENCE]
- END
-
- ■ Description
-
- The outgtext function sends the string text to the screen, including any
- trailing blanks. The text is output using the current font at the current
- graphics position and in the current color.
-
- No formatting is provided.
-
- After it outputs the text, outgtext updates the current graphics position.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- This function operates only in graphics video modes (such as
- $MRES4COLOR). Because it is a graphics function, the color of text is set
- by the setcolor function, not by settextcolor.
- ───────────────────────────────────────────────────────────────────────────
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- moveto, setcolor, setfont
-
- ■ Example
-
- See the example program for registerfonts.
-
-
- outtext
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE outtext[FAR, C, ALIAS:"__f_outtext"](text)
- CHARACTER*(*) text [FAR, REFERENCE]
- END
-
- ■ Description
-
- The outtext function sends the string text to the screen, including any
- trailing blanks. No formatting is provided. This function will work in any
- screen mode. Text output begins at the current text position.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- To output text using special fonts, you must use the outgtext function.
- ───────────────────────────────────────────────────────────────────────────
-
- This function is also available under OS/2.
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- setactivepage, settextposition
-
- ■ Example
-
- See the example program for gettextcolor and setvideomoderows.
-
-
- pie, pie_w
-
- ■ Interface
-
- INTERFACE TO FUNCTION pie(i, x1, y1, x2, y2, x3, y3, x4, y4)
- INTEGER*2 pie[FAR, C, ALIAS:"__f_pie"]
- INTEGER*2 i ! Fill flag
- INTEGER*2 x1, y1 ! Upper left corner of bounding rectangle
- INTEGER*2 x2, y2 ! Lower right corner of bounding rectangle
- INTEGER*2 x3, y3 ! Start vector
- INTEGER*2 x4, y4 ! End vector
- END
-
- INTERFACE TO FUNCTION pie_w(i, wx1, wy1, wx2, wy2, wx3, wy3, wx4, wy4)
- INTEGER*2 pie[FAR, C, ALIAS:"__f_pie_w"]
- INTEGER*2 i ! Fill flag
- DOUBLE PRECISION wx1, wy1 ! Upper left corner of bounding rectangle
- DOUBLE PRECISION wx2, wy2 ! Lower right corner of bounding rectangle
- DOUBLE PRECISION wx3, wy3 ! Start vector
- DOUBLE PRECISION wx4, wy4 ! End vector
- END
-
- ■ Description
-
- The pie functions draw a pie-shaped wedge by drawing an elliptical arc whose
- center and two endpoints are joined by lines.
-
- The pie function uses the viewport-coordinate system. The center of the arc
- is the center of the bounding rectangle, which is specified by the
- viewport-coordinate points (x1, y1) and (x2, y2). The arc starts where it
- intersects the vector defined by (x3, y3) and ends where it intersects the
- vector (x4, y4).
-
- The pie_w function uses the window-coordinate system. The center of the arc
- is the center of the bounding rectangle specified by the window-coordinate
- pairs (wx1, wy1) and (wx2, wy2). The arc starts where it intersects the
- vector defined by (wx3, wy3) and ends where it intersects the vector defined
- by (wx4, wy4).
-
- The wedge is drawn using the current color moving in a counterclockwise
- direction. The control parameter can be one of the following symbolic
- constants:
-
- Constant Action
-
- $GFILLINTERIOR Fills the figure using the
- current color and fill mask
-
- $GBORDER Does not fill the figure
-
- The control option given by $GFILLINTERIOR is equivalent to a subsequent
- call to the floodfill function using the center of the ellipse as the
- starting point and the current color (set by setcolor) as the boundary
- color.
-
- ■ Return value
-
- The pie and pie_w functions return a nonzero value if the pie is drawn
- successfully; otherwise, they return 0.
-
- ■ See also
-
- arc, ellipse, floodfill, getcolor, lineto, rectangle, setcolor,
- setfillmask
-
- ■ Example
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
- INTEGER*2 dummy
-
- dummy = setvideomode( $MRES16COLOR )
- dummy = pie( $GBORDER, 80, 50, 240, 150, 240, 12, 0, 150 )
- READ (*,*) ! Press ENTER to exit
- dummy = setvideomode( $DEFAULTMODE )
- END
-
- This program draws the "pie" wedge shown in Figure R.4.
-
- See also the example program for setpixel.
-
-
- putimage, putimage_w
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + putimage[FAR, C, ALIAS:"__putimage"](x, y, image, action)
- INTEGER*2 x, y ! Position of upper left corne
- INTEGER*2 action ! Interaction with existing sc
- INTEGER*1 image [FAR, REFERENCE](*) ! Stored image buffer
- END
-
- INTERFACE TO SUBROUTINE
- + putimage_w[FAR, C, ALIAS:"__f_putimage_w"](wx, wy, image, action)
- INTEGER*2 wx, wy ! Position of upper left corne
- INTEGER*2 action ! Interaction with existing sc
- INTEGER*1 image [FAR, REFERENCE](*) ! Stored image buffer
- END
-
- ■ Description
-
- The putimage function transfers to the screen the image stored in image. In
- the putimage function, the upper left corner of the image is placed at the
- viewport-coordinate point (x, y).
-
- In the putimage_w function, the upper left corner of the image is placed at
- the window-coordinate point (wx, wy).
-
- The action argument defines the interaction between the stored image and the
- one that is already on the screen. It may be any one of the following
- symbolic constants (defined in FGRAPH.FD):
-
- Constant Meaning
-
- $GAND Transfers the image over an
- existing image on the screen. The
- resulting image is the logical
- AND of the two images: points
- that have the same color in both
- the existing image and the new
- one will remain the same color,
- while points that have different
- colors are joined by logical AND.
-
- $GOR Superimposes the image onto an
- existing image. The new image
- does not erase the previous
- screen contents.
-
- $GPRESET Transfers the data point by point
- onto the screen. Each point has
- the inverse of the color
- attribute it had when it was
- taken from the screen by
- getimage, producing a negative
- image.
-
- $GPSET Transfers the data point by point
- onto the screen. Each point has
- the exact color attribute it had
- when it was taken from the screen
- by getimage.
-
- $GXOR Causes the points on the screen
- to be inverted where a point
- exists in the image buffer. This
- behavior is exactly like that of
- the cursor: when an image is put
- against a complex background
- twice, the background is restored
- unchanged. This allows you to
- move an object around without
- erasing the background. The $GXOR
- constant is a special mode often
- used for animation.
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- getimage, imagesize
-
- ■ Example
-
- See the example program for imagesize.
-
-
- rectangle, rectangle_w
-
- ■ Interface
-
- INTERFACE TO FUNCTION rectangle(control, x1, y1, x2, y2)
- INTEGER*2 rectangle[FAR, C, ALIAS:"__rectangle"]
- INTEGER*2 control ! Fill flag
- INTEGER*2 x1, y1 ! Upper left corner
- INTEGER*2 x2, y2 ! Lower right corner
- END
-
- INTERFACE TO FUNCTION rectangle_w(control, wx1, wy1, wx2, wy2)
- INTEGER*2 rectangle[FAR, C, ALIAS:"__f_rectangle_w"]
- INTEGER*2 control ! Fill flag
- DOUBLE PRECISION wx1, wy1 ! Upper left corner
- DOUBLE PRECISION wx2, wy2 ! Lower right corner
- END
-
- ■ Description
-
- The rectangle functions draw a rectangle with the current line style.
-
- The rectangle function uses the viewport-coordinate system. The
- viewport-coordinate points (x1, y1) and (x2, y2) are the diagonally opposed
- corners of the rectangle.
-
- The rectangle_w function uses the window-coordinate system. The
- window-coordinate points (wx1, wy1) and (wx2, wy2) are the diagonally
- opposed corners of the rectangle.
-
- The control parameter can be one of the following symbolic constants defined
- in the include file FGRAPH.FD:
-
- Constant Action
-
- $GFILLINTERIOR Fills the figure with the current
- color using the current fill mask
-
- $GBORDER Does not fill the rectangle
-
- If the current fill mask is all zeros, no mask is used. Instead, the
- rectangle is filled with the current color.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- If you try to fill the rectangle with the floodfill function, the
- rectangle must be bordered by a solid line-style pattern.
- ───────────────────────────────────────────────────────────────────────────
-
- ■ Return value
-
- The rectangle and rectangle_w functions return a nonzero value if the
- rectangle is drawn successfully, 0 if not.
-
- ■ See also
-
- floodfill, getcolor, getlinestyle, setcolor, setlinestyle
-
- ■ Example
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
- INTEGER*2 dummy
-
- dummy = setvideomode( $MRES16COLOR )
- dummy = rectangle( $GBORDER, 80, 50, 240, 150 )
- READ (*,*) ! Press ENTER to exit
- dummy = setvideomode( $DEFAULTMODE )
- END
-
- This program draws the rectangle shown in Figure R.5.
-
- See also the example program for setpixel, setvieworg, and setviewport.
-
-
- registerfonts
-
- ■ Interface
-
- INTERFACE TO FUNCTION registerfonts(filename)
- INTEGER*2 registerfonts
- + [FAR, C, ALIAS:"__f_registerfonts"]
- CHARACTER*(*) filename
- + [FAR, REFERENCE] ! File name of .FON files to register
- END
-
- ■ Description
-
- The registerfonts function initializes the fonts graphics system. Font files
- must be registered with the registerfonts function before any other
- font-related library functions (getgtextextent, setfont, outgtext,
- unregisterfonts) can be used.
-
- The registerfonts function reads the specified files and loads font header
- information into memory. Each font header takes up about 140 bytes of
- memory.
-
- The filename argument is the path specification and file name of valid .FON
- files. The filename can contain standard DOS wild-card characters.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- The font functions affect only the output from the font output function
- outgtext; no other FORTRAN run-time output functions are affected by font
- usage.
- ───────────────────────────────────────────────────────────────────────────
-
- ■ Return value
-
- Returns a positive value that indicates the number of fonts successfully
- registered. A negative return value indicates failure. The following
- negative values may be returned:
-
- Value Meaning
-
- -1 No such file or directory
-
- -2 One or more of the .FON files was
- not a valid, binary .FON file
-
- -3 One or more of the .FON files is
- damaged
-
- ■ See also
-
- getfontinfo, getgtextextent, outgtext, setfont, unregisterfonts
-
- ■ Example
-
- CC FONTS.FOR - Illustrates fonts functions including:
- CC getfontinfo outgtext setfont
- CC getgtextextent registerfonts unregisterfonts
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- PARAMETER ( NFONTS = 6 )
-
- INTEGER*2 dummy, x, y, iend
- INTEGER*4 ifont
- CHARACTER*11 face(NFONTS)
- CHARACTER*10 options(NFONTS)
- CHARACTER*20 list
- CHARACTER*64 fontpath
- RECORD /videoconfig/ vc
- RECORD /xycoord/ xy
- RECORD /fontinfo/ fi
-
- DATA face / "Courier" , "Helvetica" , "Times Roman",
- + "Modern" , "Script" , "Roman" /
- DATA options / "t'courier'", "t'helv'" , "t'tms rmn'" ,
- + "t'modern'" , "t'script'" , "t'roman'" /
-
- CALL clearscreen( $GCLEARSCREEN )
- WRITE (*,*) 'Enter file specification for .FON files'
- WRITE (*,*) '[pathname\*.FON]:'
- WRITE (*,*)
- READ (*, '(A)') fondir
- C
- C Locate .FON files, then register fonts by reading header
- C information from all files.
- C
- IF( registerfonts( '*.FON' ). LT. 0 ) THEN
- WRITE (*, '(A/)') ' Enter directory for .FON files:'
- READ (*, '(A )') fontpath
- iend = INDEX( fontpath, ' ' )
- fontpath( iend:iend + 5 ) = '\*.FON'
- IF( registerfonts( fontpath ). LT. 0 )
- + STOP 'Error: cannot find font files'
- ENDIF
-
- C
- C Find graphics mode.
- C
- IF( setvideomode( $MAXRESMODE ) .EQ. 0 )
- + STOP 'Error: cannot set graphics mode'
- CALL getvideoconfig( vc )
-
- C
- C Display each font name centered on screen.
- C
- DO ifont = 1, NFONTS
-
- C
- C Build options string.
- C
- list = options( ifont ) // 'h30w24b'
-
- CALL clearscreen( $GCLEARSCREEN )
- IF( setfont( list ) .EQ. 0 ) THEN
- C
- C Use length of text and height of font to center text.
- C
- x = ( vc.numxpixels - getgtextextent
- + ( face( ifont ) ) ) / 2
- IF( getfontinfo( fi ) .NE. 0 ) THEN
- CALL outtext( 'Error: cannot get font info' )
- READ (*,*)
- END IF
- y = ( vc.numypixels - fi.ascent ) / 2
- CALL moveto( x, y, xy )
- IF( vc.numcolors .GT. 2 ) dummy = setcolor( ifont )
- CALL outgtext( face( ifont ) )
- ELSE
- CALL outtext( 'Error: cannot set font' )
- END IF
- READ (*,*)
- END DO
- CALL unregisterfonts()
- dummy = setvideomode( $DEFAULTMODE )
- END
-
- The program FONTS.FOR displays the fonts provided with the FORTRAN Graphics
- Library
-
-
- remapallpalette, remappalette
-
- ■ Interface
-
- INTERFACE TO FUNCTION remapallpalette(colors)
- INTEGER*2 remapallpalette[FAR, C, ALIAS:"__remapallpalette"]
- INTEGER*4 colors [FAR, REFERENCE](*) ! Color value array
- END
-
- INTERFACE TO FUNCTION remappalette(index, color)
- INTEGER*4 remappalette[FAR, C, ALIAS:"__remappalette"]
- INTEGER*4 color ! Color value to assign color
- INTEGER*2 index ! Color index to reassign
- END
-
- ■ Description
-
- The remapallpalette function remaps all of the available color indexes
- simultaneously. The colors argument points to an array of color values. The
- default array of color indexes is shown below.
-
-
- Index Color Index Color
-
- 0 Black 8 Dark gray
- 1 Blue 9 Light blue
- 2 Green 10 Light green
- 3 Cyan 11 Light cyan
- 4 Red 12 Light red
- 5 Magenta 13 Light magenta
- 6 Brown 14 Yellow
- 7 White 15 Bright white
-
- The number of colors mapped depends on the number of colors supported by the
- current video mode. A 16-color mode will map all the colors shown, from 0 to
- 15. An eight-color mode will map only the colors from 0 to 7. A four-color
- mode will use one of the standard palettes supported by the EGA (see
- selectpalette). A two-color mode will support the colors 0 and 7 (black and
- white).
-
- If colors is an eight-element array whose members are 1, 3, 5, 7, 2, 4, 6,
- and 8, these color indexes would be mapped to actual colors in an
- eight-color video mode, as shown below.
-
-
- Index Color Index Color
-
- 1 Blue 5 Magenta
- 2 Green 6 Brown
- 3 Cyan 7 White
- 4 Red 8 Dark gray
-
- You are simply mapping a set of color values to the ordinal numbers
- recognized by the hardware; colors can be larger than the number of colors
- supported by the current video mode. Only the first n colors are available,
- where n is the number of colors supported by the current video mode. The
- remappalette function remaps one color index to color, a color value
- supported by the current video mode. Both functions immediately affect the
- current display.
-
- The VGA color graphics modes support a palette of 262,144 colors (256K).
- Three bytes of data represent the intensities of red, blue, and green. In
- each byte, the two high-order bits must be 0. The remaining six bits
- represent the intensity of blue, green, and red (reading from high-order
- byte to low-order byte). For example, to make a low-intensity white color,
- equal values of red, green, and blue are used. Thus the three-byte color
- value is
-
- blue byte green byte red byte
- 00011111 00011111 00011111
- high order ------------------------> low order
-
- Because of the splitting of colors between bytes, the color values are not
- continuous. Symbolic constants for the default color values are supplied to
- provide compatibility with EGA practice. The names of these constants are
- listed below.
-
-
- Index Constant Index Constant
-
- 0 $BLACK 8 $GRAY
- 1 $BLUE 9 $LIGHTBLUE
- 2 $GREEN 10 $LIGHTGREEN
- 3 $CYAN 11 $LIGHTCYAN
- 4 $RED 12 $LIGHTRED
- 5 $MAGENTA 13 $LIGHTMAGENTA
- 6 $BROWN 14 $LIGHTYELLOW
- 7 $WHITE 15 $BRIGHTWHITE
-
- Both the remappalette and remapallpalette functions work in all video modes,
- but only with an EGA or VGA.
-
-
- ■ Return value
-
- If successful, remapallpalette returns a nonzero value. If the function is
- inoperative (that is, running under a configuration other than an EGA or
- VGA), it returns 0.
-
- If successful, remappalette returns the previous color value for the given
- color index. If unsuccessful, it returns -1.
-
-
- ■ See also
-
- selectpalette, setbkcolor, setvideomode
-
-
- ■ Example
-
- CC PALETTE.FOR - Illustrates functions for assigning color values
- CC to color indexes. Functions include:
- CC remapallpalette remappalette
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy2, mode, cells, x, y, xinc, yinc, i
- INTEGER*4 dummy4, pal( 256 ), iblue, ired, igreen
- INTEGER*4 RGB, tmp, inc
- CHARACTER*3 str1, str2
- RECORD /videoconfig/ vc
-
- C
- C Make sure all palette numbers are valid.
- C
- DO i = 1, 256
- pal( i ) = $BLACK
- END DO
- C
- C Loop through each graphics mode that supports palettes.
- C
-
- DO mode = $MRES4COLOR, $MRES256COLOR
- IF( mode .EQ. $ERESNOCOLOR ) CYCLE
- IF( setvideomode( mode ) .EQ. 0 ) CYCLE
-
- C
- C Get configuration variables for current mode.
- C
- CALL getvideoconfig( vc )
- SELECT CASE( vc.numcolors )
-
- CASE( 256 )
- C
- C Active bits in this order:
- C ???????? ??bbbbbb ??gggggg ??rrrrrr
- C
- cells = 13
- inc = 12
-
- CASE( 16 )
- C
- C If $ERES or $VRES16, active bits in this order:
- C ???????? ??????bb ??????gg ??????rr
- C
- C Else in this order:
- C ???????? ??????Bb ??????Gg ??????Rr
- C
- cells = 4
- inc = 32
- IF( ( vc.mode .EQ. $ERESCOLOR ) .OR.
- + ( vc.mode .EQ. $VRES16COLOR ) ) inc = 16
-
- CASE( 4 )
- C
- C Active bits in this order:
- C ???????? ??????Bb ??????Gg ??????Rr
- C
- cells = 2
- inc = 32
-
- CASE DEFAULT
- CYCLE
-
- END SELECT
-
- xinc = vc.numxpixels / cells
- yinc = vc.numypixels / cells
-
- C
- C Fill palette arrays in BGR order.
- C
- i = 1
- DO iblue = 0, 63, inc
- DO igreen = 0, 63, inc
- DO ired = 0, 63, inc
- pal( i ) = RGB( ired, igreen, iblue )
- C
- C Special case: using 6 bits to represent 16 colors
- C If both bits are on for a color, intensity is set
- C If one bit is set for a color, the color is on.
- C
- IF( inc .EQ. 32 )
- + pal( i + 8 ) = pal( i ) .OR. ( pal( i ) / 2 )
- i = i + 1
- END DO
- END DO
- END DO
- C
- C If palettes available, remap all palettes at once.
- C Otherwise, quit.
- C
- IF( remapallpalette( pal ) .EQ. 0 ) THEN
- dummy2 = setvideomode( $DEFAULTMODE )
- STOP 'Palettes not available with this adapter'
- END IF
- C
- C Draw colored squares.
- C
- i = 0
- DO x = 0, ( xinc * cells ) - 1, xinc
- DO y = 0, ( yinc * cells ) - 1, yinc
- dummy2 = setcolor( INT4( i ) )
- dummy2 = rectangle( $GFILLINTERIOR, x, y, x + xinc,
- + y + yinc )
- i = i + 1
- END DO
- END DO
-
- dummy2 = setcolor( INT4( vc.numcolors / 2 ) )
- WRITE (str1, '(I3)') vc.mode
- WRITE (str2, '(I3)') vc.numcolors
- CALL outtext( 'Mode' // str1 // ' has' //
- + str2 // ' colors' )
- READ (*,*)
-
- C
- C Change each palette entry separately in GRB order.
- C
- i = 0
- DO igreen = 0, 63, inc
- DO ired = 0, 63, inc
- DO iblue = 0, 63, inc
- tmp = RGB( ired, igreen, iblue )
- dummy4 = remappalette( i, tmp )
- IF( inc .EQ. 32 )
- + dummy4 = remappalette(i + 8, tmp.OR.(tmp / 2))
- i = i + 1
- END DO
- END DO
- END DO
-
- READ (*,*) ! Wait for ENTER to be pressed
- END DO
-
- dummy2 = setvideomode( $DEFAULTMODE )
- END
-
-
-
- CC RGB - Function for mixing red, green, and blue color elements.
- CC
- CC Params: r, g, b - Values for red, green, and blue, respectively
- CC
- CC Return: Mixed color value
-
- INTEGER*4 FUNCTION RGB( r, g, b )
- INTEGER*4 r, g, b
-
- RGB = ISHL( ISHL( b, 8 ) .OR. g, 8 ) .OR. r
- RETURN
- END
-
- The program PALETTE.FOR shows the effects of using and remapping palettes.
-
-
- selectpalette
-
- ■ Interface
-
- INTERFACE TO FUNCTION selectpalette(number)
- INTEGER*2 selectpalette[FAR, C, ALIAS:"__selectpalette"]
- INTEGER*2 number ! Palette number
- END
-
- ■ Description
-
- The selectpalette function works only under the video modes $MRES4COLOR and
- $MRESNOCOLOR. A palette consists of a selectable background color (Color 0)
- and three set colors. Under the $MRES4COLOR mode the number argument selects
- one of the four predefined palettes shown in Table R.2.
-
- Table R.2 $MRES4COLOR Mode Palette Colors
-
- Color Index
- Palette
- Number Color 1 Color 2 Color 3
-
- 0 Green Red Brown
- 1 Cyan Magenta Light gray
- 2 Light green Light red Yellow
- 3 Light cyan Light magenta White
-
- The $MRESNOCOLOR video mode is used with black-and-white displays, producing
- palettes consisting of various shades of gray. It will also produce color
- when used with a color display. The number of palettes available depends
- upon whether a CGA or EGA hardware package is employed. Under a CGA
- configuration, only the two palettes shown in Table R.3 are available.
-
- Table R.3 $MRESNOCOLOR Mode CGA Palette Colors
-
- Color Index
- Palette
- Number Color 1 Color 2 Color 3
-
- 0 Blue Red Light gray
- 1 Light blue Light red White
-
- Under the EGA configuration, the three palettes shown in Table R.4 are
- available in the $MRESNOCOLOR video mode.
-
- Table R.4 $MRESNOCOLOR Mode EGA Palette Colors
-
- Color Index
- Palette
- Number Color 1 Color 2 Color 3
-
- 0 Green Red Brown
- 1 Light green Light red Yellow
- 2 Light cyan Light red Yellow
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- With an EGA in $MRESNOCOLOR video mode, Palette 3 is identical to
- Palette 1.
- ───────────────────────────────────────────────────────────────────────────
-
- ■ Return value
-
- Returns the value of the previous palette.
-
- ■ See also
-
- getvideoconfig, setvideomode
-
- ■ Example
-
- CC CGAPAL.FOR - Illustrates CGA palettes using:
- CC selectpalette
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy2
- INTEGER*4 dummy4, bkcolor( 8 )
- CHARACTER*7 bkname( 8 )
- CHARACTER*40 str
- RECORD /rccoord/ curpos
-
- DATA bkcolor / $BLACK , $BLUE , $GREEN , $CYAN ,
- + $RED , $MAGENTA , $BROWN , $WHITE /
- DATA bkname / 'BLACK', 'BLUE' , 'GREEN', 'CYAN' ,
- + 'RED' , 'MAGENTA', 'BROWN', 'WHITE' /
-
- C
- C Set video mode.
- C
- IF( setvideomode( $MRES4COLOR ) .EQ. 0 )
- + STOP 'Error: cannot set CGA color mode'
- C
- C Palette loop
- C%
- DO i = 0, 3
- dummy2 = selectpalette( i )
- C
- C Background color loop
- C
- DO k = 1, 8
- CALL clearscreen( $GCLEARSCREEN )
- dummy4 = setbkcolor( bkcolor(k) )
- CALL settextposition( 1, 1, curpos )
- WRITE ( str, 9000 ) bkname( k ), i
- CALL outtext( str )
- C
- C Foreground color loop
- C
- DO j = 1, 3
- dummy2 = setcolor( INT4( j ) )
- dummy2 = ellipse( $GFILLINTERIOR, 100, j * 30, 220,
- + 80 + ( j * 30 ) )
- END DO
- READ (*,*) ! Wait for ENTER to be pressed
- END DO
- END DO
-
- dummy2 = setvideomode( $DEFAULTMODE )
-
- 9000 FORMAT ('Background: ', A, 10x, 'Palette: ', I2)
-
- END
-
- The program CGAPAL.FOR draws a series of line segments while continuously
- changing the current palette.
-
-
- setactivepage
-
- ■ Interface
-
- INTERFACE TO FUNCTION setactivepage(page)
- INTEGER*2 setactivepage[FAR, C, ALIAS:"__setactivepage"]
- INTEGER*2 page ! Memory page number
- END
-
- ■ Description
-
- For hardware and mode configurations with enough memory to support
- multiple-screen pages, setactivepage specifies where in memory graphics
- output is written. The page argument selects the current active page. The
- default page number is 0.
-
- Objects on the screen can be animated by alternating the graphics pages
- displayed. Use the setvisualpage function to display a completed graphics
- page while executing graphics statements in another active page.
-
- These functions can also be used to control text output if you use text
- functions, such as gettextcolor, gettextcursor, gettextposition, outtext,
- settextcolor, settextcursor, settextposition, settextwindow, and wrapon,
- instead of the standard FORTRAN I/O functions.
-
- This function is also available under OS/2.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- The CGA hardware configuration has only 16K of RAM available to support
- multiple-video pages, and only in the text mode. The EGA and VGA
- configurations may be equipped with up to 256K of RAM for multiple-video
- pages in graphics mode.
- ───────────────────────────────────────────────────────────────────────────
-
- ■ Return value
-
- If successful, returns the page number of the previous active page. If the
- function fails, it returns -1.
-
- ■ See also
-
- getactivepage, getvisualpage, gettextcolor, gettextposition, outtext,
- settextcolor, settextposition, settextwindow, setvideomode,
- setvisualpage, wrapon
-
- ■ Example
-
- See the example program for getactivepage.
-
-
- setbkcolor
-
- ■ Interface
-
- INTERFACE TO FUNCTION setbkcolor(color)
- INTEGER*4 setbkcolor[FAR, C, ALIAS:"__setbkcolor"]
- INTEGER*4 color ! Desired color
- END
-
- ■ Description
-
- The setbkcolor function sets the current background color to the color value
- color.
-
- In a color text mode (such as $TEXTC80), setbkcolor accepts a color index.
- The value for the default colors is listed in the description of the
- settextcolor function. For example, setbkcolor(2) sets the background color
- to color index 2. The actual color displayed depends on the palette mapping
- for pixel value 2. The default is green in a color text mode.
-
- In a color graphics mode (such as $ERESCOLOR), setbkcolor accepts a color
- value. The value for the background color is given by the symbolic constants
- defined in the include file FGRAPH.FD. For example, setbkcolor($GREEN) sets
- the background color in a graphics mode to green. These symbolic constants
- are provided as a convenience in defining and manipulating the most common
- colors. The actual range of colors is much greater.
-
- The function setcolor accepts an INTEGER*4 value as an argument. It is a
- color index.
-
- Whenever an argument is INTEGER*4, it refers to a color value, and whenever
- it is INTEGER*2, it refers to a color index. The two exceptions are the
- functions setbkcolor and getbkcolor.
-
- Since the background color is color index 0, the remappalette function will
- do the same thing that setbkcolor does. Unlike remappalette, however,
- setbkcolor does not require an EGA or VGA environment.
-
- In a text mode, the setbkcolor function does not affect anything already
- appearing on the display; stebkcolor affects only the subsequent output. In
- a graphics mode, it immediately changes all background pixels.
-
- This function is also available under OS/2.
-
- ■ Return value
-
- Returns the pixel color value of the old background color.
-
- ■ See also
-
- getbkcolor, remappalette, selectpalette
-
- ■ Example
-
- See the example program for gettextcolor.
-
-
- setcliprgn
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + setcliprgn[FAR, C, ALIAS:"__setcliprgn"](x1, y1, x2, x2)
- INTEGER*2 x1, y1 ! Upper left corner of clip region
- INTEGER*2 x2, y2 ! Lower right corner of clip region
- END
-
- ■ Description
-
- The setcliprgn function limits the display of subsequent graphics output and
- font text output to the part that fits within a particular area of the
- screen (the "clipping region"). The physical points (x1, y1) and (x2, y2)
- are the upper left and lower right corners of the rectangle that defines the
- clipping region. The setcliprgn function does not change the
- viewport-coordinate system; it merely masks the screen.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- The setcliprgn function affects graphics and font text output only. To
- mask the screen for text output, use the settextwindow function.
- ───────────────────────────────────────────────────────────────────────────
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- settextwindow, setvieworg, setviewport, setwindow
-
- ■ Example
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
- INTEGER*2 dummy
-
- dummy = setvideomode( $MRES16COLOR )
- CALL setcliprgn( 0, 0, 200, 125 )
- dummy = ellipse( $GBORDER, 80, 50, 240, 200 )
- READ (*,*) ! Press ENTER to exit
- dummy = setvideomode( $DEFAULTMODE )
- END
-
- This program draws an ellipse lying partly within a clipping region, as
- shown in Figure R.6.
-
- See also the example program for setvieworg.
-
-
- setcolor
-
- ■ Interface
-
- INTERFACE TO FUNCTION setcolor(color)
- INTEGER*2 setcolor[FAR, C, ALIAS:"__setcolor"]
- INTEGER*2 color ! Desired color index
- END
-
- ■ Description
-
- The setcolor function sets the current color index to color. The color
- parameter is masked but always within range. The following graphics
- functions use the current color: arc, ellipse, floodfill, lineto, outgtext,
- pie, rectangle, and setpixel.
-
- The setcolor function accepts an INTEGER*2 value as an argument. It is a
- color index.
-
- The default color index is the highest numbered color index in the current
- palette.
-
- ■ Return value
-
- Returns the previous color. If setcolor fails (if used in a text mode), it
- returns -1.
-
- ■ See also
-
- arc, ellipse, floodfill, getcolor, lineto, outgtext, pie, rectangle,
- selectpalette, setpixel
-
- ■ Example
-
- See the example program for setlinestyle.
-
-
- setfillmask
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + setfillmask[FAR, C, ALIAS:"__setfillmask"](mask)
- INTEGER*1 mask[FAR, REFERENCE](8) ! Mask array
- END
-
- ■ Description
-
- The setfillmask function sets the current fill mask. The mask is an
- 8-by-8-bit array, where each bit represents a pixel. A 1 bit sets the
- corresponding pixel to the current color, while a 0 bit leaves the pixel
- unchanged. The mask is repeated over the entire fill area.
-
- If no fill mask is set (mask is all zeros──the default), only the current
- color is used in fill operations.
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- ellipse, floodfill, getfillmask, pie, rectangle
-
- ■ Example
-
- PROGRAM Fill
- INCLUDE 'FGRAPH.FD'
- INCLUDE 'FGRAPH.FI'
-
- INTEGER*1 style(8,6)/ #18, #18, #18, #18, #18, #18, #18, #18,
- + #08, #08, #08, #08, #08, #08, #08, #08,
- + #18, #00, #18, #18, #18, #00, #18, #18,
- + #00, #08, #00, #08, #08, #08, #08, #08,
- + #18, #18, #00, #18, #18, #00, #18, #18,
- + #08, #00, #08, #00, #08, #00, #08, #00 /
-
- INTEGER*1 oldstyle(8) ! Placeholder for old style
- INTEGER loop
-
- dummy2 = setvideomode( $MRES4COLOR )
- CALL getfillmask( oldstyle )
- C
- C Draw an ellipse under the middle few rectangles in a
- C different color.
- C
- dummy2 = setcolor( 2 )
- dummy2 = ellipse( $GFILLINTERIOR, 120, 75, 200, 125 )
- dummy2 = setcolor( 3 )
- DO loop = 1, 6
-
- C
- C Make 6 rectangles.
- C
- CALL setfillmask( style(1,loop) )
- dummy2 = rectangle( $GFILLINTERIOR, loop*40+5,90
- + (loop+1)*40, 110 )
- END DO
-
- CALL setfillmask( oldstyle ) ! Restore old style
- READ (*,*) ! Wait for ENTER to be pressed
- dummy2 = setvode( $DEFAULTMODE )
- END
-
- This program draws an ellipse overlaid with six rectangles, each with a
- different fill mask, as shown in Figure R.7.
-
- See also the example program for setlinestyle.
-
-
- setfont
-
- ■ Interface
-
- INTERFACE TO FUNCTION setfont(options)
- CHARACTER *(*) options
- + [FAR, REFERENCE] ! String describing font characteri
- INTEGER*2 setfont[FAR, C, ALIAS: "__f_setfont"]
- END
-
- ■ Description
-
- The setfont finds a single font, from the set of registered fonts, that has
- the characteristics specified by the options parameter.
-
- If a font is found, it is set to the current font. The current font is used
- in all subsequent calls to the outgtext function. There can be only one
- active font.
-
- The setfont function searches the list of registered fonts for a font
- matching the specified characteristics.
-
- The function's argument consists of letter codes that describe the desired
- font. The option code specified in the options parameter are not case or
- position sensitive.
-
- Option Description
-
- t'fontname' Name the desired typeface
-
- hy Select character height, where y
- is the number of pixels
-
- wx Select character width, where x
- is the number of pixels
-
- f Select only a fixed-space font
- (should not be used with the p
- characteristic)
-
- p Select only a proportional-space
- font (should not be used with the
- f characteristic)
-
- v Select only a vector-mapped font
- (should not be used with the r
- characteristic)
-
- r Select only a raster-mapped
- ("bit-mapped") font (should not
- be used with the v
- characteristic)
-
- b Select the font that best fits
- the other parameters specified
-
- nx Select font number x, where x is
- less than or equal to the value
- returned by the registerfonts
- function
-
- You can request as many options as desired, except with nx, which should be
- used alone. If mutually exclusive options are requested (such as the pair
- f/p or r/v), the setfont function ignores them. There is no error detection
- for incompatible parameters used with nx.
-
- The t typeface specification option is specified as a "t" followed by the
- name of the font in apostrophes. The fontname may be any of the following
- valid fonts:
-
- Font Name Description
-
- Courier Fixed-width bit-mapped font with
- serifs
-
- Helv Sans serif proportional
- bit-mapped font
-
- Tms Rmn Proportional bit-mapped font with
- serifs
-
- Script Proportional vector-mapped font
- of slanted characters formed from
- nearly continuous lines
-
- Modern Proportional vector-mapped font
- without serifs
-
- Roman Proportional vector-mapped font
- with serifs
-
- A "b" in the options field causes the setfont routine to automatically
- select the "best fit" font that matches the other characteristics you have
- specified.
-
- If the b option is specified and at least one font is registered, setfont
- will always be able to set a font and will return 0 to indicate success.
-
- In selecting a font, the setfont routine uses the following precedence,
- rated from highest precedence to lowest:
-
- 1. Pixel height
- 2. Typeface
- 3. Pixel width
- 4. Fixed or proportional font
-
- You can also specify a pixel width and height for fonts. If a nonexistent
- value is chosen for either, and the b option is specified, the setfont
- function will choose the closest match.
-
- A smaller font size has precedence over a larger size. If setfont requests
- Helv 12 with best fit, and only Helv 10 and Helv 14 are available, setfont
- will select Helv 10.
-
- If you specify the nx parameter, setfont will ignore any other specified
- options and supply only the font number corresponding to x.
-
- If a nonexistent value is chosen for pixel height and width, the setfont
- function will apply a magnification factor to a vector-mapped font to obtain
- a suitable font size. This automatic magnification does not apply if the r
- (raster-mapped font) option is specified, or if a specific typeface is
- requested and there is no best-fit (b) option specified.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- The font functions affect only the output from the font-output function
- outgtext; no other FORTRAN Graphics Library run-time output functions are
- affected by font usage.
- ───────────────────────────────────────────────────────────────────────────
-
- ■ Return value
-
- Returns 0 to indicate success and -1 to indicate an error.
-
- An error occurs if a request for a specific font fails and the b option was
- not specified, or if fonts have not yet been registered.
-
- ■ See also
-
- getfontinfo, getgtextextent, outgtext, registerfonts, unregisterfonts
-
- ■ Example
-
- See the example program for registerfonts.
-
-
- setlinestyle
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + setlinestyle[FAR, C, ALIAS:"__setlinestyle"](mask)
- INTEGER*2 mask ! Desired line-style mask
- END
-
- ■ Description
-
- The setlinestyle function selects the mask (line style) used for line
- drawing. The mask is a 16-bit number, where each bit represents a pixel in
- the line being drawn. If a bit is 1, the corresponding pixel is set to the
- color of the line (the current color). If a bit is 0, the corresponding
- pixel is left unchanged. The template is repeated for the entire length of
- the line. The default mask is #FFFF (a solid line). The setlinestyle
- function does not alter the styles for arcs, ellipses, or "pie-slice"
- wedges.
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- getlinestyle, lineto, rectangle
-
- ■ Example
-
- CC FILL.FOR - Illustrates color, filling, and linestyle functions
- CC including: floodfill setfillmask
- CC getlinestyle setlinestyle
- CC setcolor
- CC
- CC The getfillmask function is not shown, but its use is similar
- CC to getlinestyle.
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*1 fill(8)
- INTEGER*2 dummy, xinc, yinc, i,
- + irand, xwid, ywid, rseed
- INTEGER*4 ncolor
- REAL*4 rand
- RECORD /xycoord/ xy
- RECORD /videoconfig/ vc
-
- C
- C Find graphics mode.
- C
- IF( setvideomode( $MAXRESMODE ) .EQ. 0 )
- + STOP 'Error: cannot set graphics mode'
- CALL getvideoconfig( vc )
-
- C
- C Size variables to mode.
- C
- xinc = vc.numxpixels / 8.0
- yinc = vc.numypixels / 8.0
- xwid = ( xinc / 2.0 ) - 4.0
- ywid = ( yinc / 2.0 ) - 4.0
-
- C
- C Seed random-number generator.
- C
- CALL GETTIM( dummy, dummy, dummy, rseed)
- CALL SEED( rseed )
-
- C
- C Draw ellipses and lines with different patterns.
- C
- DO x = xinc, ( vc.numxpixels - xinc ), xinc
- DO y = yinc, ( vc.numypixels - yinc ), yinc
- C
- C Randomize fill and color. Array FILL holds
- C random numbers between 0 and 255.
- C
- DO i = 1, 8
- CALL RANDOM( rand )
- fill(i) = INT1( rand * 256.0 )
- END DO
-
- CALL setfillmask( fill )
- irand = rand * 256.0
- ncolor = MOD( irand, vc.numcolors ) + 1
- dummy = setcolor( ncolor )
-
- C
- C Draw ellipse and fill with random color.
- C
- dummy = ellipse( $GBORDER, x - xwid, y - ywid,
- + x + xwid, y + ywid )
- CALL RANDOM( rand )
- irand = rand * 256.0
- i = ncolor
- ncolor = MOD( irand, vc.numcolors ) + 1
- dummy = setcolor( ncolor )
- dummy = floodfill( x, y, i )
- C
- C Draw vertical and horizontal lines. Vertical line style
- C is anything other than horizontal style. Since lines
- C are overdrawn with several line styles, this has the
- C effect of combining colors and styles.
- C
- CALL RANDOM( rand )
- irand = rand * 256.0
- CALL setlinestyle( irand )
- CALL moveto( 0, y + ywid + 4, xy )
- dummy = lineto( vc.numxpixels - 1, y + ywid + 4 )
- C
- C Get linestyle, invert bits, and reset linestyle.
- C
- CALL setlinestyle( 255 - getlinestyle() )
- CALL moveto( x + xwid + 4, 0, xy )
- dummy = lineto( x + xwid + 4, vc.numypixels - 1 )
- END DO
- END DO
-
- READ (*,*) ! Wait for ENTER to be pressed
- dummy = setvideomode( $DEFAULTMODE )
- END
-
- This program draws filled ovals and lines on the screen. It uses a variety
- of fill patterns and line styles in different colors.
-
-
- setpixel, setpixel_w
-
- ■ Interface
-
- INTERFACE TO FUNCTION setpixel(x, y)
- INTEGER*2 setpixel[FAR, C, ALIAS:"__setpixel"]
- INTEGER*2 x, y ! Target pixel
- END
-
- INTERFACE TO FUNCTION setpixel_w(wx, wy)
- INTEGER*2 setpixel[FAR, C, ALIAS:"__f_setpixel_w"]
- DOUBLE PRECISION wx, wy ! Target pixel
- END
-
- ■ Description
-
- The setpixel and the setpixel_w functions set a pixel at a specified
- location to the current color.
-
- The function setpixel sets the pixel at the viewport-coordinate point (x, y)
- to the current color.
-
- The function setpixel_w sets the pixel at the window-coordinate point (wx,
- wy) to the current color.
-
- ■ Return value
-
- The setpixel and setpixel_w functions return the previous value of the
- target pixel. If the function fails (for example, the point lies outside of
- the clipping region), it returns -1.
-
- ■ See also
-
- getpixel, setcolor
-
- ■ Example
-
- CC FIGURE.FOR - Illustrates graphics drawing functions including:
- CC arc ineto pie setpixel
- CC ellipse moveto rectangle
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy, x, y
- INTEGER*4 ncolor
- RECORD /xycoord/ xy
-
- C
- C Find graphics mode.
- C
- IF ( setvideomode( $MAXRESMODE ) .EQ. 0 )
- + STOP 'Error: cannot set graphics mode'
-
- WRITE (*,*) ' Press ENTER to continue'
- C
- C Draw pixels.
- C
- ncolor = 2
- dummy = setcolor( ncolor )
- x = 10
- DO y = 50, 89, 3
- dummy = setpixel( x, y )
- x = x + 2
- END DO
- READ (*,*) ! Wait for ENTER to be pressed
- C
- C Draw lines.
- C
- ncolor = ncolor + 1
- dummy = setcolor( ncolor )
- x = 60
- DO y = 50, 89, 3
- CALL moveto( x, y, xy )
- dummy = lineto( x + 20, y )
- END DO
- READ (*,*) ! Wait for ENTER to be pressed
- C
- C Draw rectangles.
- C
- ncolor = ncolor + 1
- dummy = setcolor( ncolor )
- x = 110
- y = 70
- dummy = rectangle( $GBORDER, x - 20, y - 20, x, y )
- dummy = rectangle( $GFILLINTERIOR, x + 20, y + 20, x, y )
- READ (*,*) ! Wait for ENTER to be pressed
- C
- C Draw ellipses.
- C
- ncolor = ncolor + 1
- dummy = setcolor( ncolor )
- x = 160
- dummy = ellipse( $GBORDER, x - 20, y - 20, x, y )
- dummy = ellipse( $GFILLINTERIOR, x + 20, y + 20, x, y )
- READ (*,*) ! Wait for ENTER to be pressed
-
- C
- C Draw arcs.
- C
- ncolor = ncolor + 1
- dummy = setcolor( ncolor )
- x = 210
- dummy = arc( x - 20, y - 20, x, y, x, y - 10, x - 10, y )
- dummy = arc( x + 20, y + 20, x, y, x + 10, y + 20, x + 20,
- + y + 10 )
- READ (*,*) ! Wait for ENTER to be pressed
- C
- C Draw pies.
- C
- ncolor = ncolor + 1
- dummy = setcolor( ncolor )
- x = 260
- dummy = pie( $GBORDER, x - 20, y - 20, x, y, x,
- + y - 10, x - 10, y )
- dummy = pie( $GFILLINTERIOR, x + 20, y + 20, x, y, x + 10,
- + y + 20, x + 20, y + 10 )
- READ (*,*) ! Wait for ENTER to be pressed
- dummy = setvideomode( $DEFAULTMODE )
- END
-
- The program FIGURE.FOR draws a series of small shapes in a variety of
- colors.
-
-
- settextcolor
-
- ■ Interface
-
- INTERFACE TO FUNCTION settextcolor(index)
- INTEGER*2 settextcolor[FAR, C, ALIAS:"__settextcolor"]
- INTEGER*2 index ! Desired color index
- END
-
- ■ Description
-
- The settextcolor function sets the current text color. The value of index
- specifies the new color index; the default value is the same as the maximum
- color index. The settextcolor routine sets the color for the outtext
- function. It does not affect the color of the WRITE statement or the color
- of text output with the outgtext font routine. Use the setcolor function to
- change the color of font output.
-
- In text color mode, you can specify a color index in the range 0-31. The
- colors in the range 0-15 are interpreted to be normal; colors in the range
- 16-31 are the same as those in the range 0-15, except that the text blinks.
- The normal color range is defined below.
-
- Index Color Index Color
-
- 0 Black 8 Dark gray
- 1 Blue 9 Light blue
- 2 Green 10 Light green
- 3 Cyan 11 Light cyan
- 4 Red 12 Light red
- 5 Magenta 13 Light magenta
- 6 Brown 14 Yellow
- 7 White 15 Bright white
-
- In every text mode, including monochrome, the getvideoconfig function
- returns the value 32 for the number of available colors. The value 32
- indicates the range of values (0-31) accepted by the settextcolor function.
- This includes 16 normal colors (0-15) and 16 blinking colors (16-31). To
- select blinking text, add 16 to the normal color value. Some color values
- appear the same on monochrome monitors. However, because blinking is
- selected in the same manner, the text mode for monochrome monitors uses the
- same range (0-31) as the color text mode.
-
- This function is also available under OS/2.
-
- ■ Return value
-
- Returns the color index of the previous text color.
-
- ■ See also
-
- gettextcolor, outtext
-
- ■ Example
-
- See the example program for gettextcolor.
-
-
- settextcursor
-
- ■ Interface
-
- INTERFACE TO FUNCTION settextcursor(attr)
- INTEGER*2 settextcursor[FAR, C, ALIAS:"__settextcursor"]
- INTEGER*2 attr ! Cursor attribute
- END
-
- ■ Description
-
- The settextcursor function sets the cursor shape based on the attribute
- specified by attr. The high-order byte of attr determines the start line of
- the cursor. The low-order byte of attr determines the stop line of the
- cursor. The settextcursor function uses the same format as the BIOS routines
- in setting the cursor. Values for the cursor attribute are shown below.
-
- Attribute Cursor Shape
-
- #0707 Underline
-
- #0007 Full block cursor
-
- #0607 Double underline
-
- #2000 No cursor
-
- This function is also available under OS/2. Note that this function works
- only in text video modes.
-
- ■ Return value
-
- Returns the previous cursor attribute or -1 if an error occurs, such as
- calling the function in a graphics screen mode.
-
- ■ See also
-
- displaycursor, gettextcursor
-
- ■ Example
-
- CC CURSOR.FOR - Illustrates cursor functions including:
- CC displaycursor gettextcursor settextcursor
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy, oldcursor, newcursor,
- + curs_start, curs_end, block
- CHARACTER*40 str
- RECORD /rccoord/ curpos
- RECORD /videoconfig/ vc
-
- C
- C Save old cursor shape and make sure cursor is on.
- C
-
- CALL clearscreen( $GCLEARSCREEN )
- oldcursor = gettextcursor()
- dummy = displaycursor( $GCURSORON )
- CALL settextposition( 1, 1, curpos )
- CALL outtext( 'Press ENTER to continue . . .' )
- C
- C Change cursor shape.
- C Color cursor uses scan lines 0-7, monochrome uses 0-13.
- C
- CALL getvideoconfig( vc )
- block = 7
- IF( vc.mode .EQ. $TEXTMONO ) block = 13
- curs_start = 0
- DO curs_end = block, 0, -1
- CALL settextposition( 10, 1, curpos )
- WRITE (str, 9000) curs_start, curs_end
- CALL outtext( str )
- newcursor = (curs_start * 256) + curs_end
- dummy = settextcursor( newcursor )
- READ (*,*) ! Wait for ENTER to be pressed
- curs_start = curs_start + 1
- END DO
-
- WRITE (str, '(A13)') 'Cursor off: '
- CALL settextposition( 12, 1, curpos )
- CALL outtext( str, 13 )
- dummy = displaycursor( $GCURSOROFF )
- READ (*,*) ! Wait for ENTER to be pressed
- WRITE (str, '(A13)') 'Cursor on : '
- CALL settextposition( 13, 1, curpos )
- CALL outtext( str )
- dummy = settextcursor( block )
- dummy = displaycursor( $GCURSORON )
- READ (*,*) ! Wait for ENTER to be pressed
- C
- C Restore original cursor shape.
- C
- dummy = settextcursor( oldcursor )
- CALL clearscreen( $GCLEARSCREEN )
-
- 9000 FORMAT ( 'Start line:', I4, 8x, 'Endline:', I4, 3x )
-
- END
-
- The program CURSOR.FOR shows the effect of changing the start and stop lines
- for the cursor, and the effect of turning the cursor off and on.
-
-
- settextposition
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + settextposition[FAR, C, ALIAS:"__f_settextposition"](row, column, s)
- INTEGER*2 row, column ! New output start position
- STRUCTURE/rccoord/
- INTEGER*2 row ! Row coordinate
- INTEGER*2 col ! Column coordinate
- END STRUCTURE
- RECORD/rccoord/s ! Returns the previous text position
- END
-
- ■ Description
-
- This function relocates the current text position to the display point (row,
- column). Subsequent text produced with the outtext function (as well as
- standard console I/O routines, such as PRINT) begins at that point.
-
- The previous text position is returned in the rccoord structure variable s,
- defined in FGRAPH.FD.
-
- This subroutine is also available under OS/2.
-
- ───────────────────────────────────────────────────────────────────────────
- WARNING
- The WRITE statement sent its carriage-return (CR) and line-feed (LF)
- characters to the screen at the beginning of the first I/O statement
- following the WRITE statement. This can cause unpredictable text
- positioning if you mix the graphics routines settextposition and outtext
- with the WRITE statement. You can minimize the effect by using the
- backslash (\) format descriptor (suppress the CR-LF characters) in the
- associated FORMAT statement.
- ───────────────────────────────────────────────────────────────────────────
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- gettextposition, outtext, settextwindow
-
- ■ Example
-
- See the example program for setviewport.
-
-
- settextrows
-
- ■ Interface
-
- INTERFACE TO FUNCTION settextrows(rows)
- INTEGER*2 settextrows[FAR, C, ALIAS:"__settextrows"]
- INTEGER*2 rows ! Number of text rows
- END
-
- ■ Description
-
- The settextrows function specifies the number of text rows used in text
- modes, requiring hardware that supports 43- or 50-line modes, such as VGA or
- EGA. In the rows argument, $MAXTEXTROWS chooses the number of rows
- available: in text mode, 50 rows (VGA); 43 (EGA); and 25 on all others. In
- graphics modes supporting 30 or 60 rows, it chooses 60. This function is
- also available under OS/2.
-
- ■ Return value
-
- Returns the numbers of rows set, or returns 0 if an error occurred.
-
- ■ See also
-
- getvideoconfig, setvideomode, setvideomoderows
-
- ■ Example
-
- CC SETROWS.FOR - Illustrates: settextrows
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 rows
- CHARACTER*2 arg
- C
- C Get command line argument: 25, 43, or 50.
- C
- CALL GETARG( 1, arg, 2 )
- rows = 0
- IF( arg .EQ. '25' ) rows = 25
- IF( arg .EQ. '43' ) rows = 43
- IF( arg .EQ. '50' ) rows = 50
- C
- C Make sure new rows are valid and the same as requested rows.
- C
- IF( (rows .EQ. 0) .OR. (settextrows( rows ) .NE. rows) ) THEN
- WRITE (*,*) 'Syntax: SETROWS [ 25 | 43 | 50 ]'
- STOP 01
- END IF
- C
- C Return 0 if successful
- C
- STOP 00
- END
-
- This program accepts a command-line argument, checking for a valid number of
- rows for the current display.
-
-
- settextwindow
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + settextwindow[FAR, C, ALIAS:"__settextwindow"](r1, c1, r2, c2)
- INTEGER*2 r1, c1 ! Upper left corner of window
- INTEGER*2 r2, c2 ! Lower right corner of window
- END
-
- ■ Description
-
- The settextwindow function specifies a window in row and column coordinates
- where all the text output to the screen is displayed. The arguments (r1, c1)
- specify the upper left corner of the text window, and the arguments (r2, c2)
- specify the lower right corner of the text window.
-
- Text is output from the top of the text window down. When the text window is
- full, the lines begin to scroll off the top of the window.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- This function does not affect the output of the font display routine
- outgtext. Use the setviewport function to control the display area for
- fonts.
- ───────────────────────────────────────────────────────────────────────────
-
- This subroutine is also available under OS/2.
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- gettextposition, outtext, settextposition
-
- ■ Example
-
- See the example program for setvideomoderows.
-
-
- setvideomode
-
-
- ■ Interface
-
- INTERFACE TO FUNCTION setvideomode(mode)
- INTEGER*2 setvideomode[FAR, C, ALIAS:"__setvideomode"]
- INTEGER*2 mode ! Desired mode
- END
-
- ■ Description
-
- The setvideomode function selects a screen mode appropriate for a particular
- hardware/ display configuration. The mode argument can be one of the
- symbolic constants shown in Table R.5 below and defined in FGRAPH.FD.
-
- $MAXCOLORMODE and $MAXRESMODE in the mode argument choose the graphics mode
- with the most colors or the highest resolution, respectively. They fail for
- adapters that have no graphics modes. Table R.6 below shows the specific
- modes selected by the constants $MAXCOLORMODE and $MAXRESMODE for different
- adapter/monitor combinations.
-
- In $HERCMONO mode, only monochrome (two-color) text and graphics are
- supported. The screen resolution is 720 by 348 pixels. The text dimensions
- are 80 columns by 25 rows, with a 9-by-14-character box. The bottom two scan
- lines of row 25 are not visible.
-
- You must install the Hercules driver MSHERC.COM before running your program.
- Type MSHERC to load the driver. This can be done from an AUTOEXEC.BAT file.
-
- If you use both a Hercules monochrome and a color video card, install
- MSHERC.COM with the /H (/HALF) option. The /H option causes the driver to
- use one instead of two graphics pages. This prevents the two video cards
- from attempting to use the same memory. You do not have to use the /H option
- if you have only a Hercules card. See your Hercules hardware manual for more
- details on compatibility.
-
- This function is also available under OS/2.
-
- ■ Return value
-
- Returns the number of text rows if the function is successful. If an error
- occurs (that is, if the mode selected is not supported by the current
- hardware configuration), the function returns 0.
-
- ■ See also
-
- getvideoconfig
-
- ■ Example
-
- See the example program for setvideomoderows.
-
- Table R.5 Symbolic Constants for Screen Mode
-
- Mode Type Size Colors Adapter
- $DEFAULTMODE Hardware Hardware Hardware Hardware
- default default default default
- $TEXTBW40 M/T 40 x 25 16 CGA
- $TEXTC40 C/T 40 x 25 16 CGA
- $TEXTBW80 M/T 80 x 25 16 CGA
- $TEXTC80 C/T 80 x 25 6 CGA
- $MRES4COLOR C/G 320 x 200 4 CGA
- $MRESNOCOLOR M/G 320 x 200 4 CGA
- $HRESBW M/G 640 x 200 2 CGA
- $TEXTMONO M/T 80 x 25 1 MDPA
- $HERCMONO Hercules graphics --- --- HGC
- $MRES16COLOR C/G 320 x 200 16 EGA
- $HRES16COLOR C/G 640 x 200 16 EGA
- $ERESNOCOLOR M/T 640 x 350 1 EGA
- $ERESCOLOR C/G 640 x 350 64 EGA
- $VRES2COLOR C/G 640 480 2 VGA
- $VRES16COLOR C/G 640 480 16 VGA
- $MRES256COLOR C/G 320 200 256 VGA
- $ORESCOLOR C/G 640 400 1 of 16 Olivetti co
- graphics
- $MAXCOLORMODE C/G See Table R.6 Maximum CGA
- $MAXRESMODE C/G Maximum See Table R.6 CGA
-
-
- Table R.6 Modes Selected by $MAXCOLORMODE and $MAXRESMODE
-
- Adapter/Monitor $MAXCOLORMODE $MAXRESMODE
-
- MDPA Fail Fail
- HGC $HERCMONO $HERCMONO
- CGA Color $MRES4COLOR $HRESBW
- CGA Noncolor $MRESNOCOLOR $HRESBW
- OCGA $MRES4COLOR $ORESCOLOR
- OEGA Color $ERESCOLOR $ORESCOLOR
- EGA Color 256K $HRES16COLOR $HRES16COLOR
- EGA Color 64K $HRES16COLOR $HRES16COLOR
- EGA > 256K $ERESCOLOR $ERESCOLOR
- EGA > 64K $HRES16COLOR $ERESCOLOR
- EGA Mono $ERESNOCOLOR $ERESNOCOLOR
- MCGA $MRES256COLOR $VRES2COLOR
- VGA/OVGA $MRES256COLOR $VRES16COLOR
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- Only standard hardware is described here, but display hardware that is
- strictly compatible with IBM, Hercules, or Olivetti hardware should also
- work as described.
- ───────────────────────────────────────────────────────────────────────────
-
-
- setvideomoderows
-
- ■ Interface
-
- INTERFACE TO FUNCTION setvideomoderows(mode, rows)
- INTEGER*2 setvideomoderows[FAR, C, ALIAS:"__setvideomoderows"]
- INTEGER*2 mode ! Desired mode
- INTEGER*2 rows ! Number of text rows
- END
-
- ■ Description
-
- The setvideomoderows function selects a screen mode for a particular
- hardware/display combination. The options for the symbolic constant mode
- (the screen mode) are given in the reference pages for setvideomode.
-
- The setvideomoderows argument rows specifies the number of text rows to be
- used in a text mode. Optionally, placing the constant $MAXTEXTROWS in the
- rows argument chooses the maximum number of rows available. In text mode
- this is 50 rows for a VGA, 43 for an EGA, and 25 on all others. In graphics
- modes that support 30 or 60 rows, $MAXTEXTROWS chooses 60 rows.
-
- ■ Return value
-
- Returns the numbers of rows set. The function returns 0 if an error occurred
- (for example, if the mode is not supported).
-
- ■ See also
-
- getvideoconfig, settextrows, setvideomode
-
- ■ Example
-
- CC MODES.FOR - Illustrates configuration and text window
- CC functions including:
- CC getvideoconfig outtext settextwindow
- CC setvideomoderows setvideomode
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- PARAMETER ( NUM_ROWS = 5 )
- PARAMETER ( NUM_MODE = 17 )
-
- INTEGER*2 dummy, irow, x, y
- INTEGER*2 modes( NUM_MODE ), rows( NUM_ROWS )
- CHARACTER*12 names( NUM_MODE ), str
- RECORD / videoconfig / vc
-
- DATA modes / $TEXTBW40 , $TEXTC40 , $TEXTBW80 ,
- + $TEXTC80 , $MRES4COLOR , $MRESNOCOLOR ,
- + $HRESBW , $TEXTMONO , $HERCMONO ,
- + $MRES16COLOR , $HRES16COLOR , $ERESNOCOLOR ,
- + $ERESCOLOR , $VRES2COLOR , $VRES16COLOR ,
- + $MRES256COLOR , $ORESCOLOR /
-
-
- DATA names / ' $TEXTBW40', ' $TEXTC40', ' $TEXTBW80',
- + ' $TEXTC80', ' $MRES4COLOR', '$MRESNOCOLOR',
- + ' $HRESBW', ' $TEXTMONO', ' $HERCMONO',
- + ' $MRES16COLOR', '$HRES16COLOR', '$ERESNOCOLOR',
- + ' $ERESCOLOR', ' $VRES2COLOR', '$VRES16COLOR',
- + '$MRES256COLOR', ' $ORESCOLOR' /
-
- DATA rows / 60, 50, 43, 30, 25 /
-
- dummy = displaycursor( $GCURSOROFF )
- C
- C Try each mode.
- C
- DO i = 1, NUM_MODE
- DO j = 1, NUM_ROWS
- C
- C Try each possible number of rows.
- C
- irow = setvideomoderows( modes(i), rows(j) )
- IF( ( irow .EQ. 0 ) .OR. (rows(j) .NE. irow) ) THEN
- GOTO 100
- ELSE
- CALL getvideoconfig( vc )
- y = ( vc.numtextrows - 12 ) / 2
- x = ( vc.numtextcols - 25 ) / 2
- END IF
- C
- C Use text window to place output in middle of screen.
- C
- CALL settextwindow( y, x, vc.numtextrows - y,
- + vc.numtextcols - x - 2 )
- C
- C Display all information on the screen.
- C
- CALL outtext( 'Video mode: ' // names(i) )
- WRITE (str, '(I12)') vc.numxpixels
- CALL outtext( 'X pixels: ' // str )
- WRITE (str, '(I12)') vc.numypixels
- CALL outtext( 'Y pixels: ' // str )
- WRITE (str, '(I12)') vc.numtextcols
- CALL outtext( 'Text columns:' // str )
- WRITE (str, '(I12)') vc.numtextrows
- CALL outtext( 'Text rows: ' // str )
- WRITE (str, '(I12)') vc.numcolors
- CALL outtext( 'Colors: ' // str )
- WRITE (str, '(I12)') vc.bitsperpixel
- CALL outtext( 'Bits/pixel: ' // str )
-
- WRITE (str, '(I12)') vc.numvideopages
- CALL outtext( 'Video pages: ' // str )
- WRITE (str, '(I12)') vc.mode
- CALL outtext( 'Mode: ' // str )
- WRITE (str, '(I12)') vc.adapter
- CALL outtext( 'Adapter: ' // str )
- WRITE (str, '(I12)') vc.monitor
- CALL outtext( 'Monitor: ' // str )
- WRITE (str, '(I12)') vc.memory
- CALL outtext( 'Memory: ' // str )
-
- READ (*,*) ! Wait for ENTER to be pressed
- 100 END DO
- END DO
-
- dummy = displaycursor( $GCURSORON )
- dummy = setvideomode( $DEFAULTMODE )
- END
-
- The program MODES.FOR demonstrates each of the possible mode and row
- combinations.
-
-
- setvieworg
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + setvieworg[FAR, C, ALIAS:"__f_setvieworg"](x, y, s)
- INTEGER*2 x, y ! New origin point
- STRUCTURE/xycoord/
- INTEGER*2 xcoord ! x-coordinate
- INTEGER*2 ycoord ! y-coordinate
- END STRUCTURE
- RECORD/xycoord/s[FAR, REFERENCE] ! Returns the previous v
- END
-
- ■ Description
-
- The setvieworg function moves the view-coordinate origin (0, 0) to the
- physical point (x, y). All other view-coordinate points move the same
- direction and distance.
-
- The xycoord structure variable s, defined in FGRAPH.FD, returns the physical
- coordinates of the previous view origin.
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- getphyscoord, getviewcoord, getwindowcoord, setcliprgn, setviewport
-
- ■ Example
-
- CC WINDOW.FOR - Illustrates windows and coordinate systems using
- CC the following functions:
- CC clearscreen ellipse ellipse_w
- CC rectangle rectangle_w setcliprgn
- CC setvieworg setviewport setwindow
- CC
- CC Although not all illustrated here, functions ending in _w
- CC are similar to rectangle_w and ellipse_w.
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy, xhalf, yhalf, xquar, yquar
- DOUBLE PRECISION x_upleft, y_upleft, x_botrght, y_botrght
- RECORD / xycoord / xy
- RECORD / videoconfig / vc
-
- C
- C Find graphics mode.
- C
- IF( setvideomode( $MAXRESMODE ) .EQ. 0 )
- + STOP 'Error: cannot set graphics mode'
- CALL getvideoconfig( vc )
-
- xhalf = vc.numxpixels / 2
- yhalf = vc.numypixels / 2
- xquar = xhalf / 2
- yquar = yhalf / 2
-
- C
- C First window - integer physical coordinates
- C
- CALL setviewport( 0, 0, xhalf - 1, yhalf - 1 )
- dummy = setcolor( 2 )
- dummy = rectangle( $GBORDER, 0, 0, xhalf - 1, yhalf - 1 )
- dummy = setcolor( 1 )
- dummy = ellipse( $GFILLINTERIOR, xquar / 4, yquar / 4,
- + xhalf - (xquar / 4), yhalf - (yquar / 4) )
- READ (*,*) ! Wait for ENTER to be pressed
- CALL clearscreen( $GVIEWPORT )
- dummy = rectangle( $GBORDER, 0, 0, xhalf - 1, yhalf - 1 )
-
- C
- C Second window - integer world coordinates with clip region
- C
- CALL setcliprgn( xhalf, 0, vc.numxpixels, yhalf )
- CALL setvieworg( xhalf + xquar - 1, yquar - 1, xy )
- dummy = setcolor( 3 )
- dummy = rectangle( $GBORDER, -xquar + 1, -yquar + 1, xquar,
- + yquar )
- dummy = setcolor( 2 )
- dummy = ellipse( $GFILLINTERIOR, (-xquar * 3) / 4,
- + (-yquar * 3) / 4, (xquar * 3) / 4,
- + (yquar * 3) / 4 )
- READ (*,*) ! Wait for ENTER to be pressed
- CALL clearscreen( $GVIEWPORT )
- dummy = rectangle( $GBORDER, -xquar + 1, -yquar + 1, xquar,
- + yquar )
-
- C
- C Third window
- C
- CALL setviewport( xhalf, yhalf, vc.numxpixels - 1,
- + vc.numypixels - 1 )
- dummy = setwindow( .FALSE., -4.0, -5.0, 4.0, 5.0 )
- dummy = setcolor( 4 )
- dummy = rectangle_w( $GBORDER, -4.0, -5.0, 4.0, 5.0 )
- dummy = setcolor( 3 )
- dummy = ellipse_w( $GFILLINTERIOR, -3.0, -3.5, 3.0, 3.5 )
- READ (*,*) ! Wait for ENTER to be pressed
- CALL clearscreen( $GVIEWPORT )
- dummy = rectangle_w( $GBORDER, -4.0, -5.0, 4.0, 5.0 )
-
- C
- C Fourth window
- C
- CALL setviewport( 0, yhalf, xhalf - 1, vc.numypixels - 1 )
- dummy = setwindow( .FALSE., -4.0, -5.0, 4.0, 5.0 )
- x_upleft = -4.0
- y_upleft = -5.0
- x_botrght = 4.0
- y_botrght = 5.0
- dummy = setcolor( 5 )
- dummy = rectangle_w( $GBORDER, x_upleft, y_upleft,
- + x_botrght, y_botrght )
- x_upleft = -3.0
- y_upleft = -3.5
- x_botrght = 3.0
- y_botrght = 3.5
- dummy = setcolor( 4 )
- dummy = ellipse_w( $GFILLINTERIOR, x_upleft, y_upleft,
- + x_botrght, y_botrght )
-
- READ (*,*) ! Wait for ENTER to be pressed
- dummy = setvideomode( $DEFAULTMODE )
- END
-
- The program WINDOW.FOR draws several windows, using different methods and
- options for each window.
-
-
- setviewport
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + setviewport[FAR, C, ALIAS:"__setviewport"](x1, y1, x2, y2)
- INTEGER*2 x1, y1 ! Upper left corner of viewport
- INTEGER*2 x2, y2 ! Lower right corner of viewport
- END
-
- ■ Description
-
- The setviewport function redefines the graphics viewport. The setviewport
- function defines a clipping region in the same manner as setcliprgn, and
- then sets the viewport-coordinate origin to the upper left corner of the
- region. The physical points (x1, y1) and (x2, y2) are the upper left and
- lower right corners of the rectangular clipping region. Any window
- transformation done with the setwindow function applies only to the viewport
- and not to the entire screen.
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- setcliprgn, setvieworg, setwindow
-
- ■ Example
-
- CC MAGNIFY.FOR - Illustrates translation between window and view
- CC coordinate systems using the following functions:
- CC getphyscoord getviewcoord getviewcoord_w
- CC getwindowcoord lineto moveto
- CC rectangle rectangle_w settextposition
- CC setwindow setviewport
- CC
- CC Although not all illustrated here, functions ending in _w
- CC are similar to rectangle_w.
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy, rseed, j, k, m, n
- INTEGER*2 coord(3,2,2), fill(2)
- INTEGER*4 i
- REAL*4 rand
- DOUBLE PRECISION x(2), y(2)
- CHARACTER*18 text
- RECORD / xycoord / xy, xy1
- RECORD / wxycoord / wxy
- RECORD / rccoord / curpos
- RECORD / videoconfig / vc
-
- DATA text / 'magnification: 1x' /
- DATA fill / $GFILLINTERIOR, $GBORDER /
-
- C
- C Find graphics mode.
- C
- IF( setvideomode( $MAXRESMODE ) .EQ. 0 )
- + STOP 'Error: cannot set graphics mode'
- CALL getvideoconfig( vc )
-
- C
- C Find physical (pixel) coordinates for windows 1, 2, and 3.
- C
- coord(1,1,1) = vc.numxpixels * 3 / 16
- coord(1,1,2) = vc.numypixels * 7 / 32
- coord(1,2,1) = coord(1,1,1) + vc.numxpixels / 8
- coord(1,2,2) = coord(1,1,2) + vc.numypixels / 16
- coord(2,1,1) = vc.numxpixels * 9 / 16
- coord(2,1,2) = vc.numypixels * 5 / 32
- coord(2,2,1) = coord(2,1,1) + vc.numxpixels * 3 / 8
- coord(2,2,2) = coord(2,1,2) + vc.numypixels * 3 / 16
- coord(3,1,1) = 0
- coord(3,1,2) = vc.numypixels / 2
- coord(3,2,1) = vc.numxpixels - 1
- coord(3,2,2) = vc.numypixels - 1
-
- C
- C Connect windows with lines.
- C
- dummy = setcolor( 4 )
- DO i = 1, 2
- DO j = 1, 2
- DO k = 1, 2
- CALL moveto( coord(i,j,1), coord(i,k,2), xy )
- dummy = lineto( coord(i + 1,j,1), coord(i + 1,k,2) )
- END DO
- END DO
- END DO
-
- C
- C Label windows and frame with rectangles.
- C
- DO i = 1, 3
- dummy = setcolor( i )
- row = ( coord(i,1,2) * 25 ) / vc.numypixels
- column = ( coord(i,1,1) * 80 ) / vc.numxpixels
- CALL settextposition( row, column, curpos )
- CALL outtext( text )
- text(17:17) = '3'
-
-
- IF( i .EQ. 2 ) text(17:17) = '8'
- CALL setviewport( coord(i,1,1), coord(i,1,2) ,
- + coord(i,2,1), coord(i,2,2) )
- CALL getviewcoord( coord(i,1,1), coord(i,1,2), xy )
- CALL getviewcoord( coord(i,2,1), coord(i,2,2), xy1 )
- dummy = rectangle( $GBORDER, xy.xcoord, xy.ycoord,
- + xy1.xcoord, xy1.ycoord )
- END DO
-
- C
- C Seed random number generator.
- C
- CALL GETTIM( dummy, dummy, dummy, rseed )
- CALL SEED( rseed )
- C
- C Get random window coordinates (x, y) for rectangles,
- C where x and y are between 0 and 1000.
- C
- DO i = 8, 15
- dummy = setcolor( i )
- CALL RANDOM( rand )
- x(1) = rand * 980.0
- x(2) = rand * ( 999.0 - x(1) ) + x(1)
- CALL RANDOM( rand )
- y(1) = rand * 980.0
- y(2) = rand * ( 999.0 - y(1) ) + y(1)
- k = rand + 1.5
-
- C
- C Display rectangles in normal and magnified views.
- C
- DO j = 1, 3
- CALL setviewport( coord(j,1,1), coord(j,1,2) ,
- + coord(j,2,1), coord(j,2,2) )
- dummy = setwindow( .TRUE., 0.0, 0.0, 1000.0, 1000.0 )
- dummy = rectangle_w( fill(k), x(1), y(1), x(2), y(2) )
-
- C
- C In last window, make rectangle sides 2 pixels wide by
- C encasing unfilled rectangles with another rectangle.
- C Convert window coords (x, y) to physical coords,
- C adjust, and translate back into window coords.
- C
- IF( (j .EQ. 3) .AND. (k .EQ. 2) ) THEN
- m = -1
- DO n = 1, 2
- CALL getviewcoord_w( x(n), y(n), xy )
- CALL getphyscoord( xy.xcoord, xy.ycoord, xy )
- CALL getviewcoord( xy.xcoord+m, xy.ycoord+m, xy )
- CALL getwindowcoord( xy.xcoord, xy.ycoord, wxy )
- x(n) = wxy.wx
- y(n) = wxy.wy
- m = 1
- END DO
- dummy = rectangle_w( fill(k), x(1), y(1), x(2), y(2) )
- END IF
- END DO
- END DO
-
- READ (*,*) ! Wait for ENTER to be pressed
- dummy = setvideomode( $DEFAULTMODE )
- END
-
- By translating a drawing between window and viewport coordinates, the
- program MAGNIFY.FOR enlarges the window's contents.
-
- See also the example program for setvieworg.
-
-
- setvisualpage
-
- ■ Interface
-
- INTERFACE TO FUNCTION setvisualpage(page)
- INTEGER*2 setvisualpage[FAR, C, ALIAS:"__setvisualpage"]
- INTEGER*2 page ! Visual page number
- END
-
- ■ Description
-
- The setvisualpage function selects the current visual page on hardware that
- has an EGA or VGA adapter and enough memory to support multiple-screen
- pages. The page argument specifies the current visual page. The default page
- number is 0.
-
- This function is also available under OS/2.
-
- ■ Return value
-
- Returns the page number of the previous visual page. If the function fails,
- it returns a negative value.
-
- ■ See also
-
- getactivepage, getvisualpage, setactivepage, setvideomode
-
- ■ Example
-
- See the example program for getactivepage.
-
-
- setwindow
-
- ■ Interface
-
- INTERFACE TO FUNCTION setwindow(finvert, wx1, wy1, wx2, wy2)
- INTEGER*2 setwindow[FAR, C, ALIAS:"__setwindow"]
- LOGICAL*2 finvert
- DOUBLE PRECISION wx1, wy1 ! Upper left corner of window
- DOUBLE PRECISION wx2, wy2 ! Lower right corner of window
- END
-
- ■ Description
-
- The setwindow function defines a window bound by the specified coordinates.
- The arguments (wx1, wy1) specify the upper left corner of the window, and
- the arguments (wx2, wy2) specify the lower right corner of the window.
-
- The finvert argument specifies the direction of the coordinates. If finvert
- is .TRUE., the y-axis increases from the screen bottom to the screen top
- (Cartesian coordinates). If finvert is .FALSE., the y-axis increases from
- the screen top to the screen bottom (screen coordinates).
-
- Any window transformation done with the setwindow function applies only to
- the viewport and not to the entire screen.
-
- If wx1 equals wx2 or wy1 equals wy2, the function will fail.
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- This function does not affect the output of the font display routine
- outgtext.
- ───────────────────────────────────────────────────────────────────────────
-
- ■ Return value
-
- Returns a nonzero value if successful. If the function fails (for example,
- if it is not in a graphics mode), it returns 0.
-
- ■ See also
-
- setviewport
-
- ■ Example
-
- See the example program for setviweorg and setviewport.
-
-
- unregisterfonts
-
- ■ Interface
-
- INTERFACE TO SUBROUTINE
- + unregisterfonts[FAR, C, ALIAS:"__unregisterfonts"]( )
- END
-
- ■ Description
-
- The unregisterfonts subroutine frees memory previously allocated and used by
- the registerfonts function. The unregisterfonts subroutine removes the
- header information for all fonts and unloads the currently selected font
- data from memory.
-
- Any attempt to use the setfont or outgtext function after calling
- unregisterfonts causes an error.
-
- ■ Return value
-
- There is no return value.
-
- ■ See also
-
- getfontinfo, getgtextextent, setfont, outgtext, registerfonts
-
- ■ Example
-
- See the example program for registerfonts.
-
-
- wrapon
-
- ■ Interface
-
- INTERFACE TO FUNCTION wrapon(option)
- INTEGER*2 wrapon[FAR, C, ALIAS:"__wrapon"]
- INTEGER*2 option ! Wrap condition
- END
-
- ■ Description
-
- The wrapon function controls whether text output with the outtext function
- wraps to a new line or is simply clipped when the text output reaches the
- edge of the defined text window. The option argument can be one of the
- following symbolic constants:
-
- Constant Meaning
-
- $GWRAPOFF Truncates lines at window border
-
- $GWRAPON Wraps lines at window border
-
- ───────────────────────────────────────────────────────────────────────────
- NOTE
- This function does not affect the output of font routines.
- ───────────────────────────────────────────────────────────────────────────
-
- This function is also available under OS/2.
-
- ■ Return value
-
- Returns the previous value of option. There is no error return.
-
- ■ See also
-
- settextwindow
-
- ■ Example
-
- CC WRAP.FOR - Illustrates:
- CC wrapon
-
- INCLUDE 'FGRAPH.FI'
- INCLUDE 'FGRAPH.FD'
-
- INTEGER*2 dummy2, old_color, old_mode, row, col
- INTEGER*4 dummy4, old_bk
- CHARACTER*22 text
- CHARACTER*80 border
- RECORD / rccoord / curpos
- RECORD / videoconfig / vc
-
- DATA text / 'Here text DOES wrap. ' /
-
- CALL getvideoconfig( vc )
- old_mode = vc.mode
- old_color = gettextcolor()
- old_bk = getbkcolor()
- IF( vc.numtextcols .NE. 80 ) THEN
- IF( setvideomode( $TEXTC80 ) .EQ. 0 )
- + dummy2 = setvideomode( $TEXTMONO )
- END IF
- dummy2 = settextcolor( 14 )
- dummy4 = setbkcolor( 1 )
- CALL clearscreen( $GCLEARSCREEN )
- C
- C Draw window borders.
- C
- DO i = 1, 80
- border(i:i) = CHAR( 219 )
- END DO
- CALL settextposition( 13, 1, curpos )
- CALL outtext( border )
- col = 60
- DO row = 1, 25
- IF( row .EQ. 13 ) col = 20
- CALL settextposition( row, col, curpos )
- CALL outtext( border(1:1) )
- END DO
- C
- C Display wrapped and unwrapped text in windows.
- C
- dummy4 = setbkcolor( 0 )
- CALL settextwindow( 1, 1, 13, 59 )
- CALL settextposition( 1, 1, curpos )
- dummy2 = wrapon( $GWRAPON )
- dummy2 = settextcolor( 10 )
- DO i = 1, 32
- CALL outtext( text )
- END DO
- CALL outtext( text )
-
- CALL settextwindow( 14, 21, 25, 80 )
- CALL settextposition( 1, 1, curpos )
- dummy2 = wrapon( $GWRAPOFF )
- dummy2 = settextcolor( 12 )
- DO row = 1, 12
- CALL settextposition( row, 1, curpos )
- DO i = 1, 3
- CALL outtext( text(1:15) // 'NOT ' // text(16:22) )
- END DO
- END DO
-
- READ (*,*) ! Wait for ENTER to be pressed
- dummy2 = setvideomode( old_mode )
- dummy2 = settextcolor( old_color )
- dummy4 = setbkcolor( old_bk )
- END
-
- The program WRAP.FOR demonstrates the effect of wrapping and not wrapping
- text within a text window.
-
-
- Index
- ───────────────────────────────────────────────────────────────────────────
-
- /4I2 and /4I4 options (FL)
- /4Yb and /4Nb options (FL)
- /4Yb option (FL)
- I8087/287/387 coprocessor
- math package
- suppressing use of
-
- A
- ───────────────────────────────────────────────────────────────────────────
- Address sizes
- code
- data
- Address variables
- Addresses
- far
- code
- defined
- large and huge models
- subprogram calls
- huge
- defined
- huge arrays
- huge model
- near
- default data segment
- defined
- medium model
- subprograms
- ADR
- address variable
- keyword
- ADS, address variable
- Affine mode
- /AH option (FL)
- ALIAS keyword
- FORTRAN, use in
- Alternate math library
- /AM option (FL)
- API
- calls, low level
- DosCreateThread
- DosExit
- Apostrophes, use
- arc, arcwxy
- arc, arc_w
- Arguments
- passing
- by value
- medium model
- Array descriptors
- Arrays
- addressing
- adjustable size
- assumed size
- constant use, minimizing in declarations
- declaring for efficient compilation
- EQUIVALENCE statements, used in
- formal arguments, used as
- huge
- addressing
- Assembly interfaces; writing
- Assembly
- calling from
- FORTRAN
- interfaces
- address parameters, used with
- FORTRAN
- passing by
- far reference
- near reference
- procedures
- Attributes
- Attributes, FORTRAN
- Attributes
- FAR
- adjustable-size arrays
- arguments in medium model
- assumed-size arrays
- default data segment
- effects
- huge model
- library routines, used with
- medium model
- using
- HUGE
- alternative to huge model
- common blocks
- default data segment
- effects
- large model
- library routines, used with
- medium model
- using
- lack of portability
- NEAR
- adjustable-size arrays
- alternative to medium model
- assumed-size arrays
- common blocks
- declaring subprograms with
- effects
- huge model
- large and huge models
- library routines, used with
- subprograms
- VALUE
- Axes
- screen
-
- B
- ───────────────────────────────────────────────────────────────────────────
- BASIC
- arrays
- BYVAL keyword
- calling convention
- calling from
- FORTRAN
- CALLS statement
- common blocks
- compiling
- naming convention
- parameter-passing
- defaults
- methods
- passing by
- far reference
- near reference
- value
- procedures
- string format
- types, user-defined
- VARPTR keyword
- VARSEG keyword
- BEGINTHREAD run-time-library function
- _BEGINTHREAD run-time-library function
- BLOCKSIZE option
- Bold type, use
- BOOLEAN data type
- Bounding rectangle
- Brackets, double, use
- BYVAL keyword
-
- C
- ───────────────────────────────────────────────────────────────────────────
- C attribute
- FORTRAN, used in
- Pascal, used in
- C language
- calling convention
- calling from
- FORTRAN
- compiling
- FORTRAN, linking with
- functions
- memory models
- naming convention
- parameter-passing
- defaults
- methods
- passing by
- far reference
- near reference
- value
- pointers
- string format
- structures
- C-string feature, FORTRAN
- Calling conventions
- CALLS statement
- CDECL keyword
- ICGA (Color Graphics Adapter)
- Character types
- variables as format specifiers
- Classes
- defined
- clearscreen, library routine
- clearscreen
- Clipping region
- Clipping regions
- Code size
- limits
- Color Graphics Adapter see CGA
- Color indexes
- Color text modes see Video modes, text
- Color values
- Column-major order
- Common blocks
- formal arguments, used as
- large and huge models, used in
- medium model, used in
- memory allocation
- restrictions
- Compact memory model
- Compatibility
- 8087/287/387 library
- emulator library
- floating-point options
- Compiler options
- /AT
- /Lp
- /Zl
- COMPLEX data type, FORTRAN
- CONST keyword
- CONSTS keyword
- Conventions, document
- Coordinates
- physical
- text
- view
- viewport
- window
- Coprocessor
- 8087/287/387
- suppressing use of
- Courier, use of typeface
- CS register
-
- D
- ───────────────────────────────────────────────────────────────────────────
- Data address size
- Data segments
- data threshold
- default
- contents
- limits
- naming
- near addresses
- threshold, setting
- naming
- Data threshold, setting
- _DATA segment
- $DEBUG metacommand
- .DEF files
- introduced
- Default
- data segment
- contents
- data threshold
- defined
- limits
- object file
- Denormal
- numbers
- propagating
- Display attributes
- displaycursor
- DLL symbolic constant
- Document conventions
- DOSCALLS.LIB library
- DosCreateThread API call
- DosExit API call
- Double-precision reals
- Drawing see graphics
- DS register
- near addresses
- near, far, and huge addresses
- Dynamic linking
- Dynamic-link library
- creating
- defined
- multithread
- creating
- described
- using
- run time
- creating
- global data
- shared strings
- thread identification
- summary of components
-
- E
- ───────────────────────────────────────────────────────────────────────────
- Edit descriptors
- Tc
- TLc
- Edit lists
- EGA (Enhanced Graphics Adapter)
- ellipse, ellipsew, ellipsewxy
- ellipse, ellipse_w
- Ellipses, use
- EMOEM.ASM
- Emulator
- described
- function calls
- in-line instructions
- library
- ENDTHREAD run-time-library function
- Environment variables
- NO87
- EQUIVALENCE statement
- ERESCOLOR video mode
- Error messages
- removing text during SETUP
- ES register
- Exception handling
- control word
- dividing by zero
- invalid operation
- overflow and underflow
- precision
- status byte
- EXEMOD
- stack size, setting
- External data
-
- F
- ───────────────────────────────────────────────────────────────────────────
- Far addresses
- code
- data threshold
- defined
- large and huge models
- subprogram calls
- FAR attribute
- adjustable-size arrays
- assumed-size arrays
- default data segment
- effects
- huge model
- library routines, used with
- medium model, arguments in
- using
- Far reference parameters
- BASIC
- C
- FORTRAN
- FDLLOBJS.LIB library
- FGRAPH.FI
- constants in
- File-control blocks (FCBs)
- Files
- FORTRAN
- access modes
- binary direct
- binary sequential
- data formats
- formatted direct
- formatted sequential
- record structure
- unformatted direct
- unformatted sequential
- Fill flag
- Fill flags
- FL options
- /4I2 and /4I4
- /4Yb and 4Nb
- /AH
- /AL
- /AM
- /F
- /FPa
- /FPc87
- 8087/80287 coprocessor
- described
- floating-point operations
- /FPc
- described
- flexibility
- floating-point operations
- /FPi
- /FPi87
- /Gt
- described
- FAR attribute, compared with
- medium memory model
- standard memory models
- /NM
- /NT
- /Zl
- data threshold
- /Gt option
- default value, setting
- moving data items
- debug
- default integer size
- memory model
- huge
- large
- medium
- naming
- modules
- text segments
- stack size, setting
- suppressing
- library selection
- $FLOATCALLS metacommand
- Floating point
- exceptions
- disabling
- listed
- options
- compatibility
- default
- default libraries
- function calls
- in-line instructions
- maximum efficiency with coprocessor
- maximum efficiency without coprocessor
- maximum flexibility
- maximum precision with coprocessor
- floodfill, floodfillw
- .FNT files
- .FON files
- Fonts
- .FNT files
- .FON files
- bit-mapped
- data structure
- displaying
- example program
- functions, listed
- memory allocation
- option list
- spacing
- table
- type sizes
- typefaces
- vector-mapped
- Foreground colors
- Formatted I/O
- FORTRAN
- C, linking with
- fortran keyword
- FORTRAN.LIB
- FORTRAN
- ALIAS keyword
- arrays
- C attribute
- calling convention
- calls to
- BASIC
- C
- other languages
- Pascal
- common blocks
- compiling
- COMPLEX data type
- functions and subroutines
- INTERFACE statement
- LOC function
- LOCFAR function
- LOCNEAR function
- LOGICAL data type
- naming convention
- parameter-passing
- defaults
- keywords
- methods
- PASCAL attribute
- passing by
- far reference
- near reference
- value
- string formats
- /FPa option (FL)
- /FPc option (FL)
- described
- floating-point operations
- /FPc87 option (FL)
- /FPi option (FL)
- /FPi87 option (FL)
- FUNCTION procedures
- functions
- Functions
- listed
-
- G
- ───────────────────────────────────────────────────────────────────────────
- getactivepage
- getbkcolor, library routine
- getbkcolor
- getcolor
- getcurrentposition, getcurrentpositionw
- getcurrentposition, getcurrentposition_w
- getfillmask
- getfontinfo
- getgtextextent
- getimage, getimage_w
- getlinestyle
- getphyscoord
- getpixel, getpixelw
- getpixel, getpixel_w
- gettextcolor, library routine
- gettextcolor
- gettextcursor
- gettextposition
- getvideoconfig
- getviewcoord, getviewcoordw, getviewcoordwxy
- getviewcoord, getviewcoord_w
- getvisualpage
- getwindowcoord
- GFILLINTERIOR, fill flag
- Ggraphics
- color selection
- Ggraphics
- palettes
- Global data, sharing
- GRAPH.H
- described
- Graphics
- attributes
- color selection
- configuration
- coordinates
- display characteristics
- see also drawing
- font functions. See Fonts
- font functions
- described
- use
- fonts
- image transfer
- output
- arc, arcwxy
- arc, arc_w
- ellipse, ellipsew, ellipsewxy
- ellipse, ellipse_w
- lineto, linetow
- pie, piewxy
- pie, pie_w
- rectangle, rectanglew, rectanglewxy
- rectangle, rectangle_w
- palettes
- parameters
- physical coordinates
- text output
- text support, listed
- text support
- settextrows
- settextwindow
- setvideomoderows
- setwindow
- view coordinates
- viewport coordinates
- window coordinates
- /Gt option (FL)
- described
- FAR attribute, compared with
- medium memory model
- standard memory models
-
- H
- ───────────────────────────────────────────────────────────────────────────
- Header files see GPROC.FI
- Hercules Graphics Card
- HRES16COLOR video mode
- HUGE attribute
- alternative to huge model
- common blocks
- default data segment
- effects
- large model
- library routines, used with
- medium model, arguments in
- using
- Huge memory model, use with C
- Huge
- addresses
- arrays
- defined
- huge model
- memory model. See also Memory models
- /AH option (FL)
- adjustable-size arrays
- assumed-size arrays
- described
-
- I
- ───────────────────────────────────────────────────────────────────────────
- I/O
- buffers
- formatted
- list-directed
- imagesize, imagesize_w
- IMPLIB (Microsoft Import Library Manager)
- Imports library
- In-line instructions
- Include files
- FGRAPH.FI
- Include files see GRAPH.H
- Infinities
- Infinity arithmetic modes
- INTERFACE statement
- INTERFACE statement, FORTRAN
- Italics, use
-
- L
- ───────────────────────────────────────────────────────────────────────────
- Large memory model
- Large memory model
- /AL option (FL)
- adjustable-size, assumed-size arrays
- described
- see Memory models
- $LARGE metacommand
- LCWRQQ routine
- masking denormals
- LES instruction
- LIB (Microsoft Library Manager)
- LIBPATH variable
- Libraries
- 8087/287/387
- 8087/80287
- alternate math
- controlling use
- DOSCALLS.LIB
- emulator
- FORTRAN.LIB
- huge model
- imports
- large model
- LLIBFMT.LIB
- LLIBFOR7.LIB
- LLIBFORA.LIB
- LLIBFORE.LIB
- medium model
- memory models
- MLIBFOR7.LIB
- MLIBFORA.LIB
- MLIBFORE.LIB
- multithread programs
- standard memory models, support for
- Library functions see Routines
- Line styles
- see also Presentation Graphics, palettes
- linetow
- lineto
- lineto_w
- LINK options
- /NODEFAULTLIBRARYSEARCH (/NOD)
- standard libraries
- /STACK (/ST)
- stack size, setting
- Linker options
- /NODEFAULTLIBRARYSEARCH (/NOD)
- List-directed I/O
- Listing files
- map
- LLIBFMT.LIB library
- LLIBFOR7.LIB
- LLIBFORA.LIB
- LLIBFORE.LIB
- LOC, FORTRAN function
- LOCFAR, FORTRAN function
- LOCNEAR, FORTRAN function
- LOGICAL data type, FORTRAN
- Low-level graphics
- output
- lineto, lineto_w
- Lower bounds, arrays
- /Lp compiler option
- multithread programs
- LSTRING
-
- M
- ───────────────────────────────────────────────────────────────────────────
- Macro Assembler
- assembly interfaces, writing
- simplified segment directives
- Map file, code size
- Medium memory model
- /AM option (FL)
- adjustable-size, assumed-size arrays
- argument passing
- common blocks
- described
- NEAR and FAR attributes
- Memory models
- adjustable-size arrays
- argument passing
- assumed-size arrays
- see also Attributes, FAR
- see also Attributes, HUGE
- see also Attributes, NEAR
- common blocks
- customizing
- default
- defined
- huge
- /AH option (FL)
- adjustable-size arrays
- arrays
- assumed-size arrays
- described
- large
- /AL option (FL)
- adjustable-size, assumed-size arrays
- described
- library support
- medium
- /AM option (FL)
- adjustable-size, assumed-size arrays
- argument passing
- common blocks
- default data segment
- described
- restrictions
- selecting
- specifying
- standard
- Metacommands
- $DEBUG
- $FLOATCALLS
- $LARGE
- $NOFLOATCALLS
- $NOTLARGE
- $STORAGE
- Microsoft Import Library Manager, see IMPLIB
- Microsoft Library Manager, see LIB
- Microsoft Windows
- Mixed-language programs
- compiling
- linking
- MLIBFOR7.LIB
- MLIBFORA.LIB
- MLIBFORE.LIB
- Modules, naming
- Monotype, use of
- movetow
- moveto
- moveto_w
- MRES16COLOR video mode
- MRES256COLOR video mode
- MRES4COLOR video mode
- MRESNOCOLOR video mode
- MT symbolic constant
- /MT compiler option
- Multitasking
- Multithread programs
- compiling and linking
- see Dynamic-link libraries
- function calls
- library support
- memory allocation
- possible problems
- run-time thread management
- BEGINTHREAD
- ENDTHREAD
- THREADID
- _BEGINTHREAD
- stack checking
-
- N
- ───────────────────────────────────────────────────────────────────────────
- Naming conventions
- Naming
- modules
- segments
- NANs
- Near addresses
- default data segment
- defined
- medium model
- subprograms
- NEAR attribute, FORTRAN
- NEAR attribute
- adjustable-size arrays
- alternative to medium model
- assumed-size arrays
- common blocks
- declaring subprograms with
- effects
- huge model
- large and huge models
- large and huge models
- library routines, used with
- subprograms
- Near reference parameters
- assembly
- BASIC
- C
- FORTRAN
- Pascal
- NO87 variable
- /NODEFAULTLIBRARYSEARCH (/NOD) linker option
- /NODEFAULTLIBRARYSEARCH option (LINK)
- standard libraries
- $NOFLOATCALLS metacommand
- /NOI linker option
- /NM option (FL)
- $NOTLARGE metacommand
- /NT option (FL)
-
- O
- ───────────────────────────────────────────────────────────────────────────
- origin
- OS/2 support files
- DOSCALLS.LIB
- LLIBFMT.LIB
- FDLLOBJS.LIB
- outgtext
- outtext
- Overlays
- reducing program size
-
- P
- ───────────────────────────────────────────────────────────────────────────
- Packed storage
- Palettes
- Palettes
- display
- remapping
- Parameter-passing methods
- Parameters
- calling conventions, effect of
- passing, see also Passing by
- varying number of
- PASCAL attribute
- pascal keyword
- Pascal
- address variables
- C attribute
- calling convention
- calling from
- FORTRAN
- compiling
- functions and procedures
- LSTRING
- naming convention
- parameter-passing
- defaults
- methods
- passing by
- near reference
- records
- string formats
- Passing arguments
- by value
- medium model
- Passing by
- far reference
- assembly
- BASIC
- C
- FORTRAN
- near reference
- assembly
- BASIC
- C
- FORTRAN
- FORTRAN
- Pascal
- value
- BASIC
- C
- FORTRAN
- pie, piewxy
- pie, pie_w
- Pixel values see Color indexes
- Pixels, defined
- Pointers
- Procedures
- Process, illustrated
- Programs, sample
- COLTEXT.C
- SAMPLER.C
- SAMPLER.FOR
- SINE
- Public data
- putimage, putimage_w
-
- R
- ───────────────────────────────────────────────────────────────────────────
- Receiving parameters and calling conventions
- Record structure
- binary direct files
- binary sequential files
- formatted direct files
- formatted sequential files
- unformatted direct files
- unformatted sequential files
- Records
- rectangle, rectanglew, rectanglewxy
- rectangle, rectangle_w
- REFERENCE attribute
- registerfonts
- Registers
- CS
- DS
- near addresses
- near, far, and huge addresses
- ES
- SS
- remapallpalette
- described
- use
- remappalette
- described
- use
- Remapping, see Palettes, remapping
- Resource, ownership of
- Round control
- Routines, categories
- Routiness
- Row-major order
-
- S
- ───────────────────────────────────────────────────────────────────────────
- Sample programs
- FMHELLO.FOR
- SNAP.FOR
- Screen groups, illustrated
- Segment directives, simplified
- Segments
- code
- data
- default
- naming
- naming
- text
- default
- naming
- selectpalette
- described
- use
- setactivepage
- setbkcolor
- setcliprgn
- setcolor
- setfillmask
- described
- dselection
- use
- setfont
- setlinestyle
- setpixelw
- setpixel
- described
- use
- setpixel_w
- settextcolor
- settextcursor
- settextposition
- settextrows
- settextwindow
- SETUP
- removing error-message text
- setvideomoderows
- setvideomode
- described
- use
- setvieworg
- setviewport
- setvisualpage
- setwindow
- sine
- Single-precision reals
- Small memory model
- C, use with
- Special data types
- SS register
- Stack
- allocating separately from DS
- changing size
- default data segment, used in
- large
- Stack checking
- /STACK option
- (LINK)
- default data segment
- Static data
- Static linking
- $STORAGE metacommand
- Strings
- passing from
- C
- FORTRAN
- Pascal
- Structured data types
- Structures
- Subprograms
- Subroutines
- Symbolic constants, described
- Syntax conventions
- Document conventions
-
- T
- ───────────────────────────────────────────────────────────────────────────
- Tc edit descriptor
- Text segment
- default name
- naming
- _TEXT
- TEXTC40 video mode
- TEXTC80 video mode
- THREADID run-time-library function
- THREADID variable
- Threads
- defined
- ending
- identifying
- illustrated
- synchronizing
- TLc edit descriptor
- Typefaces
-
- U
- ───────────────────────────────────────────────────────────────────────────
- Unpacked storage
- unregisterfonts
- Unsigned integers
- Uppercase, use of
- User-defined types
-
- V
- ───────────────────────────────────────────────────────────────────────────
- VALUE attribute
- VALUE keyword
- Value parameters
- BASIC
- C
- FORTRAN
- passing
- VAR keyword
- Variables
- address
- LIBPATH
- _THREADID
- VARPTR keyword
- VARS keyword
- VARSEG keyword
- VARYING attribute
- VGA (Video Graphics Array)
- Video adapters
- CGA
- EGA
- Hercules
- VGA
- Video memory
- Video modes
- graphics
- CGA
- described
- EGA
- setting
- setting color
- VGA
- table
- (table)
- text
- Video modesgraphics
- setting
- videoconfig structure
- VRES16COLOR video mode
- VRES2COLOR video mode
-
- W
- ───────────────────────────────────────────────────────────────────────────
- Windows, graphics
- wrapon
-
- Z
- ───────────────────────────────────────────────────────────────────────────
- /Zl compiler option
- /Zl option (FL)
-
-