Microsoft QuickC v2

This commit is contained in:
davidly 2024-07-02 06:32:02 -07:00
parent 5c4870468d
commit d64f7de3f9
151 changed files with 17743 additions and 0 deletions

Binary file not shown.

393
Microsoft QuickC v2/C1.ERR Normal file
View File

@ -0,0 +1,393 @@
/* SCCSWHAT( "@(#)c1.err 2.76 88/12/08 15:34:23 " ) */
/* fatals */
1001 "Internal Compiler Error\n\t\t(compiler file '%s', line %d)\n\t\tContact Microsoft Technical Support"
1002 "out of heap space"
1003 "error count exceeds %d; stopping compilation"
1004 "unexpected EOF"
1005 "string too big for buffer"
1006 "write error on compiler intermediate file"
1007 "unrecognized flag '%s' in '%s'"
1008 "no input file specified"
1009 "compiler limit : macros too deeply nested"
1010 "compiler limit : macro expansion too big"
1011 "compiler limit : '%s': macro definition too big"
1012 "bad parenthesis nesting - missing '%c'"
1013 "cannot open source file '%s'"
1014 "too many include files"
1015 "cannot open include file '%s'"
1016 "#if[n]def expected an identifier"
1017 "invalid integer constant expression"
1018 "unexpected '#elif'"
1019 "unexpected '#else'"
1020 "unexpected '#endif'"
1021 "bad preprocessor command '%s'"
1022 "expected '#endif'"
1025 "compiler terminated by user" /* QC */
1026 "parser stack overflow, please simplify your program"
1027 "DGROUP data allocation exceeds 64K" /* QC, c23 */
1028 "%s segment allocation exceeds 64K" /* QC */
1031 "compiler limit : function calls too deeply nested" /* QC, c23 */
1032 "cannot open object listing file '%s'" /* QC, c23 */
1035 "expression too complex, please simplify" /* QC, c23 */
1037 "cannot open object file '%s'" /* QC, c23 */
1041 "cannot open compiler intermediate file - no more files"
1042 "cannot open compiler intermediate file - no such file or directory"
1043 "cannot open compiler intermediate file"
1044 "out of disk space for compiler intermediate file"
1045 "floating point overflow"
1047 "too many %s flags, '%s'"
1048 "unknown option '%c' in '%s'"
1049 "invalid numerical argument '%s'"
1052 "too many #if/#ifdef's"
1053 "compiler limit : struct/union nesting"
1054 "compiler limit : initializers too deeply nested"
1055 "compiler limit : out of keys"
1056 "compiler limit : out of macro expansion space"
1057 "unexpected EOF in macro expansion (missing ')'?)"
1059 "out of near heap space"
1060 "out of far heap space"
1061 "compiler limit : blocks too deeply nested" /* QC */
1062 "error writing to preprocessor output file"
1063 "compiler limit : compiler stack overflow" /* QC */
1064 "compiler limit : identifier overflowed internal buffer"
1065 "declarator too complex" /* C51 */
1068 "cannot open file '%s'" /* QC */
1069 "write error on file '%s'" /* QC */
1070 "mismatched #if/#endif pair in file '%s'"
1126 "%Fs : auto allocation exceeds %s" /* QC, c23 */
1000 "UNKNOWN FATAL ERROR\n\t\tContact Microsoft Technical Support"
/* errors */
2001 "newline in constant"
2002 "out of macro actual parameter space" /* C51 */
2003 "expected 'defined id'"
2004 "expected 'defined(id)'"
2005 "#line expected a line number, found '%s'"
2006 "#include expected a file name, found '%s'"
2007 "#define syntax"
2008 "'%c' : unexpected in macro definition"
2009 "reuse of macro formal '%s'"
2010 "'%c' : unexpected in formal list"
2011 "'%s' : definition too big" /* C51 */
2012 "missing name following '<'"
2013 "missing '>'"
2014 "preprocessor command must start as first non-whitespace"
2015 "too many chars in constant"
2016 "no closing single quote"
2017 "illegal escape sequence"
2018 "unknown character '0x%x'"
2019 "expected preprocessor command, found '%c'"
2020 "bad octal number '%c'" /* C51 */
2021 "expected exponent value, not '%c'"
2022 "'%ld' : too big for char"
2023 "divide by 0"
2024 "mod by 0"
2025 "'%s' : enum/struct/union type redefinition"
2026 "'%s' : member of enum redefinition"
2027 "use of undefined enum/struct/union '%Fs'"
2028 "struct/union member needs to be inside a struct/union"
2029 "'%Fs' : bit-fields only allowed in structs"
2030 "'%Fs' : struct/union member redefinition"
2031 "'%Fs' : function cannot be struct/union member"
2032 "'%Fs' : base type with near/far/huge not allowed" /* C51 */
2033 "'%Fs' : bit-field cannot have indirection"
2034 "'%Fs' : bit-field type too small for number of bits"
2035 "struct/union '%Fs' : unknown size"
2036 "left of '%s%s' must have a struct/union type"
2037 "left of '%s' specifies undefined struct/union '%Fs'"
2038 "'%s' : not struct/union member"
2039 "'->' requires struct/union pointer"
2040 "'.' requires struct/union name"
2041 "illegal digit '%c' for base %d"
2042 "signed/unsigned keywords mutually exclusive"
2043 "illegal break"
2044 "illegal continue"
2045 "'%s' : label redefined"
2046 "illegal case"
2047 "illegal default"
2048 "more than one default"
2050 "non-integral switch expression"
2051 "case expression not constant"
2052 "case expression not integral"
2053 "case value %d already used"
2054 "expected '(' to follow '%Fs'"
2055 "expected formal parameter list, not a type list"
2056 "illegal expression"
2057 "expected constant expression"
2058 "constant expression is not integral"
2059 "syntax error : '%s'"
2060 "syntax error : EOF"
2061 "syntax error : identifier '%s'"
2062 "type '%s' unexpected"
2063 "'%s' : not a function"
2064 "term does not evaluate to a function"
2065 "'%s' : undefined"
2066 "cast to function returning . . . is illegal"
2067 "cast to array type is illegal"
2068 "illegal cast"
2069 "cast of 'void' term to non-void"
2070 "illegal sizeof operand"
2071 "'%Fs' : bad storage class"
2072 "'%Fs' : initialization of a function"
2073 "'%Fs' : cannot initialize array in function" /* C51 */
2074 "'%Fs' : cannot initialize struct/union in function" /* C51 */
2075 "'%Fs' : array initialization needs curly braces"
2076 "'%Fs' : struct/union initialization needs curly braces"
2077 "non-scalar field initializer '%Fs'"
2078 "too many initializers"
2079 "'%Fs' uses undefined struct/union '%Fs'"
2082 "redefinition of formal parameter '%Fs'"
2083 "array '%Fs' already has a size" /* C51 */
2084 "function '%Fs' already has a body"
2085 "'%Fs' : not in formal parameter list"
2086 "'%Fs' : redefinition"
2087 "'%Fs' : missing subscript"
2088 "use of undefined enum/struct/union '%s'" /* C51 */
2089 "typedef specifies a near/far function" /* C51 */
2090 "function returns array"
2091 "function returns function"
2092 "array element type cannot be function"
2093 "cannot initialize a static or struct with address of automatic vars"
2094 "label '%Fs' was undefined"
2095 "'%Fs' : actual has type 'void' : parameter %d"
2096 "struct/union comparison illegal"
2097 "illegal initialization"
2098 "non-address expression"
2099 "non-constant offset"
2100 "illegal indirection"
2101 "'&' on constant"
2102 "'&' requires lvalue"
2103 "'&' on register variable"
2104 "'&' on bit-field ignored"
2105 "'%s' needs lvalue"
2106 "'%s' : left operand must be lvalue"
2107 "illegal index, indirection not allowed"
2108 "non-integral index"
2109 "subscript on non-array"
2110 "'+' : 2 pointers"
2111 "pointer + non-integral value"
2112 "illegal pointer subtraction"
2113 "'-' : right operand pointer"
2114 "'%s' : pointer on left; needs integral right"
2115 "'%s' : incompatible types"
2116 "'%s' : bad %s operand"
2117 "'%s' : illegal for struct/union"
2118 "negative subscript"
2119 "'typedefs' both define indirection"
2120 "'void' illegal with all types"
2121 "typedef specifies different enum" /* C51 */
2122 "typedef specifies different struct" /* C51 */
2123 "typedef specifies different union" /* C51 */
2125 "%Fs : allocation exceeds 64K" /* QC, c23 */
2127 "parameter allocation exceeds 32K" /* QC, c23 */
2130 "#line expected a string containing the file name, found '%s'"
2131 "attributes specify more than one near/far/huge"
2132 "syntax error : unexpected identifier"
2133 "'%Fs' : unknown size"
2134 "'%Fs' : struct/union too large"
2135 "missing ')' in macro expansion" /* C51 */
2137 "empty character constant"
2138 "unmatched close comment '*/'"
2139 "type following '%s' is illegal"
2140 "argument type cannot be function returning . . ."
2141 "value out of range for enum constant"
2142 "ellipsis requires three periods"
2143 "syntax error : missing '%s' before '%s'"
2144 "syntax error : missing '%s' before type '%Fs'"
2145 "syntax error : missing '%s' before identifier"
2146 "syntax error : missing '%s' before identifier '%s'"
2147 "unknown size"
2148 "array too large"
2149 "'%Fs' : named bit-field cannot have 0 width"
2150 "'%Fs' : bit-field must have type int, signed int, or unsigned int"
2151 "more than one cdecl/fortran/pascal attribute specified"
2152 "'%s' : pointers to functions with different attributes"
2153 "hex constants must have at least 1 hex digit"
2154 "'%s' : does not refer to a segment name"
2155 "'%s' : already in a segment" /* C51 */
2156 "pragma must be at outer level"
2157 "'%s' : must be declared before use in pragma list"
2158 "'%s' : is a function"
2159 "more than one storage class specified"
2160 "## cannot occur at the beginning of a macro definition"
2161 "## cannot occur at the end of a macro definition"
2162 "expected macro formal parameter"
2163 "'%s' : not available as an intrinsic"
2164 "'%s' : intrinsic was not declared"
2165 "'%s' : cannot modify pointers to data"
2166 "lval specifies 'const' object"
2167 "'%Fs' : too many actual parameters for intrinsic"
2168 "'%Fs' : too few actual parameters for intrinsic"
2169 "'%Fs' : is an intrinsic, it cannot be defined"
2170 "'%s' : intrinsic not declared as a function"
2171 "'%s' : bad operand"
2172 "'%Fs' : actual is not a pointer : parameter %d"
2173 "'%Fs' : actual is not a pointer : parameter %d, parameter list %d"
2174 "'%Fs' : actual has type 'void' : parameter %d, parameter list %d"
2175 "'%Fs' : unresolved external" /* QC */
2176 "static huge data not supported" /* QC */
2177 "constant too big"
2178 "'%s' : storage class for same_seg variables must be 'extern'"
2179 "'%Fs' : was used in same_seg, but storage class is no longer 'extern'"
2180 "controlling expression has type 'void'"
2181 "pragma requires command line option '%s'" /* QC */
2182 "'%Fs' : has type 'void'"
2183 "'%Fs' : 'interrupt' function must be 'far'" /* C51 */
2184 "'%Fs' : '%s' function cannot be 'pascal/fortran'" /* C51 */
2186 "'%Fs' : 'saveregs/interrupt' modifiers mutually exclusive" /* C51 */
2187 "cast of near function pointer to far function pointer"
2188 "#error : %s"
2190 "'%s' : is a text segment" /* C51 */
2191 "'%s' : is a data segment" /* C51 */
2192 "'%s' : function has already been defined" /* C51 */
2198 "'%Fs' : tried to be allocated in code segment '%Fs'"
2199 "'%Fs' : tried to be allocated in data segment '%Fs'"
2200 "'%Fs' : function has already been defined"
2201 "'%Fs' : storage class must be 'extern'"
2202 "'interrupt' function must be 'far'"
2203 "'%s' function cannot be 'pascal/fortran'"
2204 "'saveregs/interrupt' modifiers mutually exclusive"
2205 "'%Fs' : cannot initialize 'extern' block scoped variables"
2206 "'%Fs' : typedefs cannot be used for function definitions"
2400 "inline syntax error %s, found '%Fs'"
2401 "'%s' : register must be base %s"
2402 "'%s' : register must be index %s"
2403 "'%s' : register must be base/index %s"
2404 "'%s' : illegal register %s"
2405 "illegal short forward reference with offset"
2406 "'%s' : name undefined %s"
2407 "illegal float register %s"
2408 "illegal type on PTR operator %s"
2409 "illegal type used as operator %s"
2410 "'%s' : ambiguous member name %s"
2411 "'%s' : illegal struct/union member %s"
2412 "'%s' : label redefined"
2413 "'%s' : illegal align size"
2414 "illegal number of operands"
2415 "improper operand type"
2416 "'%s' : illegal opcode for processor"
2417 "divide by zero %s"
2418 "'%Fs' : not in a register"
2419 "mod by zero %s"
2420 "'%s' : illegal symbol %s"
2421 "PTR operator used with register %s"
2422 "illegal segment override %s"
2424 "'%Fs' : improper expression %s"
2425 "'%Fs' : non-constant expression %s"
2426 "'%Fs' : illegal operator %s"
2427 "'%Fs' : jump referencing label is out of range" /* QC */
2429 "'%Fs' : illegal far label reference"
2000 "UNKNOWN ERROR\n\t\tContact Microsoft Technical Support"
/* warnings */
4001 "macro '%s' requires parameters" /* C51 */
4002 "too many actual parameters for macro '%s'"
4003 "not enough actual parameters for macro '%s'"
4004 "missing close parenthesis after 'defined'"
4005 "'%s' : redefinition"
4006 "#undef expected an identifier"
4009 "string too big, trailing chars truncated"
4011 "identifier truncated to '%s'"
4012 "float constant in a cross compilation"
4013 "constant too big" /* C51 */
4014 "'%Fs' : bit-field type must be unsigned"
4015 "'%Fs' : bit-field type must be integral"
4016 "'%s' : no function return type, using 'int' as default"
4017 "cast of int expression to far pointer"
4020 "'%Fs' : too many actual parameters"
4021 "'%Fs' : too few actual parameters"
4022 "'%Fs' : pointer mismatch : parameter %d"
4024 "'%Fs' : different types : parameter %d"
4025 "function declaration specified variable argument list" /* C51 */
4026 "function was declared with formal argument list"
4027 "function was declared without formal argument list"
4028 "parameter %d declaration different"
4029 "declared parameter list different from definition"
4030 "first parameter list is longer than the second"
4031 "second parameter list is longer than the first"
4032 "unnamed struct/union as parameter"
4033 "function must return a value"
4034 "sizeof returns 0"
4035 "'%Fs' : no return value"
4036 "unexpected formal parameter list" /* C51 */
4037 "'%Fs' : formal parameters ignored"
4038 "'%Fs' : formal parameter has bad storage class"
4039 "'%Fs' : function used as an argument"
4040 "near/far/huge on '%Fs' ignored"
4041 "formal parameter '%s' is redefined" /* C51 */
4042 "'%Fs' : has bad storage class"
4044 "huge on '%Fs' ignored, must be an array"
4045 "'%s' : array bounds overflow"
4046 "'&' on function/array, ignored"
4047 "'%s' : different levels of indirection"
4048 "array's declared subscripts different"
4049 "'%s' : indirection to different types"
4051 "data conversion"
4052 "different enum types" /* C51 */
4053 "at least one void operand"
4058 "address of frame variable taken, DS != SS" /* QC, c23 */
4060 "conversion of long address to short address" /* QC, c23 */
4061 "long/short mismatch in argument : conversion supplied" /* QC, c23 */
4062 "near/far mismatch in argument : conversion supplied" /* QC, c23 */
4067 "unexpected characters following '%s' directive - newline expected"
4068 "unknown pragma"
4069 "conversion of near pointer to long integer" /* QC, c23 */
4071 "'%Fs' : no function prototype given"
4074 "non standard extension used - '%s'"
4075 "size of switch expression or case constant too large - converted to int"
4076 "'%s' : may be used on integral types only"
4077 "unknown check_stack option"
4079 "unexpected token '%s'"
4080 "expected 'identifier' for segment name, found '%s'"
4081 "expected a comma, found '%s'"
4082 "expected an identifier, found '%s'"
4083 "expected '(', found '%s'"
4084 "expected a pragma keyword, found '%s'"
4085 "expected [on | off]"
4086 "expected [1 | 2 | 4]"
4087 "'%Fs' : declared with 'void' parameter list"
4088 "'%Fs' : pointer mismatch : parameter %d, parameter list %d"
4089 "'%Fs' : different types : parameter %d, parameter list %d"
4090 "different 'const' attributes"
4091 "no symbols were declared"
4092 "untagged enum/struct/union declared no symbols"
4093 "unescaped newline in character constant in non-active code"
4094 "unexpected newline" /* C51 */
4095 "expected ')', found '%s'"
4098 "void function returning a value"
4099 "expected ')', (too many arguments?)" /* C51 */
4100 "'%Fs' : unreferenced formal parameter"
4101 "'%Fs' : unreferenced local variable"
4102 "'%Fs' : unreferenced label"
4103 "'%Fs' : function definition used as prototype" /* C51 */
4104 "'%s' : near data in same_seg pragma, ignored"
4105 "'%Fs' : code modifiers only on function or pointer to function"
4106 "pragma requires integer between 1 and 127"
4107 "pragma requires integer between 15 and 255"
4108 "pragma requires integer between 79 and 132"
4109 "unexpected identifier '%s'"
4110 "unexpected token 'int constant'"
4111 "unexpected token 'string'"
4112 "macro name '%s' is reserved, %s ignored"
4113 "function parameter lists differed"
4114 "same type qualifier used more than once"
4115 "'%Fs' : type definition in formal parameter list"
4116 "<no tag> : type definition in formal parameter list"
4118 "pragma not supported"
4401 "'%s' : member is bitfield"
4402 "must use PTR operator"
4403 "illegal PTR operator"
4404 "period on directive ignored"
4405 "'%s' : identifier is reserved word"
4406 "operand on directive ignored"
4407 "operand size conflict"
4408 "'%s' : ambiguous label"
4409 "illegal instruction size"
4410 "illegal size for operand"
4411 "'%s' : symbol resolves to displacement register"
4412 "'%s' : identifier is also assembler mnemonic"
4413 "'%Fs' redefined: preceeding references may be invalid."
4000 "UNKNOWN WARNING\n\t\tContact Microsoft Technical Support"

View File

@ -0,0 +1,35 @@
/* error messages */
2001 "too many symbols predefined with -D"
2002 "a previously defined model specification has been overridden"
2003 "missing source file name"
2008 "too many %s flags, '%s'"
2011 "only one floating point model allowed"
2012 "too many linker flags on command line"
2013 "incomplete model specification"
2016 "%s and %s are incompatible"
2018 "cannot open linker cmd file"
2019 "cannot overwrite the source/object file, '%s'"
2020 "-Gc option requires extended keywords to be enabled (-Ze)"
2021 "invalid numerical argument '%s'"
2022 "cannot open help file, '%s'"
2027 "could not execute '%s'"
2028 "too many open files, cannot redirect '%s'"
2000 "UNKNOWN COMMAND LINE ERROR\n\t\tContact Microsoft Technical Support"
/* warning messages */
4001 "listing has precedence over assembly output"
4002 "ignoring unknown flag '%s'"
4003 "Different processors selected for code generation"
4005 "could not execute '%s';\nPlease enter new file name (full path) or Ctrl-C to quit: "
4006 "only one of -P/-E/-EP allowed, -P selected"
4007 "-C ignored (must also specify -P or -E or -EP)"
4009 "threshold only for far/huge data, ignored"
4011 "preprocessing overrides source listing"
4012 "function declarations override source listing"
4013 "combined listing has precedence over object listing"
4014 "invalid value %d for '%s'. Default %d is used"
4018 ".DEF files supported in protected mode only"
4019 "string too long. Truncated to %d characters"
4000 "UNKNOWN COMMAND LINE WARNING\n\t\tContact Microsoft Technical Support"

Binary file not shown.

View File

@ -0,0 +1,57 @@
PATCH320.DOC File
Notes on patching IBM(R) PC-DOS Version 3.20
(C) Copyright Microsoft Corporation, 1988
Version 3.20 of IBM(R) PC-DOS contains a bug that can cause unexpected results
in programs that generate floating-point exceptions. This file explains how to
install a small patch in DOS to eliminate the problem.
It is especially important to install this patch if you wish to use the C
run-time routine signal with the SIGFPE parameter, since that routine does
not work correctly in the unpatched version of IBM PC-DOS 3.20. IBM Corporation
also supplies a patch to eliminate this problem.
Note that MS-DOS(R) Version 3.20 contains another, different floating-point
bug. The README.DOC file for this release tells you where to find more
information about installing a patch for that bug. If you use any version of
DOS 3.20 other than IBM PC-DOS 3.20 or MS-DOS 3.20, contact your hardware
manufacturer to determine whether the problem exists in your version.
You can install the DOS patch for IBM PC-DOS 3.20 by following these steps:
1. Format a blank floppy disk. (Do NOT use the /s formatting option to
transfer system files to the disk.)
2. Use the SYS command to copy the files IBMDOS.COM and IBMBIO.COM to
the new disk. For example, if you boot from drive C:, you could use
these commands:
C:
SYS A:
3. Use the COPY command to copy the files COMMAND.COM, SYS.COM, and
DEBUG.COM to the new disk.
4. Use the COPY command to copy the files STKPAT.BAT, STKPAT.SCR,
RMRHS.EXE, and SETRHS.EXE from the \PATCH directory of your hard-disk
drive to the new disk.
5. Reboot your system from the floppy disk that you prepared in steps 1-4.
6. Run the STKPAT.BAT file to patch the IBMBIO.COM file on the new disk.
7. Use the SYS command to transfer the patch from the floppy disk to any
other Version 3.20 disk. For example, if you normally boot from drive
C:, you would enter these commands to transfer the patched DOS to
your hard-disk drive:
A:
SYS C:
This installs the patch.
8. Reboot your system as you normally do.

View File

@ -0,0 +1,107 @@
PATCH87.DOC File
Notes on patching MS-DOS(R) Version 3.20
(C) Copyright Microsoft Corporation, 1988
Version 3.20 of MS-DOS(R) contains a bug that can cause unexpected results in
programs that use floating-point math. This file explains how to eliminate
that problem by using PATCH87.EXE, a program included in this release.
Note that IBM(R) PC-DOS 3.20 contains another, different floating-point bug.
The README.DOC file for this release tells you where to find more information
about installing a patch for that bug. If you use any version of DOS 3.20
other than IBM PC-DOS 3.20 or MS-DOS 3.20, contact your hardware manufacturer
to determine whether the problem exists in your version.
Do I Need to Use This Program?
------------------------------
You do not need to read any further unless your system has ALL of the following
characteristics:
1. You use MS-DOS version 3.20.
2. You boot from a hard-disk drive.
3. Your system has a math coprocessor (for instance, an 8087 chip).
4. 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. If
you are not sure whether you need the patch, perform the following steps:
1. Copy the program PATCH87.EXE (included in this release) to the root
directory of your hard-disk drive.
2. Reboot your system from the hard disk and DO NOT PERFORM ANY FLOPPY-
DISK OPERATIONS after rebooting. It is very important that you avoid
floppy-disk I/O after rebooting, since that will affect the reliability
of the diagnostic test that you are about to perform.
3. If necessary, use the CD command to move to the root directory of your
hard-disk drive.
4. Run the PATCH87.EXE program by entering this command at the DOS prompt:
PATCH87
The program performs a diagnostic test on your system to determine
whether it needs the DOS patch, and, if the patch is needed,
whether it can be performed successfully.
5. Follow the procedure described in the next section if the program
tells you that you need to install the DOS patch, and that it can
be done.
NOTE: The floating-point problem has been eliminated in versions of
MS-DOS higher than 3.20. This includes MS-DOS versions 3.21 and 3.30.
If You Need to Install the Patch
--------------------------------
If you performed the preceding test and determined that you should install the
DOS patch on your system, perform the following steps:
1. Format a blank floppy disk. (Do NOT use the /s formatting option to
transfer system files to the disk.)
2. Use the SYS command to copy IO.SYS and MSDOS.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
the following command:
A:
7. Install the DOS patch by entering the following command:
PATCH87 /F
WARNING: If you experience any disk errors during steps 2 through 7,
do NOT proceed with step 8. Reboot from your hard disk and repeat the
entire process.
8. If you have not experienced any errors, use the SYS command to transfer
the files IO.SYS and MSDOS.SYS from the floppy disk back to your hard
disk. For instance, if the boot directory of your system is the root
directory of drive C:, you would enter the following command at the DOS
prompt:
A:
SYS C:
This installs the DOS patch.
9. Reboot the system.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,6 @@
echo This script will work only on drive a:
rmrhs
debug ibmbio.com <stkpat.scr
setrhs

View File

@ -0,0 +1,5 @@
a c48
jmp short c64
w
q

35
Microsoft QuickC v2/E.C Normal file
View File

@ -0,0 +1,35 @@
#include <stdio.h>
#ifndef MWC
#include <string.h>
#include <stdlib.h>
#endif
#define DIGITS_TO_FIND 200 /*9009*/
int main() {
int N = DIGITS_TO_FIND;
int x = 0;
int a[ DIGITS_TO_FIND ];
int n;
for (n = N - 1; n > 0; --n) {
a[n] = 1;
}
a[1] = 2, a[0] = 0;
while (N > 9) {
n = N--;
while (--n) {
a[n] = x % n;
x = 10 * a[n-1] + x/n;
}
printf("%d", x);
}
printf( "\ndone\n" );
return 0;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Microsoft QuickC v2/IS.GIF Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

BIN
Microsoft QuickC v2/LC.PGM Normal file

Binary file not shown.

Binary file not shown.

BIN
Microsoft QuickC v2/LIB.EXE Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,138 @@
>>
>>contents
The NOTES.HLP file provides an easy way to add your own information to the
QC Advisor.
The NOTES.HLP file is a minimally formatted ASCII help file that appears
in the Help window whenever you press a "Notes" button. Press the Alt+F1
key to return from the NOTES.HLP file to the QC Advisor.
The NOTES.HLP file contains three parts:
Part Description
>>contents Appears when you select the "Notes" button on the
Table of Contents screen. This is the part of the
NOTES.HLP file that is now being displayed.
>>edit Appears when you select the "Notes" button on the
Keyboard Shortcuts screen.
>>index Appears when you select the "Notes" button on the
Index screen.
To change the contents of the NOTES.HLP file you must do the following:
1. Close the NOTES.HLP file if it is currently displayed in the
Help window.
2. Open the NOTES.HLP file with any editor (such as the QuickC
editor) to edit NOTES.HLP. Change anything in the file except
the file name "NOTES.HLP" and lines that begin with the ">>"
characters. These lines are links to the buttons in the QC
Advisor
3. Save your modified NOTES.HLP file as a normal ASCII file.
4. When you open NOTES.HLP with one of the "Notes" buttons in the
QC Advisor, you will see your additions and changes.
5. Press ALT+F1 to return to the QC Advisor.
To change the other parts of the QC Advisor such as the run-time library
help file QC.HLP or the graphics help file GRAPHICS.HLP, you will need to
use the HELPMAKE utility. This program is described in the QuickC Tool Kit
Reference book.
>>edit
The NOTES.HLP file provides an easy way to add your own information to the
QC Advisor.
The NOTES.HLP file is a minimally formatted ASCII help file that appears
in the Help window whenever you press a "Notes" button. Press the Alt+F1
key to return from the NOTES.HLP file to the QC Advisor.
The NOTES.HLP file contains three parts:
Part Description
>>contents Appears when you select the "Notes" button on the
Table of Contents screen.
>>edit Appears when you select the "Notes" button on the
QuickC Keys screen. This is the part of the
NOTES.HLP file that is now being displayed.
>>index Appears when you select the "Notes" button on the
Index screen.
To change the contents of the NOTES.HLP file you must do the following:
1. Close the NOTES.HLP file if it is currently displayed in the
Help window.
2. Open the NOTES.HLP file with any editor (such as the QuickC
editor) to edit NOTES.HLP. Change anything in the file except
the file name "NOTES.HLP" and lines that begin with the ">>"
characters. These lines are links to the buttons in the QC
Advisor
3. Save your modified NOTES.HLP file as a normal ASCII file.
4. When you open NOTES.HLP with one of the "Notes" buttons in the
QC Advisor, you will see your additions and changes.
5. Press ALT+F1 to return to the QC Advisor.
To change the other parts of the QC Advisor such as the run-time library
help file QC.HLP or the graphics help file GRAPHICS.HLP, you will need to
use the HELPMAKE utility. This program is described in the QuickC Tool Kit
Reference book.
>>index
The NOTES.HLP file provides an easy way to add your own information to the
QC Advisor.
The NOTES.HLP file is a minimally formatted ASCII help file that appears
in the Help window whenever you press a "Notes" button. Press the Alt+F1
key to return from the NOTES.HLP file to the QC Advisor.
The NOTES.HLP file contains three parts:
Part Description
>>contents Appears when you select the "Notes" button on the
Table of Contents screen.
>>edit Appears when you select the "Notes" button on the
Keyboard Shortcuts screen.
>>index Appears when you select the "Notes" button on the
Index screen. This is the part of the NOTES.HLP
file that is now being displayed.
To change the contents of the NOTES.HLP file you must do the following:
1. Close the NOTES.HLP file if it is currently displayed in the
Help window.
2. Open the NOTES.HLP file with any editor (such as the QuickC
editor) to edit NOTES.HLP. Change anything in the file except
the file name "NOTES.HLP" and lines that begin with the ">>"
characters. These lines are links to the buttons in the QC
Advisor
3. Save your modified NOTES.HLP file as a normal ASCII file.
4. When you open NOTES.HLP with one of the "Notes" buttons in the
QC Advisor, you will see your additions and changes.
5. Press ALT+F1 to return to the QC Advisor.
To change the other parts of the QC Advisor such as the run-time library
help file QC.HLP or the graphics help file GRAPHICS.HLP, you will need to
use the HELPMAKE utility. This program is described in the QuickC Tool Kit
Reference book.


Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1165
Microsoft QuickC v2/LIFE.C Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
PROJ =LIFE
DEBUG =1
CC =qcl
CFLAGS_G =
CFLAGS_D =/Od /Gi$(PROJ).mdt /Zi /Zr
CFLAGS_R =/O /DNDEBUG
CFLAGS =$(CFLAGS_G) $(CFLAGS_D)
LFLAGS_G =/NOI
LFLAGS_D =/NOI /CO
LFLAGS_R =
LFLAGS =$(LFLAGS_G) $(LFLAGS_D)
RUNFLAGS =
OBJS_EXT =
LIBS_EXT =
all: $(PROJ).exe
life.obj: life.c
tools.obj: tools.c
$(PROJ).exe: life.obj tools.obj $(OBJS_EXT)
echo >NUL @<<$(PROJ).crf
life.obj +
tools.obj +
$(OBJS_EXT)
$(PROJ).exe
$(LIBS_EXT);
<<
ilink -a -e "link $(LFLAGS) @$(PROJ).crf" $(PROJ)
run: $(PROJ).exe
$(PROJ) $(RUNFLAGS)

Binary file not shown.

Binary file not shown.

BIN
Microsoft QuickC v2/ME.KEY Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1055
Microsoft QuickC v2/NTV Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,243 @@
Packing List for Microsoft QuickC (R) with QuickAssembler, Version 2.01
5.25" Disk Set
Copyright (c) Microsoft Corporation, 1986, 1989
DISK 1 : QuickAssembler / QuickC Setup
Files Description
----- -----------
packing.lst Packing list (this file)
setup.exe Setup program for QuickC (R) with QuickAssembler
readme.doc Release notes for QuickC (R) with QuickAssembler
helpmake.exe Creates and customizes help files
msherc.com TSR -- supports Hercules card graphics
fixshift.com Fixes BIOS bug for some Compaq and other keyboards
dospatch\patch320.doc Patch files for MS-DOS 3.20 and PC-DOS 3.20
dospatch\setrhs.exe " -- Read the .DOC files for details
dospatch\rmrhs.exe ""
dospatch\stkpat.bat ""
dospatch\stkpat.scr ""
dospatch\patch87.doc ""
dospatch\patch87.exe ""
samples\samples.doc Sample C programs
samples\grdemo.c " -- Read SAMPLES.DOC for details
samples\grdemo.mak ""
samples\menu.c ""
samples\menu.h ""
samples\turtle.c ""
samples\turtle.h ""
samples\life.c ""
samples\tools.c ""
samples\tools.h ""
samples\life.mak ""
samples\crlf.c ""
DISK 2 : Learning the QuickC Integrated Environment
Files Description
----- -----------
learn.com On-line tutorial and introduction to QuickC (R)
lc.pgm Tutorial support files
qccbt.ctx ""
qccbt.scn ""
qccbt.sob ""
link.exe Special linker for Windows and OS/2 developers
DISK 3 : Integrated Development Environment 1
Files Description
----- -----------
qc.exe QuickC (R) integrated programming environment
qc.ini Default .INI file for QuickC (R)
DISK 4 : Integrated Development Environment 2
Files Description
----- -----------
qcc.ovl QuickC (R) overlay for the integrated environment
c1.err Compiler error messages for QC and QCL
nmake.exe Stand-alone program maintenance utility
include\assert.h Include files
include\bios.h " -- Read the beginning of each file for details
include\conio.h ""
include\ctype.h ""
include\direct.h ""
include\dos.h ""
include\errno.h ""
include\fcntl.h ""
include\float.h ""
include\graph.h ""
include\io.h ""
include\limits.h ""
include\malloc.h ""
include\math.h ""
include\memory.h ""
include\pgchart.h ""
include\process.h ""
include\search.h ""
include\setjmp.h ""
include\share.h ""
include\signal.h ""
include\stdarg.h ""
include\stddef.h ""
include\stdio.h ""
include\stdlib.h ""
include\string.h ""
include\time.h ""
include\varargs.h ""
include\sys\locking.h ""
include\sys\stat.h ""
include\sys\timeb.h ""
include\sys\types.h ""
include\sys\utime.h ""
DISK 5 : Utilities
Files Description
----- -----------
crlf.exe Removes CTRL characters and inserts CR/LFs
link.exe Linker
ilink.exe Incremental linker
ilinkstb.ovl Ilink overlay
lib.exe Library maintenance utility
errors.hlp Help on error messages
qcc.dat Data file used by QC environment
mouse.com Microsoft mouse driver - version 6.24a
mkkey.exe Creates customized keyboard command files
brief.key Keyboard files
emacs.key ""
epsilon.key ""
me.key ""
qc.key ""
DISK 6 : Microsoft Quick Advisor
Files Description
----- -----------
qc.hlp Help on C and library functions
DISK 7 : Command-Line Compiler
Files Description
----- -----------
qccom.exe Command-line compiler
qcl.exe Driver for command-line compiler
qcl.hlp Help on QCL
cl.err Error messages for QCL and QC
graphics.hlp Help on graphics functions
DISK 8 : Libraries 1
Files Description
----- -----------
slibc.lib Library for small model
slibfp.lib Floating-point math library (small model)
svarstck.obj Small model competing heap/stack object file
mlibc.lib Library for medium model
mlibfp.lib Floating-point math library (medium model)
mvarstck.obj Medium model competing heap/stack object file
DISK 9 : Libraries 2
Files Description
----- -----------
binmode.obj Changes default file I/O mode from text to binary
setargv.obj Allows wild cards in command-line arguments
rmfixup.obj Removes interrupts; forces co-processor math
dbused.obj Needed when linking with C 5.1 OS/2 libraries
em.lib FP math library for software emulation of 8087
libh.lib General helper library
graphics.lib Low-level graphics library
pgchart.lib Presentation graphics library
clibc.lib Library for compact model
clibfp.lib Floating-point math library (compact model)
cvarstck.obj Compact model competing heap/stack object file
DISK 10 : Libraries 3 / Fonts
Files Description
----- -----------
87.lib FP math library for 8087 co-processor
llibc.lib Library for large model
llibfp.lib Floating-point math library (large model)
lvarstck.obj Large model competing heap/stack object file
font\courb.fon Font files
font\helvb.fon ""
font\modern.fon ""
font\roman.fon ""
font\script.fon ""
font\tmsrb.fon ""
notes.hlp User-defined help file
DISK 11 : QuickAssembler 1
Files Description
----- -----------
qas.ovl QuickAssembler overlay
samples\qasample.doc Sample C and Assembler programs
samples\filedemo.mak " -- Read QASAMPLE.DOC for details
samples\filedemo.c ""
samples\file.asm ""
samples\mathdemo.mak ""
samples\mathdemo.c ""
samples\math.asm ""
samples\miscdemo.mak ""
samples\miscdemo.asm ""
samples\misc.asm ""
samples\common.asm ""
samples\demo.h ""
samples\demo.inc ""
samples\chrtdemo.c ""
samples\chrtdemo.h ""
samples\chrtsupt.c ""
samples\chrtopt.c ""
samples\chrtdemo.mak ""
DISK 12 : QuickAssembler 2
Files Description
----- -----------
qa.hlp Help on the QuickAssembler - part 1 of 2
DISK 13 : QuickAssembler 3
Files Description
----- -----------
qa1.hlp Help on the QuickAssembler - part 2 of 2
qcenv.hlp Help on the QuickC (R) environment

Binary file not shown.

BIN
Microsoft QuickC v2/QA.HLP Normal file

Binary file not shown.

BIN
Microsoft QuickC v2/QA1.HLP Normal file

Binary file not shown.

BIN
Microsoft QuickC v2/QAS.OVL Normal file

Binary file not shown.

BIN
Microsoft QuickC v2/QC.EXE Normal file

Binary file not shown.

BIN
Microsoft QuickC v2/QC.HLP Normal file

Binary file not shown.

BIN
Microsoft QuickC v2/QC.INI Normal file

Binary file not shown.

BIN
Microsoft QuickC v2/QC.KEY Normal file

Binary file not shown.

BIN
Microsoft QuickC v2/QCC.DAT Normal file

Binary file not shown.

BIN
Microsoft QuickC v2/QCC.OVL Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Microsoft QuickC v2/QCL.EXE Normal file

Binary file not shown.

View File

@ -0,0 +1,77 @@
QUICK C COMPILER AND ASSEMBLER OPTIONS
-MEMORY MODEL-
/AT tiny model (.COM)
/AS small model (default)
/AC compact model
/AM medium model
/AL large model
-OPTIMIZATION-
/O enable optimization (same as /Ot)
/Od disable optimizations
/Ol enable loop optimizations
/Ox enable optimization (same as /Otl)
/Ot enable optimization
-CODE GENERATION-
/G0 8086 instructions (default)
/G2 286 instructions
/Gc Pascal style function calls
/Gi incremental compilation
/Gs no stack checking
/Gt[number] data size threshold
-OUTPUT FILES-
/Fb[bound executable file]
/Fe<executable file>
/Fm[map file]
/Fo<object file>
-C PREPROCESSOR-
/C don't strip comments
/D<name>[=text] define macro
/E preprocess to stdout
/EP same as /E but no #line
/I<name> add #include path
/P preprocess to file
/U<name> remove predefined macro
/u remove all predefined macros
/X ignore "standard places"
-C LANGUAGE-
/Za disable extensions
/Ze enable extensions (default)
/Zl remove default library info
/Zp pack structures
/Zr enable pointer checking
/Zs syntax check only
-DEBUGGING-
/Zd line number information
/Zi symbolic debugging information
-FLOATING POINT-
/FPi inline with emulator (default)
/FPi87 inline with 8087
-MISCELLANEOUS-
/c compile or assemble only, no link
/v verbose messages
/W<number> warning level
/w equivalent to /W0
-LINKING-
/F <hex_number> stack size (hex. bytes)
/Lc link compatibility mode executable
/Li incremental linking
/Lr link compatibility mode executable
/Lp link protect mode executable
/link [linker_options_and_libraries]
-ASSEMBLY LISTING-
/Fl<name> generate listing file
/l listing file with default name
/Sa list all lines in macros
/Sd create pass 1 listing
/Se editor-oriented listing
/Sn omit symbol table from listing
/Sq line-number index in listing
/Sx omit listing of false conditionals
-MISCELLANEOUS ASSEMBLER OPTIONS-
/a place segments in alphabetical order
/Cu convert all names to uppercase
/Cx preserve case of externals
/Cl preserve case of all symbols
/P1 one-pass assembly
/s place segments in order they appear
/t no messages if assembly successful

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,140 @@
/* File: CHRTDEMO.H
*
* Common definitions for major modules of CHRTDEMO.
*/
/* --- For graphics adaptors that are color capable: --- */
#define C_INPUTCOLOR 11 /* Color for data input */
#define C_HILITECOLOR 10 /* Color for first-letter highlights */
#define C_FORMCOLOR 15 /* Color for screen form lines and help */
#define C_TITLECOLOR 15 /* Color for QuickCHART title */
#define C_ERRORCOLOR 14 /* Color for error lines */
#define C_INFOCOLOR 7 /* Color non-input data on screen */
/* --- For graphics adaptors that are not color capable: --- */
#define M_INPUTCOLOR 7 /* Color for data input */
#define M_HILITECOLOR 15 /* Color for first-letter highlights */
#define M_FORMCOLOR 7 /* Color for screen form lines and help */
#define M_TITLECOLOR 15 /* Color for QuickCHART title */
#define M_ERRORCOLOR 15 /* Color for error lines */
#define M_INFOCOLOR 7 /* Color non-input data on screen */
/* Define macros to determine whether the graphics adaptor is color-capable. */
#define ismono(m) ( ((m) == _MRESNOCOLOR) || ((m) == _HRESBW) || \
((m) == _HERCMONO) || ((m) == _ERESNOCOLOR) || \
((m) == _VRES2COLOR) )
#define iscolor(m) (!ismono(m))
/* ASCII codes for commonly used control functions. */
#define BEEP 7
#define ESCAPE 27
/* Constant limits. */
#define MAXVALUES 12
#define MAXSERIES 4
/* Constants that identify typefaces to ChooseFont. */
enum tagTypeFace
{
COURIER,
HELV,
TMS_RMN,
MODERN,
SCRIPT,
ROMAN
};
typedef enum tagBool { FALSE, TRUE } BOOL;
/* Variables used to track control and screen position. */
struct SCREENINFO
{
int top; /* Row under top form line */
int bot; /* Row above bottom form line */
int mid; /* Middle line of form */
int help; /* Line number of help line */
int mode; /* Current screen mode */
int xMax;
int yMax;
BOOL fColor;
};
/* This variable holds either the constants #defined for color
* graphics adaptors (those that are formed: C_xxxxxCOLOR) or those
* #defined for monochrome graphics adaptors (those that are formed:
* M_xxxxxCOLOR). They do NOT control the color of the presentation
* graphics -- just the color of the menus and prompts.
*/
struct tagColor
{
short InputColor; /* Color for input requests */
short HiliteColor; /* Color for prompt highlights */
short FormColor; /* Color for input forms/menus */
short TitleColor; /* Color for titles */
short ErrorColor; /* Color for error messages */
short InfoColor; /* Color for informations msgs. */
};
/* Declaration of functions in CHRTSUPT.C */
int BlankMenu( char *pchTitle, char *pchChoice1, char *pchChoice2 );
void ClrForm( void );
void ClrHelp( void );
void ErrorMsg( char *pchMsg );
void Help( char *pchMsg, short sColor );
char InputCh( char *pchPrompt, char *pchAccept );
int InputInt( char *pchPrompt, int iOld, int iMin, int iMax );
float InputFloat( char *pchPrompt, float fOld );
char *InputStr( char *pchPrompt, char *pchOld );
BOOL InRange( int Value, int iMin, int iMax );
int Menu( char *pszMenuList[] );
void PopTitle( void );
void PushTitle( char *pchOldTitle );
void PrintAt(int row, int column, char far * lpszString, short sColor);
void PrintChar(int row, int column, char cChar, short sColor);
void SetDisplayColors( void );
void SprintAt( int iRow, int iCol, char * szFmt, ... );
void WrtForm( int yBot );
/* Declarations of functions in CHRTDEMO.C */
void ChartOptions( void );
void ChartType( void );
void ClearData( BOOL fConfirm );
void DefaultData( short iType, short iStyle, BOOL fClear );
int FindVideoMode( struct videoconfig vc );
void Initialize( void );
int main( void );
void MainMenu( void );
void ResetOptions( void );
void Demo( void );
BOOL SetGraphMode( int mode );
void ShowError( int iErr );
void ShowChartData( void );
int ShowAxisType( int iRow, int iCol, axistype theAxis );
int ShowLegendType( int iRow, int iCol, legendtype theLegend );
void ShowSampleData( void );
int ShowTitleType( int iRow, int iCol, titletype theTitle );
int ShowWindowType( int iRow, int iCol, windowtype theWindow );
int ViewChart( void );
/* Declarations of functions in CHRTOPT.C */
void Axes( void );
void Axis( axistype *pat );
void AxisRange( axistype *pat );
void AxisScale( axistype *pat );
void AxisTics( axistype *pat );
void Border( windowtype *pwt );
void ChangeTypeface( void );
void ChooseFont( int WhichFont, int Height );
void ChartWindow( void );
void DataWindow( void );
void FontOptions( void );
void Justify( titletype *ptt );
void Legend( void );
void LegendPlace( void );
void ScreenMode( void );
void TitleOpt( titletype *ptt );
void Titles( void );
void Windows( void );
void WindowSize( windowtype *pwt );

View File

@ -0,0 +1,45 @@
PROJ =CHRTDEMO
DEBUG =1
CC =qcl
AS =masm
CFLAGS_G = /AS /W1 /Ze
CFLAGS_D = /Zi /Zr /Gi$(PROJ).mdt /Od
CFLAGS_R = /O /Ot /DNDEBUG
CFLAGS =$(CFLAGS_G) $(CFLAGS_D)
AFLAGS_G =/Cx /P1
AFLAGS_D =/Zi
AFLAGS_R =/DNDEBUG
AFLAGS =$(AFLAGS_G) $(AFLAGS_D)
LFLAGS_G = /CP:0xfff /NOI /SE:0x80 /ST:0x800
LFLAGS_D = /CO
LFLAGS_R =
LFLAGS =$(LFLAGS_G) $(LFLAGS_D)
RUNFLAGS =
OBJS_EXT =
LIBS_EXT =
.asm.obj: ; $(AS) $(AFLAGS) -c $*.asm
all: $(PROJ).EXE
chrtdemo.obj: chrtdemo.c
chrtopt.obj: chrtopt.c
chrtsupt.obj: chrtsupt.c
$(PROJ).EXE: chrtdemo.obj chrtopt.obj chrtsupt.obj $(OBJS_EXT)
echo >NUL @<<$(PROJ).crf
chrtdemo.obj +
chrtopt.obj +
chrtsupt.obj +
$(OBJS_EXT)
$(PROJ).EXE
$(LIBS_EXT);
<<
ilink -a -e "link $(LFLAGS) @$(PROJ).crf" $(PROJ)
run: $(PROJ).EXE
$(PROJ) $(RUNFLAGS)

View File

@ -0,0 +1,917 @@
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <graph.h>
#include <pgchart.h>
#include "chrtdemo.h"
/* Structures for system configuration and chart environment. */
extern struct videoconfig vc;
extern chartenv ce;
/* Variable used to track control and screen position. */
extern struct SCREENINFO si;
/* Colors of menus and prompts. */
extern struct tagColor co;
/* Arrays of strings used by the Menu function. The first string is the
* menu title. The next non-null strings are the menu selections. A null
* string indicates the end of the list.
*/
char *pszAxes[] =
{ "Axis", "X Axis", "Y Axis", "" };
char *pszAxis[] =
{ "? Options", "Grid", "Axis Title", "Color",
"Range Type", "Scale", "Tic Marks", "" };
char *pszAuto[] =
{ "Auto", "Auto", "Manual", "" };
char *pszBorder[] =
{ "Type", "Color", "Style", "" };
char *pszChartWindow[] =
{ "Chart", "Size", "Color (Background)", "Border", "" };
char *pszDataWindow[] =
{ "Data", "Color (Background)", "Border", "" };
char * pszFontOpt[] =
{ "Font Options", "Change Typeface", "Set Character Size", "" };
char *pszJustify[] =
{ "Justify", "Left", "Center", "Right", "" };
char *pszLegendWindow[] =
{ "Options", "Place", "Text Color", "Size", "Color (Background)",
"Border", "" };
char *pszPlace[] =
{ "Place", "Right", "Bottom", "Overlay", "" };
char *pszScale[] =
{ "Scale", "Low (Min)", "High (Max)", "Scale Factor", "Title", "" };
char *pszSize[] =
{ "Size", "Top", "Left", "Bottom", "Right", "" };
char *pszTic[] =
{ "Tic Type", "Interval", "Format", "Decimals", "" };
char *pszTitleOpt[] =
{ "", "Text", "Color", "Justify", "" };
char *pszTitles[] =
{ "Title", "Main Title", "Sub Title", "" };
char *pszTypeface[] =
{ "Type Faces", "Courier", "Helv", "Tms Rmn", "Modern", "Script",
"Roman", "None", "" };
char *pszWindows[] =
{ "Window", "Chart Window", "Data Window", "" };
/* Axes - Selects X or Y axis.
*
* Params: none
*/
void Axes()
{
int iChoice;
static axistype *patAxis[2] = { &ce.xaxis, &ce.yaxis };
/* Get menu choice and call appropriate axis Menu. */
PushTitle( pszAxes[0] );
Help( "Choose 'X' or 'Y' Axis", co.InputColor );
while( (iChoice = Menu( pszAxes )) != ESCAPE )
{
/* Modify axis title, depending on choice. */
pszAxis[0][0] = (--iChoice == 0) ? 'X' : 'Y';
/* Obtain axis information for appropriate axis. */
Axis( patAxis[iChoice] );
}
PopTitle();
}
/* Axis - Selects axis options.
*
* Params: pat - Pointer to axistype variable
*/
void Axis( axistype *pat )
{
int iChoice;
PushTitle( pszAxis[0] );
while( (iChoice = Menu( pszAxis )) != ESCAPE )
{
/* Get Axis option. */
switch( iChoice )
{
case 1:
/* Grid or not? */
iChoice = BlankMenu( "Grid", "Grid", "No Grid" );
switch( iChoice )
{
case 1:
/* If yes, set grid flag and get the grid style. */
pat->grid = TRUE;
Help( "Enter a number in the range 0-10.",
co.InputColor );
pat->gridstyle =
InputInt( "Grid Style? ", pat->gridstyle, 0, 10 );
break;
case 2:
/* If no, clear grid flag. */
pat->grid = FALSE;
}
PopTitle();
break;
case 2:
/* Select axis title options. */
pszTitleOpt[0] = "Axis Title";
TitleOpt( &pat->axistitle );
break;
case 3:
/* Select color. */
Help( "Enter a number in the range 0-15.", co.InputColor );
pat->axiscolor =
InputInt( "Axis Color? ", pat->axiscolor, 0, 15 );
break;
case 4:
/* Get the axis range. */
AxisRange( pat );
break;
case 5:
/* Get the axis scale. */
AxisScale( pat );
break;
case 6:
/* Get axis tic mark options. */
AxisTics( pat );
break;
}
}
PopTitle();
}
/* AxisRange - Selects range for an axis.
*
* Params: pat - pointer to axistype variable
*/
void AxisRange( axistype *pat )
{
int iChoice;
iChoice = BlankMenu( "Range Type", "Normal", "Log" );
switch( iChoice )
{
case 1:
/* Set range type to linear. */
pat->rangetype = _PG_LINEARAXIS;
break;
case 2:
/* Set range type to log, then query for log base. */
pat->rangetype = _PG_LOGAXIS;
Help( "Enter a value greater than or equal 2.", co.InputColor );
pat->logbase = InputInt( "Log base? ", (int)pat->logbase, 2, 0 );
break;
}
PopTitle();
}
/* AxisScale - Selects scale options for an axis.
*
* Params: pat - pointer to axistype variable
*/
void AxisScale( axistype *pat )
{
int iChoice;
PushTitle( pszAuto[0] );
iChoice = Menu( pszAuto );
switch( iChoice )
{
case 1:
/* Set AutoScale flag. */
pat->autoscale = TRUE;
break;
case 2:
/* Clear AutoScale flag and get scale options. */
pat->autoscale = FALSE;
PushTitle( pszScale[0] );
while( (iChoice = Menu( pszScale )) != ESCAPE )
{
switch( iChoice )
{
case 1:
/* Query for scale minimum. */
Help( "Enter the range minimum value.", co.InputColor );
pat->scalemin =
InputInt( "Minimum? ", pat->scalemin, 1, 0 );
break;
case 2:
/* Query for scale maximum. */
Help( "Enter the range maximum value.", co.InputColor );
pat->scalemax =
InputInt( "Maximum? ", pat->scalemax, 1, 0 );
break;
case 3:
/* Query for scale factor. */
Help( "Enter scale factor (must be 1 or greater).",
co.InputColor );
pat->scalefactor =
InputInt( "Scale Factor? ", pat->scalefactor,
1, 0 );
break;
case 4:
/* Modify scale title, then use menu to get
* title options.
*/
pszTitleOpt[0] = "Scale Title";
TitleOpt( &pat->scaletitle );
}
}
PopTitle();
}
PopTitle();
}
/* AxisTics - Selects tic options for an axis.
*
* Params: pat - pointer to axistype variable
*/
void AxisTics( axistype *pat )
{
int iChoice;
PushTitle( pszTic[0] );
while( (iChoice = Menu( pszTic )) != ESCAPE )
{
switch( iChoice )
{
case 1:
/* Query for tic interval. */
Help( "Enter distance in data units.", co.InputColor );
pat->ticinterval =
InputFloat( "Distance between tic marks? ",
pat->ticinterval );
pat->autoscale = FALSE;
break;
case 2:
/* Query for tic format. */
iChoice = BlankMenu( "Tic Format", "Normal", "Log" );
if( iChoice != ESCAPE )
pat->ticformat = iChoice;
break;
case 3:
/* Query for number of decimal places per tic. */
pat->ticdecimals =
InputInt( "Enter decimal places (0 to 9). ",
pat->ticdecimals, 0, 9 );
pat->autoscale = FALSE;
break;
}
}
PopTitle();
}
/* Border - Specifies border information for a window.
*
* Params: pwt - Pointer to windowtype variable
*/
void Border( windowtype *pwt )
{
int iChoice;
/* Ask whether a border is wanted. */
iChoice = BlankMenu( "Border", "Border", "No Border" );
switch( iChoice )
{
case 1:
/* If border, set Border flag and query for border options. */
pwt->border= TRUE;
PushTitle( pszBorder[0] );
while( (iChoice = Menu( pszBorder )) != ESCAPE )
{
switch( iChoice )
{
case 1:
/* Query for border color. */
Help( "Enter a color in the range 0-15.",
co.InputColor );
pwt->bordercolor =
InputInt( "Border color? ",
pwt->bordercolor, 0, 15 );
break;
case 2:
/* Query for border style. */
Help( "Enter a style in the range 0-10.", co.InputColor );
pwt->borderstyle =
InputInt( "Border style? ",
pwt->borderstyle, 0, 10 );
}
}
PopTitle();
break;
case 2:
/* If no border, clear Border flag. */
pwt->border= FALSE;
}
PopTitle();
}
/* ChangeTypeface - Allow the user to specify a new type face.
*
* Params: None
*/
void ChangeTypeface()
{
int iChoice;
struct _fontinfo fd;
static BOOL FontsRegistered = FALSE; /* state of font package */
/* Get menu choice and call appropriate axis Menu. */
PushTitle( pszFontOpt[0] );
Help( "Choose one of the type faces listed.", co.InputColor );
if( (iChoice = Menu( pszTypeface )) != ESCAPE )
{
/* If the user wants the system font, unregister the other fonts. */
if( iChoice == 7 )
{
_unregisterfonts();
FontsRegistered = FALSE;
}
/* If the user wants any font but the system font, make sure the
* fonts are registered.
*/
else
{
if( !FontsRegistered )
{
if( _registerfonts( "*.FON" ) < 0 )
{
ErrorMsg( "Unable to register fonts" );
return;
}
else
FontsRegistered = TRUE; /* Reset the state to registered */
}
/* Get the previous font settings */
_getfontinfo( &fd );
ChooseFont( iChoice - 1, fd.pixheight );
}
}
PopTitle();
}
/* ChooseFont - Chooses a font from the font library.
*
* Params: WhichFont - A member of the set [COURIER, HELV, TMS_RMN,
* MODERN, SCRIPT, ROMAN]
* Height - The desired height of the text (in pixels)
*/
void ChooseFont( int WhichFont, int Height )
{
static char *FontIds[] =
{
"courier", "helv", "tms rmn", "modern", "script", "roman"
};
char SetCommand[21];
/* Construct the command to send to _setfont. */
sprintf( SetCommand, "t'%s'h%dw0b", FontIds[WhichFont], Height );
if( _setfont( SetCommand ) )
{
_outtext( "Could not set font to " );
_outtext( FontIds[WhichFont] );
_outtext( "." );
getch();
}
}
/* ChartWindow - Gets chart window information.
*
* Params: None
*/
void ChartWindow()
{
int iChoice;
PushTitle( pszChartWindow[0] );
while( (iChoice = Menu( pszChartWindow )) != ESCAPE )
{
/* Get window options. */
switch( iChoice )
{
case 1:
/* Get window size. */
WindowSize( &ce.chartwindow );
break;
case 2:
/* Query for background color. */
Help( "Enter a number in the range 0-15", co.InputColor );
ce.chartwindow.background =
InputInt( "Background Color? ", ce.chartwindow.background,
0, 15 );
break;
case 3:
/* Get border options. */
Border( &ce.chartwindow );
}
}
PopTitle();
}
/* DataWindow - Geta data window information.
*
* Params: None
*/
void DataWindow()
{
int iChoice;
PushTitle( pszDataWindow[0] );
while( (iChoice = Menu( pszDataWindow )) != ESCAPE )
{
/* Get data window menu options. */
switch( iChoice )
{
case 1:
/* Query for background color. */
Help( "Enter a number in the range 0-15", co.InputColor );
ce.datawindow.background =
InputInt( "Background Color? ",
ce.datawindow.background,
0, 15 );
break;
case 2:
/* Get border options. */
Border( &ce.datawindow );
break;
}
}
PopTitle();
}
/* FontOptions - Allows the user to modify the font used for display.
*
* Params: None
*/
void FontOptions()
{
int iChoice;
int iTypeSize;
int iFaceIndex;
struct _fontinfo fd;
/* Get menu choice and call appropriate axis Menu. */
PushTitle( pszFontOpt[0] );
while( (iChoice = Menu( pszFontOpt )) != ESCAPE )
{
/* Get the current font information. */
_getfontinfo( &fd );
switch( iChoice )
{
/* Change Typeface. */
case 1:
ChangeTypeface();
break;
/* Change Type Size. */
case 2:
iTypeSize = InputInt( "Enter a type size. ", fd.pixheight,
8, 128 );
for( iFaceIndex = 0; iFaceIndex < 6; ++iFaceIndex )
if( !strcmpi( fd.facename, pszTypeface[iFaceIndex + 1] ) )
break;
ChooseFont( iFaceIndex, iTypeSize );
break;
default:
break;
}
}
PopTitle();
}
/* Justify - Gets title justification option.
*
* Params: Pointer to titletype variable
*/
void Justify( titletype *ptt )
{
int iChoice;
PushTitle( pszJustify[0] );
iChoice = Menu( pszJustify );
switch( iChoice )
{
/* Set justification. */
case 1:
case 2:
case 3:
ptt->justify = iChoice;
}
PopTitle();
}
/* Legend - Asks whether a legend is desired, and if so, gets
* legend options.
*
* Params: None
*/
void Legend()
{
int iChoice;
/* Is legend desired? */
iChoice = BlankMenu( "Legend", "Legend", "No Legend" );
switch( iChoice )
{
case 1:
/* If legend, set legend flag and get options. */
ce.legend.legend = TRUE;
PushTitle( pszLegendWindow[0] );
do
{
iChoice = Menu( pszLegendWindow );
switch( iChoice )
{
case 1:
/* Get legend place. */
LegendPlace();
break;
case 2:
/* Query for legend color. */
Help( "Enter a number in the range 0-15.", co.InputColor );
ce.legend.textcolor =
InputInt( "Text color? ",
ce.legend.textcolor,
0, 15 );
break;
case 3:
/* Get auto or manual sizing. */
PushTitle( "Auto Legend" );
iChoice = Menu( pszAuto );
/* Set or clear the autosize flag. If manual
* sizing was selected, get legend size.
*/
switch( iChoice )
{
case 1:
ce.legend.autosize = TRUE;
break;
case 2:
ce.legend.autosize = FALSE;
WindowSize( &ce.legend.legendwindow );
}
PopTitle();
break;
case 4:
/* Query for background color. */
Help( "Type a number in the range 0-15.", co.InputColor );
ce.legend.legendwindow.background =
InputInt( "Background color? ",
ce.legend.legendwindow.background,
0, 15 );
break;
case 5:
/* Get border options for legend window. */
Border( &ce.legend.legendwindow );
}
} while( iChoice != ESCAPE );
PopTitle();
break;
case 2:
/* If no legend wanted, clear flag. */
ce.legend.legend = FALSE;
}
PopTitle();
}
/* LegendPlace - Gets legend placement option.
*
* Params: None
*/
void LegendPlace()
{
int iChoice;
/* Get legend placement. */
PushTitle( pszPlace[0] );
iChoice = Menu( pszPlace );
switch( iChoice )
{
case 1:
ce.legend.place = _PG_RIGHT;
break;
case 2:
ce.legend.place = _PG_BOTTOM;
break;
case 3:
ce.legend.place = _PG_OVERLAY;
}
PopTitle();
}
/* ScreenMode - Gets a new screen mode.
*
* Params: None
*/
void ScreenMode()
{
int iMode, i;
char szTmp[80], szHlp[80];
static int iLegal[5][11] =
{
{ 3, 4, 5, 6 },
{ 4, 4, 5, 6, 64 },
{ 4, 4, 5, 6, 19 },
{ 7, 4, 5, 6, 13, 14, 15, 16 },
{ 10, 4, 5, 6, 13, 14, 15, 16, 17, 18, 19 }
};
int iAdaptor;
PushTitle( "Screen Mode" );
/* Show appropriate help line for adaptor. */
switch( vc.adapter )
{
case _HGC:
PopTitle();
return;
case _CGA:
iAdaptor = 0;
break;
case _OCGA:
iAdaptor = 1;
break;
case _MCGA:
iAdaptor = 2;
break;
case _EGA:
case _OEGA:
if( vc.adapter == _MONO )
{
PopTitle();
return;
}
else
iAdaptor = 3;
break;
case _VGA:
case _OVGA:
iAdaptor = 4;
break;
}
/* Form the help line (which gives the choices legal for
* the adaptor sensed in the user's machine).
*/
for( iMode = 0, szHlp[0] = '\0'; iMode <= iLegal[iAdaptor][0]; ++iMode )
{
if( iMode == 0 )
strcpy( szTmp, "Enter " );
else if( iMode < iLegal[iAdaptor][0] )
sprintf( szTmp, "%d, ", iLegal[iAdaptor][iMode] );
else
sprintf( szTmp, "or %d", iLegal[iAdaptor][iMode] );
strcat( szHlp, szTmp );
}
WrtForm( 18 );
Help( szHlp, co.InputColor );
/* Query for screen mode. */
for( ;; )
{
iMode = InputInt( "Screen Mode? ", si.mode, 1, 64 );
for( i = 1; i <= iLegal[iAdaptor][0]; ++i ) /* Test legal values */
if( iMode == iLegal[iAdaptor][i] ) /* If a match is found */
break; /* Terminate for loop */
if( iMode == iLegal[iAdaptor][i] ) /* If it's a match, */
break; /* terminate do loop, */
else /* otherwise BEEP, and */
putchar( BEEP ); /* solicit correct data */
}
PopTitle();
if( SetGraphMode( iMode ) )
_setvideomode( _DEFAULTMODE );
else
ShowError( _PG_BADSCREENMODE );
/* Force rescaling of the chart by resetting the window
* rectangles for the chart and data windows to zero size.
*/
ce.chartwindow.x1 = ce.chartwindow.x2 = ce.chartwindow.y1 =
ce.chartwindow.y2 = 0;
ce.datawindow = ce.chartwindow;
}
/* TitleOpt - Gets title options.
*
* Params: ptt - Pointer to titletype variable
*/
void TitleOpt( titletype *ptt )
{
int iChoice;
PushTitle( pszTitleOpt[0] );
do
{
iChoice = Menu( pszTitleOpt );
switch( iChoice )
{
case 1:
/* Query for title text. */
Help( "70 characters maximum length.", co.InputColor );
InputStr( "Enter Text: ", ptt->title );
break;
case 2:
/* Query for title color color. */
Help( "Enter a number in the range 0-15.", co.InputColor );
ptt->titlecolor =
InputInt( "Title Color? ", ptt->titlecolor, 0, 15 );
break;
case 3:
/* Get justify option. */
Justify( ptt );
}
ClrHelp();
} while( iChoice != ESCAPE );
PopTitle();
}
/* Titles - Manages Main and Sub title menus.
*
* Params: None
*/
void Titles()
{
int iChoice;
PushTitle( pszTitles[0] );
do
{
iChoice = Menu( pszTitles );
switch( iChoice )
{
case 1:
/* Fix menu title and get options for main title. */
pszTitleOpt[0] = "MainTitle";
TitleOpt( &ce.maintitle );
break;
case 2:
/* Fix menu title and get options for subtitle. */
pszTitleOpt[0] = "Sub Title";
TitleOpt( &ce.subtitle );
}
} while( iChoice != ESCAPE );
PopTitle();
}
/* Windows - Selects chart or data window, and gets options for either.
*
* Params: None
*/
void Windows()
{
int iChoice;
PushTitle( pszWindows[0] );
do
{
/* Select window and get options for it. */
iChoice = Menu( pszWindows );
switch( iChoice )
{
case 1:
ChartWindow();
break;
case 2:
DataWindow();
}
} while( iChoice != ESCAPE );
PopTitle();
}
/* WindowSize - Gets coordinates for window location and size.
*
* Params: pwt - pointer to windowtype variable
*/
void WindowSize( windowtype *pwt )
{
int iChoice;
/* Get window size settings. */
PushTitle( pszSize[0] );
do
{
/* Query for top, bottom, left, or right of window. */
iChoice = Menu( pszSize );
switch( iChoice )
{
case 1:
Help( "Enter window top in pixels.", co.InputColor );
pwt->y1 = InputInt( "Top? ", pwt->y1, 0, si.yMax );
break;
case 2:
Help( "Enter window Left in pixels.", co.InputColor );
pwt->x1 = InputInt( "Left? ", pwt->x1, 0, si.xMax );
break;
case 3:
Help( "Enter window bottom in pixels.", co.InputColor );
pwt->y2 = InputInt( "Bottom? ", pwt->y2, 0, si.yMax );
break;
case 4:
Help( "Enter window right in pixels.", co.InputColor );
pwt->x2 = InputInt( "Right? ", pwt->x2, 0, si.xMax );
}
} while( iChoice != ESCAPE );
PopTitle();
}

View File

@ -0,0 +1,483 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <conio.h>
#include <graph.h>
#include <pgchart.h>
#include "chrtdemo.h"
/* Variables to manage menus. */
int cMenuLevel = 0; /* Current menu level */
char *szMenuTitles[10]; /* Stack of menu titles */
char *pszBlankMenu[4];
/* Variables used to track control and screen position. */
extern struct SCREENINFO si;
/* Colors of menus and prompts. */
extern struct tagColor co;
/* BlankMenu - Gets responses to two specified choices.
*
* Params: pchTitle - Menu title string
* pchChoice1 - Selection 1 string
* pchChoice2 - Selection 2 string
*
* Return: Number of choice, or ESCAPE
*/
int BlankMenu( char *pchTitle, char *pchChoice1, char *pchChoice2 )
{
int iChoice;
/* Initialize title and selections. */
pszBlankMenu[0] = pchTitle;
pszBlankMenu[1] = pchChoice1;
pszBlankMenu[2] = pchChoice2;
pszBlankMenu[3] = "\0";
PushTitle( pszBlankMenu[0]);
while( TRUE )
{
/* Accept only first letter of either selection, or ESC. */
iChoice = Menu( pszBlankMenu );
switch( iChoice )
{
case 1:
case 2:
case ESCAPE:
return iChoice;
}
}
}
/* ClrForm - Clears the center of the screen form.
*
* Params: None
*/
void ClrForm()
{
/* Set partial screen window and clear it, then reset full screen. */
_settextwindow( si.top, 1, si.bot, 80 );
_clearscreen( _GWINDOW );
_settextwindow( 1, 1, 25, 80 );
}
/* ClrHelp - Clears the current help line.
*
* Params: None
*/
void ClrHelp()
{
/* Decrement the help line counter and clear the line. */
_settextwindow( --si.help, 1, si.help, 80 );
_clearscreen( _GWINDOW );
_settextwindow( 1, 1, 25, 80 );
}
/* ErrorMsg - Displays an error message.
*
* Params: pchMsg - error message string
*/
void ErrorMsg( char *pchMsg )
{
/* Beep, set error color, and display error message and continue prompt. */
putch( BEEP );
Help( pchMsg, co.ErrorColor );
Help( "Press any key to continue.", co.ErrorColor );
/* Wait for keypress and clear help lines. */
getch();
ClrHelp();
ClrHelp();
}
/* Help - Displays a help line on the screen.
*
* Params: pchMsg - error message string
* sColor - color for message
*/
void Help( char *pchMsg, short sColor )
{
struct rccoord rcCursor;
/* Save current cursor position. */
rcCursor = _gettextposition();
/* Print out help line and increment Helpline position variable. */
PrintAt( si.help++, 5, pchMsg, sColor );
/* Restore cursor position. */
_settextposition( rcCursor.row, rcCursor.col );
}
/* InputCh - Prompts for and returns a character of input.
*
* Params: pchPrompt - Prompt string
* pchAccept - String of acceptable characters (case insensitive)
*
* Return: Character entered
*/
char InputCh( char *pchPrompt, char *pchAccept )
{
char chResponse;
/* Display prompt. */
PrintAt( si.mid, 10, pchPrompt, co.InputColor );
/* Loop until response is valid. */
while( TRUE )
{
chResponse = toupper( getch() );
/* Display and return if acceptable character, or beep if not. */
if( *strchr( pchAccept, chResponse) )
{
_settextcolor( co.InfoColor );
putch( chResponse );
return chResponse;
}
else
putch( BEEP );
}
}
/* InputInt - Prompts for and returns an integer value within a
* specified range.
*
* Params: pchPrompt - Prompt string
* iOld - Previous value
* iMin - Minimum value of range
* iMax - Maximum value of range
*
* Return: integer input by user
*/
int InputInt( char *pchPrompt, int iOld, int iMin, int iMax )
{
int i;
char szTmp[70];
/* Prompt for a string input and convert to an integer until a
* value in the specified range is given. Then return the value.
*/
do
{
InputStr( pchPrompt, itoa( iOld, szTmp, 10) );
i = atoi( szTmp );
} while( !InRange( i, iMin, iMax) );
return i;
}
/* InputFloat - Prompts for and returns a float value.
*
* Params: pchPrompt - Prompt string
* fOld - Previous value
*
* Return: float input by user
*/
float InputFloat( char *pchPrompt, float fOld )
{
char szTmp[70];
/* Prompt for a string input and convert to a float. */
sprintf( szTmp, "%f", fOld );
InputStr( pchPrompt, szTmp );
return atof( szTmp );
}
/* InputStr - Prompts for a string. Displays the previous string
* until the first character is given. Then replaces it with new
* entry.
*
* Params: pchPrompt - Prompt string
* pchOld - Charater buffer containing previous string; it
* must be long enough to hold new string
*
* Return: pointer to pchOld, which now contains new string
*/
char *InputStr( char *pchPrompt, char *pchOld )
{
char szTmp[81], ch;
int x = 5, y = si.mid;
/* Display prompt in center of form. */
ClrForm();
PrintAt( y, x, pchPrompt, co.InputColor );
x += strlen( pchPrompt );
/* Print the old value for reference. */
_outtext( pchOld );
_settextposition( y, x );
/* Wait for input. When received, clear old string. */
while( !(ch = kbhit()) )
;
memset( szTmp, ' ', 80 );
szTmp[80] = '\0';
PrintAt( y, x, szTmp, -1L );
/* Get new string. If string entered, return it. If null string
* (ENTER key pressed), return old value.
*/
_settextcolor( co.InfoColor );
_settextposition( y, x );
szTmp[0] = 70; /* Maximum length to be read */
cgets( szTmp );
if( szTmp[1] > 0 ) /* Are any characters read? */
{
strcpy( pchOld, &szTmp[2] );
return &szTmp[2];
}
else
{
_settextposition( y, x );
return pchOld;
}
}
/* InRange - Checks an integer to see if it is in a specified range.
*
* Params: iValue - Integer to check
* iMin - Minimum value of range
* iMax - Maximim value of range
*
* Return: TRUE if in range, FALSE if not
*/
BOOL InRange( int Value, int iMin, int iMax )
{
/* Check range and return true if valid, false if not. Note that
* (iMin >= iMax) is taken as a signal to check only the minimum
* value; there is no maximum.
*/
if( Value >= iMin )
if( (Value <= iMax) || (iMin >= iMax) )
return TRUE;
else
{
ErrorMsg( "Invalid value." );
return FALSE;
}
}
/* Menu - Draws menu on screen and returns choice number.
*
* Params: array of menu strings
*
* Return: number corresponding to the choice made from the menu
*/
int Menu( char *pszMenuList[] )
{
int iItem, cItem, yItem, x = 10;
char chResponse;
/* Count menu items. */
for( cItem = 1; *pszMenuList[cItem]; cItem++ )
;
--cItem;
/* Clear the form and print the items in the menu. */
WrtForm( 10 + cItem );
for( iItem = 1, yItem = 8; iItem <= cItem; iItem++, yItem++ )
{
PrintAt( yItem, x, pszMenuList[iItem], co.InputColor );
PrintChar( yItem, x, pszMenuList[iItem][0], co.HiliteColor );
}
++yItem;
/* Display prompt and help. */
if( strcmpi( pszMenuList[0], "main menu" ) ) /* If not the main menu */
Help( "Type the first letter of your selection or ESC to back up.",
co.InputColor );
else
Help( "Type the first letter of your selection or \"Q\" to quit.",
co.InputColor );
PrintAt( yItem, x += 5, "Choice? ", co.InfoColor );
x += 8;
/* Loop until a valid choice is made. Beep at invalid choices. */
while( TRUE )
{
_settextposition( yItem, x );
chResponse = toupper( getch() );
/* Back up for ESC. */
if( chResponse == 27 )
{
ClrHelp();
return ESCAPE;
}
/* Search first letters of choices for a match. If found, return
* choice and clear help line.
*/
for( iItem = 1; iItem <= cItem; iItem++ )
{
if( chResponse == toupper( pszMenuList[iItem][0]) )
{
putch( chResponse );
ClrHelp();
return iItem;
}
}
/* If we get here, no valid choice was found, so beep and repeat. */
putch( BEEP );
}
}
/* PopTitle - Pops a menu title from the menu stack.
*
* Params: None
*/
void PopTitle()
{
szMenuTitles[--cMenuLevel] = "";
}
/* PrintAt - Prints a string at the row/column coordinates
* specified, in the specified color.
*
* Params: row - row at which to begin output of string
* col - column at which to begin output of string
* lpszString - zero (null) terminated string
* sColor - color in which to output string (-1 if
* PrintAt should leave color alone)
*/
void PrintAt(int row, int column, char far * lpszString, short sColor)
{
if( sColor != -1L )
_settextcolor( sColor );
_settextposition( row, column );
_outtext( lpszString );
}
/* PrintChar - Prints a character at the row/column coordinates
* specified, in the specified color.
*
* Params: row - row at which to begin output of string
* col - column at which to begin output of string
* cChar - character to print
* sColor - color in which to output string (-1 if
* PrintChar should leave color alone)
*/
void PrintChar(int row, int column, char cChar, short sColor)
{
char szTiny[2];
szTiny[0] = cChar;
szTiny[1] = '\0';
PrintAt( row, column, szTiny, sColor );
}
/* PushTitle - Pushes a menu title on to the menu stack.
*
* Params: pchTitle - title string to push
*/
void PushTitle( char *pchTitle )
{
szMenuTitles[cMenuLevel++] = pchTitle;
}
/* SetDisplayColors - Set the colors to values appropriate to the display
* adaptor being used.
*
* Parms: None
*/
void SetDisplayColors()
{
if( ismono( si.mode ) )
{
co.InputColor = M_INPUTCOLOR;
co.HiliteColor = M_HILITECOLOR;
co.FormColor = M_FORMCOLOR;
co.TitleColor = M_TITLECOLOR;
co.ErrorColor = M_ERRORCOLOR;
co.InfoColor = M_INFOCOLOR;
}
else
{
co.InputColor = C_INPUTCOLOR;
co.HiliteColor = C_HILITECOLOR;
co.FormColor = C_FORMCOLOR;
co.TitleColor = C_TITLECOLOR;
co.ErrorColor = C_ERRORCOLOR;
co.InfoColor = C_INFOCOLOR;
}
}
/* SprintAt - Format a string, using sprintf() and output to screen
* using PrintAt.
*
* Parms: iRow - Row at which to begin display
* iCol - Column at which to begin display
* szFmt - Format string (see run-time library documentation for
* correct formation of a format string)
* ... - Variables to output
*/
void SprintAt( int iRow, int iCol, char * szFmt, ... )
{
char szTmp[81];
va_list Marker;
va_list saveMarker;
va_start( Marker, szFmt );
saveMarker = Marker;
vsprintf( szTmp, szFmt, Marker );
va_end( Marker );
PrintAt( iRow, iCol, szTmp, -1L );
}
/* WrtForm - Displays screen form.
*
* Params: yBot - Row number of the bottom row
*/
void WrtForm( int yBot )
{
int i;
char szTmp[81];
/* Print the copyright message in upper right. */
_clearscreen( _GCLEARSCREEN );
PrintAt( 1, 55, "Presentation Graphics Demo", co.TitleColor );
/* Clear the top separator line. */
memset( szTmp, ' ', 79 );
szTmp[79] = 0;
PrintAt( 2, 55, "(C) 1988, Microsoft", co.TitleColor );
/* Display each level of the menu title. */
_settextposition( 5, 5 );
for( i = 0; i < cMenuLevel; i++ )
{
if( i )
_outtext( " - " );
_outtext( szMenuTitles[i] );
}
/* Display the top separator line. */
memset( szTmp, 196, 80 );
szTmp[80] = 0;
PrintAt( 6, 1, szTmp, co.FormColor );
/* Display the bottom separator line. */
PrintAt( yBot, 1, szTmp, co.FormColor );
/* Set the global screen variables. */
si.help = yBot + 1;
si.top = 7;
si.bot = yBot - 1;
si.mid = (si.top + si.bot) / 2;
}

View File

@ -0,0 +1,234 @@
.MODEL small, c
INCLUDE demo.inc
.CODE
;* GetVer - Gets DOS version.
;*
;* Shows: DOS Function - 30h (Get MS-DOS Version Number)
;*
;* Params: None
;*
;* Return: Short integer of form (M*100)+m, where M is major
;* version number and m is minor version, or 0 if
;* DOS version earlier than 2.0
GetVer PROC
mov ah, 30h ; DOS Function 30h
int 21h ; Get MS-DOS Version Number
cmp al, 0 ; DOS version 2.0 or later?
jne @F ; Yes? Continue
sub ax, ax ; No? Set AX = 0
jmp SHORT exit ; and exit
@@: sub ch, ch ; Zero CH and move minor
mov cl, ah ; version number into CX
mov bl, 100
mul bl ; Multiply major by 10
add ax, cx ; Add minor to major*10
exit: ret ; Return result in AX
GetVer ENDP
;* GetVidConfig - Determines current video configuration and initializes
;* the vconfig structure.
;*
;* Shows: BIOS Interrupt - 10h, Function 0 (Set Video Mode)
;* 10h, Function 0Fh (Get Video Mode)
;* 10h, Function 1Ah (Get or Set Display
;* Combination Code)
;*
;* Uses: vconfig - Video configuration structure, declared in the
;* DEMO.INC include file.
;*
;* Params: None
;*
;* Return: None
GetVidConfig PROC
mov ax, 1A00h ; Request video info for VGA
int 10h ; Get Display Combination Code
chkVGA: cmp al, 1Ah ; Is VGA or MCGA present?
jne chkEGA ; No? Then check for EGA
cmp bl, 2 ; If VGA exists as secondary adapter,
je isCGA ; check for CGA and mono as primary
jb isMONO
cmp bl, 5 ; If EGA is primary, do normal
jbe chkEGA ; EGA checking
chkMCGA:mov vconfig.adapter, MCGA ; Yes? Assume MCGA
mov vconfig.display, COLOR
cmp bl, 8 ; Correct assumption?
ja gmode ; Yes? Continue
isVGA: mov vconfig.adapter, VGA ; Assume it's VGA color
je gmode ; Yes? Continue
mov vconfig.display, MONO ; No? Must be VGA mono
jmp SHORT gmode ; Finished with VGA, so jump
chkEGA: mov ah, 12h ; Call EGA status function
mov bl, 10h
sub cx, cx ; Clear status bits
int 10h ; Get Configuration Information
jcxz chkCGA ; If CX is unchanged, not EGA
isEGA: mov vconfig.adapter, EGA ; Set structure fields for EGA
mov vconfig.display, MONO ; Assume EGA mono
or bh, bh ; Correct assumption?
jnz gmode ; Yes? Continue
mov vconfig.display, COLOR ; No? Must be EGA color
jmp SHORT gmode ; Finished with EGA, so jump
chkCGA: int 11h ; Get equipment list
and al, 30h ; If bits 4-5 set, monochrome
cmp al, 30h ; Monochrome text mode?
je isMONO ; Yes? Continue
isCGA: mov vconfig.adapter, CGA ; No? Must be CGA
mov vconfig.display, COLOR
mov vconfig.CGAvalue, 29h ; Value for CGA 80x25 text,
jmp SHORT gmode ; color, blink enable
isMONO: mov vconfig.adapter, MDA ; Set MONO
mov vconfig.display, MONO
gmode: mov ah, 0Fh
int 10h ; Get Video Mode
mov vconfig.mode, al ; Record mode
mov vconfig.dpage, bh ; and current page
cmp al, 7 ; Monochrome text mode?
je @F ; Yes? Continue
cmp al, 3 ; Color text mode?
je @F ; Yes? Continue
cmp al, 2 ; Black/white 80-col mode?
je @F ; Yes? Continue
mov ax, 0003h ; If not 80-col text mode,
mov vconfig.mode, al ; request Function 0, mode 3
int 10h ; Set Video Mode to 80-col
@@: mov al, vconfig.display ; Multiply display value
cbw ; (which is either 0 or 1)
mov bx, 800h ; by 800h, then add to B000h
mul bx ; for segment address of
add ax, 0B000h ; video buffer
add ah, vconfig.dpage ; Adding display page gives
mov vconfig.sgmnt, ax ; address of current page
mov vconfig.rows, 24 ; Assume bottom row # = 24
cmp vconfig.adapter, EGA ; EGA or VGA?
jl exit ; No? Exit
mov ax, 1130h ; Yes? Request character info
sub bh, bh ; Set BH to valid value
push bp ; BP will change, so save it
int 10h ; Get number of rows/screen
mov vconfig.rows, dl ; Keep in structure
pop bp ; Restore BP
exit: ret
GetVidConfig ENDP
;* SetCurPos - Sets cursor position.
;*
;* Shows: BIOS Interrupt - 10h, Function 2 (Set Cursor Position)
;*
;* Uses: vconfig - Video configuration structure, declared in the
;* DEMO.INC include file. The structure must first be
;* initialized by calling the GetVidConfig procedure.
;*
;* Params: row - Target row
;* col - Target column
;*
;* Return: None
SetCurPos PROC \
row:WORD, col:WORD
mov dx, col ; DL = column
mov dh, BYTE PTR row ; DH = row
mov ah, 2 ; Function 2
mov bh, vconfig.dpage ; Current page
int 10h ; Set cursor position
ret
SetCurPos ENDP
;* StrWrite - Writes ASCIIZ string to video memory at specified row/column.
;*
;* Shows: Instructions - lodsb stosb
;*
;* Uses: vconfig - Video configuration structure, declared in the
;* DEMO.INC include file. The structure must first be
;* initialized by calling the GetVidConfig procedure.
;*
;* Params: row - Row coordinate
;* col - Column coordinate
;* str - Pointer to string
;*
;* Return: None
StrWrite PROC \
USES ds di si, \
row:WORD, col:WORD, str:PTR BYTE
GetVidOffset row, col ; Get offset in video segment
mov di, ax ; Copy to DI
LoadPtr ds, si, str ; DS:SI points to string
mov es, vconfig.sgmnt ; ES:DI points to video RAM
loop1: lodsb ; Get 1 character from string
or al, al ; Null terminator?
jz exit ; Yes? Exit loop
cmp vconfig.adapter, CGA ; CGA adapter?
jne pchar ; No? Skip next 10 lines
; For CGA systems, StrWrite waits for the video to begin a horizontal
; retrace before writing a character to memory. This avoids the problem
; of video snow inherent with some (though not all) color/graphics adapters.
; It also demonstrates a somewhat different approach to the problem than the
; one taken in the WinOpen and WinClose procedures.
push ax ; Save character
mov dx, 3dah ; Address of status register
cli ; Disallow interruptions
wait1: in al, dx ; Read current video status
test al, 1 ; Horizontal retrace active?
jnz wait1 ; Yes? Wait for it to end
wait2: in al, dx ; No? Read status again
test al, 1 ; Wait for retrace to start
jz wait2
pop ax ; Recover character
pchar: stosb ; Write char to video buffer
sti ; Reenable interrupts
inc di ; Skip attribute byte
jmp SHORT loop1 ; Loop back
exit: ret
StrWrite ENDP
;* ClearBox - Clears portion of screen with specified fill attribute.
;*
;* Shows: BIOS Interrupt - 10h, Function 6 (Scroll Up)
;*
;* Params: attr - Fill attribute
;* row1 - Top screen row of cleared section
;* col1 - Left column of cleared section
;* row2 - Bottom screen row of cleared section
;* col2 - Right column of cleared section
;*
;* Return: None
ClearBox PROC \
attr:WORD, row1:WORD, col1:WORD, row2:WORD, col2:WORD
mov ax, 0600h ; Scroll service
mov bh, BYTE PTR attr ; BH = fill attribute
mov ch, BYTE PTR row1 ; CH = top row of clear area
mov cl, BYTE PTR col1 ; CL = left column
mov dh, BYTE PTR row2 ; DH = bottom row of clear area
mov dl, BYTE PTR col2 ; DL = right column
int 10h ; Clear screen by scrolling up
ret
ClearBox ENDP
END

View File

@ -0,0 +1,296 @@
/* CRLF.C - Translates files for use in the QuickC editor.
*
* Copyright (c) 1988-1989, Microsoft Corporation
*
* A program list is not required to create CRLF from inside QC. No
* special options are required.
*
* The QuickC editor has the following restrictions on the files it
* can edit:
*
* - All lines must be terminated by a carriage return (CR) followed
* by a line feed (LF)--ASCII codes 0x0D/0x0A.
*
* - Character 0 is not allowed. All other characters in the
* range 1 to 255 are allowed.
*
* The editor specifically handles CR (0x0D), LF (0x0A), and HT (0x09).
* Since other control characters may be undesirable, CRLF allows the
* user to optionally change control characters to a specified character
* or to simply remove them. The syntax is
*
* CRLF <infile> <outfile> [/c<ascii>]
*
* where <infile> is the file to be translated, <outfile> is the new
* translated file, and <ascii> is the ASCII code for the character
* to which control characters (except CR, LF, and HT) will be translated.
* The ASCII code may be entered in decimal (ddd), octal (0ddd), or
* hexadecimal (0xddd).
*
* For example, /c32 will translate all control characters to spaces.
* If <ascii> is given as 0, control characters will be removed rather
* than translated. If /c is not given, the program will prompt for
* translation characters.
*/
#include <stdio.h>
#include <io.h>
#include <conio.h>
#include <stdlib.h>
#include <memory.h>
#include <ctype.h>
/* Constants */
#define NUM_CHARS 32 /* Total number of control characters */
#define HT 0x09 /* Horizontal tab character */
#define LF 0x0A /* Linefeed character */
#define CR 0x0D /* Carriage-return character */
#define SKIP 0 /* Filter out control characters */
#define PROMPT -1 /* Get translation from prompts */
/* Global variables. Note that the compiler initializes global arrays
* to 0. The code in translate_char() depends on the following global
* array being initialized to 0.
*/
int mapping[NUM_CHARS];
int global_trans = PROMPT;
/* Function prototypes */
void translate_file( FILE *fdIn, FILE *fdOut );
int translate_char( int line, int c );
/* main - opens input and output files and translates them.
*
* Params: argc - count of arguments
* argv - array of argument strings
*
* Return: None
*/
void main( int argc, char *argv[] )
{
FILE *fdInput;
FILE *fdOutput;
int c;
/* Check command line arguments for validity and print syntax
* prompt if invalid.
*/
if( (argc != 3) && (argc != 4) )
{
fprintf( stderr, "SYNTAX: crlf <infile> <outfile> [/c<ascii>]\n" );
exit( 1 );
}
/* Check for the /c (or -c) option. If present, read in the
* global translation value.
*/
if( argc == 4 )
{
if( ((argv[3][0] == '/') || (argv[3][0] == '-')) &&
(toupper( argv[3][1] ) == 'C') )
{
sscanf( &argv[3][2], "%i", &global_trans );
if( global_trans > 255 )
{
fprintf( stderr, "crlf: unknown translation character\n" );
global_trans = PROMPT;
}
}
else
{
fprintf( stderr, "crlf: fatal error: unknown option '%s'\n",
argv[3] );
exit( 1 );
}
}
/* Try to open the input and output files in binary mode. */
if( (fdInput = fopen( argv[1], "rb" )) == NULL )
{
fprintf( stderr, "crlf: fatal error: can't open '%s'\n", argv[1] );
exit( 1 );
}
if( !access( argv[2], 0 ) )
{
printf( "File exists. Overwrite? " );
c = getch();
if( c != 'y' && c != 'Y' )
exit( 1 );
printf( "\n" );
}
if( (fdOutput = fopen( argv[2], "wb" )) == NULL )
{
fclose( fdInput );
fprintf( stderr, "crlf: fatal error: can't open '%s'\n", argv[2] );
exit( 1 );
}
/* Translate the input file to the output file. */
translate_file( fdInput, fdOutput );
/* Close the files and exit. */
fclose( fdInput );
fclose( fdOutput );
exit( 0 );
}
/* translate_file - translates file for use in QuickC editor. Checks
* each character to see if it is a control character, and if so,
* handles appropriately.
*
* Params: fdIn - input file handle, as obtained from fopen()
* fdOut - output file handle, as obtained from fopen()
*
* Return: None
*
* Uses: trans_mode - character to translate to
*/
void translate_file( FILE *fdIn, FILE *fdOut )
{
int c;
int i;
int line = 1;
/* Loop until the end of the file, reading each character from
* the input file and writing it to the output file. Handle
* control characters; pass other characters through unchanged.
* Note * that a return value of EOF does NOT necessarily indicate
* the end of the file--feof() must be called to verify that
* the end of file has actually been reached.
*/
while( ((c = getc( fdIn )) != EOF) || (!feof( fdIn )) )
{
/* If CR, check and handle the next character. */
if( c == CR )
{
/* Get the next key. */
c = getc( fdIn );
/* If we've reached the end of file, write character and
* break loop to terminate function.
*/
if( (c == EOF) && (feof( fdIn )) )
{
putc( CR, fdOut );
break;
}
/* If it's a LF, write the CR/LF, increment the line count,
* and use the continue statement to return to the top of
* the loop for the next character.
*/
else if( c == LF )
{
putc( CR, fdOut );
putc( LF, fdOut );
++line;
continue;
}
/* If it's a CR with no following LF, skip or translate it. */
else
{
if( global_trans != SKIP )
{
putc( translate_char( line, CR ), fdOut );
}
}
}
/* If it's LF with no preceeding CR (common in files uploaded
* from Unix or Macintosh), write a CR/LF and increment the
* line count.
*/
else if( c == LF )
{
putc( CR, fdOut );
putc( LF, fdOut );
++line;
}
/* If it's a control character that we haven't already handled,
* skip or translate it (depending on value of global_trans).
*/
else if( (c != HT) && (c < NUM_CHARS) )
{
if( global_trans != SKIP )
putc( translate_char( line, c ), fdOut );
}
/* Otherwise, just write the character to the output file. */
else
putc(c, fdOut);
}
}
/* translate_char - translates a control character. If a translate
* character was provided on the command line, it is used. Otherwise
* the user is prompted for a translation character. This character
* is put in the appropriate element of the mapping[] array for future
* reference.
*
* For example, if we find character 3, and the user wants to map
* this to character 42, we set mapping[3] = 42. Next time we encounter
* character 3, we look at mapping[3] and substitute character 42
* without asking.
*
* Params: line - line number in which the character was found
* c - character to be translated
*
* Return: Translated value of character (may be same as original
* character if user didn't want to translate it)
*
* Uses: trans_mode - character to translate to
* mapping - array of translatable characters
*/
int translate_char( int line, int c )
{
int new_val;
/* If command-line translation code was given, return it. */
if( global_trans != PROMPT )
return( global_trans );
/* Otherwise, check to see if we've already got a translated value
* for this character. If so, return that value.
*/
if( mapping[c] != 0 )
return( mapping[c] );
/* Prompt for a translation value. We can't accept 0 or numbers
* larger than 255, so loop until we get a valid translation
* character. The for loop without any parameters will loop until
* a break statement is encountered. The scanf %i specifier is given
* so that the user can enter the ASCII code in decimal (ddd),
* octal (0ddd), or hexadecimal (0xddd).
*
* A different input mechanism could be implemented here.
* For example, you could use getche() to allow the user to
* type in the replacement character directly rather than
* entering an ASCII code.
*/
printf( "Control character %u in line %u: ", c, line );
for( ;; )
{
printf( "Enter ASCII translation code: " );
scanf( "%i", &new_val );
if( (new_val == 0) || (new_val > 255) )
{
printf( "Invalid translation value\n" );
fflush( stdin );
}
else
break;
}
/* Remember the translated value in mapping[c]. */
mapping[c] = new_val;
return( new_val );
}

View File

@ -0,0 +1,90 @@
/* Constants */
#define CR 13 /* ASCII code for Return */
#define ESCAPE 27 /* ASCII code for Esc key */
#define MDA 0 /* Adapter constants */
#define CGA 1
#define MCGA 2
#define EGA 3
#define VGA 4
#define MONO 0 /* Display constants */
#define COLOR 1
#define clear_scrn( attr, row1, row2 ) ClearBox( attr, row1, 0, row2, 79 )
/* Structure members at 1-byte boundaries */
#pragma pack( 1 )
/* Video configuration structure */
struct vid_config
{
unsigned char vmode; /* Current mode */
unsigned char dpage; /* Current display page */
unsigned char rows; /* Number of display rows - 1 */
unsigned char display; /* Either MONO or COLOR */
unsigned char adapter; /* Adapter code */
unsigned char CGAvalue; /* Enable value for CGA */
unsigned sgmnt; /* Video segment with page offset */
};
struct vid_config vconfig; /* Structure for video configuration */
/* Disk statistics returned from GetDiskSize procedure */
struct disk_stat
{
unsigned total; /* total clusters */
unsigned avail; /* available clusters */
unsigned sects; /* sectors per cluster */
unsigned bytes; /* bytes per sector */
};
/* File information returned from FindFirst procedure */
struct file_info
{
char pad[21]; /* pad to 43 bytes */
char attrib; /* file attribute */
int time; /* file time */
int date; /* file date */
long size; /* file size */
char name[13]; /* file name */
};
/* Procedure prototypes from COMMON.ASM */
void GetVidConfig( void );
void StrWrite( int row, int col, char *str );
void ClearBox( int attr, int row1, int col1, int row2, int col2 );
int GetVer( void );
int SetCurPos( int row, int col );
/* Procedure prototypes from MATH.ASM */
long AddLong( long long1, long long2 );
long SubLong( long long1, long long2 );
long ImulLong( long long1, long long2 );
long *MulLong( long long1, long long2 );
int DivLong( long long1, short short2, short *remn );
int IdivLong( long long1, short short2, short *remn );
int Quadratic( float a, float b, float c, float *r1, float *r2 );
/* Procedure prototypes from FILE.ASM */
void ChangeDrive( int drive );
void GetDiskSize( int drive, struct disk_stat *disk );
void GetVidConfig( void );
int ReadCharAttr( int *attr );
int GetCurDir( char *spec );
int GetCurDisk( void );
int CopyFile( int imode, char *fspec1, char *fspec2 );
int DelFile( char *fspec );
int MakeDir( char *pspec );
int RemoveDir( char *pspec );
int ChangeDir( char *pspec );
int GetAttribute( char *fspec );
int SetAttribute( int attr, char *fspec );
int RenameFile( char *fspec1, char *fspec2 );
int GetFileTime( int handle, char *str );
int FindFirst( int attr, char *fspec, struct file_info *finfo );
int FindNext( struct file_info *finfo );
int UniqueFile( int attr, char *fspec );
int OpenFile( int access, char *fspec );
int CloseFile( int handle );
int ReadFile( int handle, int len, char *pbuff );
int SetCurPos( int row, int col );
int GetStr( char *bufstr, int maxlen );
char *StrCompare( char *str1, char *str2, int len );
char *StrFindChar( char ichar, char *str, int direct );

View File

@ -0,0 +1,159 @@
BUFFER_SIZE EQU 2048 ; Buffer size in bytes for disk I/O
CR EQU 13 ; ASCII code for Return
ESCAPE EQU 27 ; ASCII code for Esc key
MDA EQU 0 ; Adapter constants
CGA EQU 1
MCGA EQU 2
EGA EQU 3
VGA EQU 4
MONO EQU 0 ; Display constants
COLOR EQU 1
;* LoadPtr - Macro to load far address into segment:register pair, or
;* near address into register.
;*
;* Params: sgmnt - Segment to be loaded with segment address
;* reg - Register to be loaded with offset address
;* ptr - Pointer to address
;*
;* Shows: Instructions - lds les
;* Directives - MACRO IF IFIDNI ELSE ELSEIF
;* ENDIF .ERR %OUT EXITM ENDM
;* Operators - < > ;;
LoadPtr MACRO sgmnt, reg, ptr ;; Macro definition
IF @DataSize ;; If far pointer, and
IFIDNI <sgmnt>, <ds> ;; if 1st argument is DS,
lds reg, ptr ;; load DS:reg with far address
EXITM
ENDIF
IFIDNI <sgmnt>, <es> ;; or if 1st argument is ES,
les reg, ptr ;; load ES:reg with far address
EXITM
ENDIF
.ERR ;; Generate error if not DS or ES
%OUT 1st macro argument must be DS or ES
ELSE ;; If near pointer,
IFIDNI <sgmnt>, <es> ;; and if segment is ES,
push ds ;; ensure ES points to
pop es ;; same segment as DS
ENDIF
mov reg, ptr ;; Then load reg with near address
ENDIF
ENDM
;* GetVidOffset - Macro to determine offset in video segment that corresponds
;* to given screen coordinates.
;*
;* Params: row - Screen row (top line = 0)
;* col - Screen column (leftmost column = 0)
GetVidOffset MACRO row, col ;; Macro definition
mov ax, row
mov bl, 80 ;; Number of columns per row *
mul bl ;; current row + current column =
add ax, col ;; character byte #
shl ax, 1 ;; Double to account for cell size
ENDM ;; Result in AX register
;* DispText - Macro to display text at given screen coordinates.
;*
;* Shows: Equates - @DataSize @data
;*
;* Params: row - Screen row (top line = 0)
;* col - Screen column (leftmost column = 0)
;* str - Pointer to ASCIIZ string
DispText MACRO row, col, str ;; Macro definition
IF @DataSize ;; If far pointer required,
mov ax, @data ;; pass data segment
push ax
ENDIF
mov ax, str ;; Pointer to ASCIIZ text
push ax
mov ax, col ;; Screen column
push ax
mov ax, row ;; Screen row
push ax
call StrWrite
IF @DataSize
add sp, 8 ;; Clean stack for far data
ELSE
add sp, 6 ;; Clean stack for near data
ENDIF
ENDM
;* Vector - Macro to read current interrupt vector, store it, and replace it.
;*
;* Shows: Equates - @CodeSize @code
;*
;* Params: num - Vector number
;* old - Pointer to doubleword for storing old vector
;* new - Pointer to new handler
Vector MACRO num, old, new ;; Macro definition
push ds ;; Save DS and ES registers
push es
mov ah, 35h ;; AH = DOS function number
mov al, num ;; AL = interrupt number
int 21h ;; Get Interrupt Vector
mov WORD PTR old[0], bx ;; Store it
mov WORD PTR old[2], es
IF @CodeSize ;; If medium or large model,
lds dx, new ;; load DS from parameter
ELSE
mov bx, @code ;; Else ensure DS points to
mov ds, bx ;; to code segment
mov dx, new ;; DS:DX equals new vector
ENDIF
mov ah, 25h ;; AH = DOS function number
int 21h ;; Set Interrupt Vector
pop es ;; Restore ES and DS
pop ds
ENDM
;* Declare structure for disk statistics.
disk_stat STRUC
total DW ? ; total clusters
avail DW ? ; available clusters
sects DW ? ; sectors per cluster
bytes DW ? ; bytes per sector
disk_stat ENDS
;* Declare structure for parameter block.
parmblk STRUC
env DW ? ; Segment address of environment block
taddr DD WORD PTR ? ; Segment:offset address of tail
fcb1 DD WORD PTR ? ; Segment:offset address of 1st FCB
fcb2 DD WORD PTR ? ; Segment:offset address of 2nd FCB
parmblk ENDS
;* Declare structure for video configuration.
;*
;* Shows: STRUC ENDS COMM
vid_config STRUC
mode DB ? ; Current mode
dpage DB ? ; Current display page
rows DB ? ; Number of display rows - 1
display DB ? ; Either MONO or COLOR
adapter DB ? ; Adapter code
CGAvalue DB ? ; Enable value for CGA
sgmnt DW ? ; Video segment with page offset
vid_config ENDS
;* Declare communal variables.
COMM NEAR vconfig:vid_config ; Video configuration structure
COMM NEAR _psp:WORD ; Segment address of Pgm Segment Prefix
COMM NEAR _env:WORD ; Segment address of environment block

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,493 @@
/* FILEDEMO.C - Performs various file operations using DOS functions which
* are invoked from QuickAssembler procedures. FILEDEMO demonstrates how
* to interface C and QuickAssembler procedures, which in turn demonstrate
* various assembly-language instructions, DOS calls, and BIOS interrupts.
*
* FILEDEMO.EXE is built from the following files:
* FILEDEMO.C - Main program
* FILE.ASM - QuickAssembler procedures for FILEDEMO
* COMMON.ASM - QuickAssembler procedures shared by other example programs
* DEMO.INC - Assembly include file with macros and structure declarations
* DEMO.H - C include file with prototypes and structure declarations
*
* Procedures: ClearBox ChangeDrive GetDiskSize
* GetVidConfig GetVer GetCurDir
* GetCurDisk CopyFile DelFile
* MakeDir RemoveDir ChangeDir
* GetAttribute SetAttribute RenameFile
* GetFileTime FindFirst FindNext
* UniqueFile OpenFile CloseFile
* ReadFile SetCurPos StrCompare
* StrFindChar ReadCharAttr
*/
#include "demo.h"
#include <string.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
/* Function prototypes */
char *get_spec( int n );
int list_dir( char *spec, int disp_attr );
void press( void );
/* Constants */
#define MAXSEARCH 80
#define MAXSPEC 64
#define BUFFSIZE 40 * 1024
/* Global variable */
struct file_info file; /* Structure for FindFirst info */
main()
{
static char source[64]; /* Buffer for source file/path */
static char text[MAXSEARCH]; /* Pointer to buffer for search text */
static char date_time[19]; /* Receive file date and time */
int err, mode, handle, len; /* Codes, file handle, bytes read */
int row, col, ch; /* Cursor coordinates, kb character */
int i, j, attr; /* Index variables, file attribute */
int disp_attr; /* Display attribute */
char *spec, *ptr, *buffer; /* File spec, char match, read buffer */
long dsize, disk_use; /* Disk size and usage */
struct disk_stat disk; /* Structure for disk size params */
char copy_msg[] =
{
"Files can be copied or moved in 2 different modes:\n" \
" 0 - overwrite target file if it exists\n" \
" 1 - abort if target file exists\n\n" \
"Mode 1 is supported only with DOS versions 3.0 or higher.\n"
};
char move_msg[] =
{
"Quick Move uses DOS function 56h (Rename File) to effectively " \
"move a file from\none directory to another directory on the " \
"same drive. It copies the entry\nfrom the source directory to " \
"the target directory, but does not physically\ncopy the file.\n\n" \
"Source and target specifications must be given in full, " \
"including filenames,\neven if the names are the same."
};
char grep_msg[] =
{
"The Find Text option uses the StrFindChar and StrCompare procedures " \
"to locate\na text string within specified files, like Unix's " \
"\"grep\" command. Find Text\nis limited to case-sensitive searches " \
"within the current directory.\n\nEnter the desired search string " \
"without quotation marks. When specifying the\nfilename, use " \
"wildcard characters to expand the search to a group of files --\n" \
"for example, \"*.*\" searches all files within the current " \
"directory, \"*.bat\"\nlimits the search to batch files, and so forth."
};
char attr_msg[] =
{
"\t\t\t1 normal \n" \
"\t\t\t2 read-only \n" \
"\t\t\t3 hidden \n" \
"\t\t\t4 system \n" \
"\t\t\t volume \n" \
"\t\t\t subdirectory\n" \
"\t\t\t5 archive \n"
};
GetVidConfig();
ReadCharAttr( &disp_attr );
clear_scrn( disp_attr, 0, 24 );
SetCurPos( 8, 0 );
puts( "Welcome to QuickAssembler's FILEDEMO program.\n\n\nThis program " \
"is meant to encourage experimentation while demonstrating how " \
"to\naccess DOS from QuickAssembler procedures. As a safety " \
"precaution, however,\nwe suggest you DO NOT experiment with " \
"files that cannot easily be replaced." );
press();
do
{
/* Display current drive and directory */
clear_scrn( disp_attr, 0, 24 );
SetCurPos( 0, 0 );
printf( "Current Directory: %c:\\", (char) (GetCurDisk() + 'A') );
GetCurDir( source );
puts( source );
/* Display DOS version */
SetCurPos( 1, 0 );
printf( "DOS Version: %2.1f", ( (float) GetVer() ) / 100 );
/* Display disk statistics for current drive */
SetCurPos( 0, 58 );
GetDiskSize( 0, &disk );
dsize = (long)disk.bytes * disk.sects * disk.total;
disk_use = (long)(disk.total - disk.avail) * disk.bytes * disk.sects;
printf( "Disk Size: %6lu K", dsize / 1024 );
SetCurPos( 1, 58 );
printf( "Disk Use: %6lu K", disk_use / 1024 );
/* Display menu and poll for key press */
clear_scrn( disp_attr, 2, 23 );
SetCurPos( 5, 0 );
puts( " \t *** QuickAssembler File " \
"Demonstration Program ***" );
SetCurPos( 7, 0 );
puts( " \tA List Directory \t\tH Get/Set File Attribute" );
puts( " \tB Copy File \t\tI Get File Date and Time" );
puts( " \tC Move File \t\tJ Rename File" );
puts( " \tD Make Subdirectory \t\tK Delete File" );
puts( " \tE Remove Subdirectory \t\tL Create Unique File" );
puts( " \tF Change Default Drive \t\tM Quick Move" );
puts( " \tG Change Directory \t\tN Find Text" );
printf( "\n\n\tSelect an option, or press ESC to quit: " );
ch = getch();
switch( (ch = toupper( ch )) )
{
/* List first 60 files in specified directory */
case 'A':
err = list_dir( get_spec( 1 ), disp_attr );
if( !err )
press();
break;
/* Copy or Move File according to requested mode:
* 0 = overwrite target
* 1 = abort if target exists
* If Move requested, delete source file after copy.
*/
case 'B':
case 'C':
clear_scrn( disp_attr, 2, 17 );
SetCurPos( 9, 0 );
puts( copy_msg );
mode = -1;
while( (mode < 0) || (mode > 1) )
{
SetCurPos( 16, 0 );
printf( "Enter copy mode: " );
mode = (int) (getche() - '0');
}
spec = get_spec( 2 ); /* Get source */
strcpy( source, spec ); /* Save in buffer */
spec = get_spec( 3 ); /* Get target */
err = CopyFile( mode, source, spec );
if( (ch == 'C') && !err )
err = DelFile( source );
break;
/* Make Directory */
case 'D':
err = MakeDir( get_spec( 1 ) );
break;
/* Remove Directory */
case 'E':
err = RemoveDir( get_spec( 1 ) );
break;
/* Change Default Drive */
case 'F':
SetCurPos( 18, 0 );
printf( "Enter new drive letter: " );
ch = getch();
ch = toupper( ch );
ChangeDrive( ch );
err = 0;
break;
/* Change Directory */
case 'G':
err = ChangeDir( get_spec( 1 ) );
break;
/* Get and Set File Attributes */
case 'H':
strcpy( source, get_spec( 3 ) );
if( (err = GetAttribute( source )) != -1 )
{
attr = err;
if( !attr )
attr_msg[6] = '*';
else
attr_msg[6] = ' ';
for( j = 1, i = 27; j <= 32; j <<= 1, i+= 21 )
{
attr_msg[i] = ' ';
if( attr & j )
attr_msg[i] = '*';
}
err = 0;
clear_scrn( disp_attr, 2, 17 );
SetCurPos( 7, 0 );
puts( attr_msg );
printf( "\n\nToggle attribute bits by selecting 1-5, " \
"or any other key to exit: " );
mode = (int)( getch() - '0' );
if( (mode > 0) && (mode < 6) )
{
switch( --mode )
{
case 0:
attr = 0;
break;
case 1:
case 2:
case 3:
attr = attr ^ (1 << (--mode) );
break;
case 4:
attr = attr ^ 32;
}
err = SetAttribute( attr, source );
}
}
break;
/* Get File Date and Time */
case 'I':
if( (handle = OpenFile( 0, get_spec( 3 ) )) == -1 )
err = 1;
else
err = 0;
if( !err )
{
if( !(err = GetFileTime( handle, date_time )) )
{
clear_scrn( disp_attr, 2, 17 );
SetCurPos( 12, 10 );
printf( "File's date and time stamp: %s", date_time );
CloseFile( handle );
press();
}
}
break;
/* Rename File */
case 'J':
strcpy( source, get_spec( 2 ) );
err = RenameFile( source, get_spec( 3 ) );
break;
/* Delete File */
case 'K':
err = DelFile( get_spec( 3 ) );
break;
/* Create File with Unique Name */
case 'L':
strcpy( source, get_spec( 1 ) );
handle = UniqueFile( 0, source ); /* Normal file attr = 0 */
if( handle >= 0 )
{
printf( "\n\nDOS creates file %s", source );
press();
err = 0;
}
else err = 1;
break;
/* Quick Move from one directory to another */
case 'M':
clear_scrn( disp_attr, 2, 17 );
SetCurPos( 8, 0 );
puts( move_msg );
strcpy( source, get_spec( 2 ) );
err = RenameFile( source, get_spec( 3 ) );
break;
/* Search files for specified text */
case 'N':
clear_scrn( disp_attr, 2, 17 );
buffer = (char *) malloc( BUFFSIZE + 1 );
if( buffer == NULL )
{
SetCurPos( 12, 26 );
puts( "Insufficient memory for option" );
err = 1;
break;
}
SetCurPos( 7, 0 );
puts( grep_msg );
SetCurPos( 18, 0 );
printf( "Enter search text: " );
GetStr( text, MAXSEARCH );
/* Find first data file. */
if( err = FindFirst( 0, get_spec( 3 ), &file ) )
{
clear_scrn( disp_attr, 2, 17 );
SetCurPos( 12, 24 );
puts( "No files found matching specification" );
}
/* If file found, initialize screen coordinates and
* open file for reading.
*/
else
{
clear_scrn( disp_attr, 2, 17 );
row = 6;
col = 0;
do
{
if( (handle = OpenFile( 0, file.name )) != -1 )
{
/* If file opened successfully, read a block
* of BUFFSIZE bytes. If end-of-file encountered
* (number of bytes read not equal to BUFFSIZE)
* or read error, set error flag to break loop.
* Terminate block with a NULL to make it an
* ASCIIZ string.
*/
err = 0;
while( !err )
{
len = ReadFile( handle, BUFFSIZE, buffer );
if( (len == 0) || (len != BUFFSIZE) )
++err;
ptr = buffer;
*( ptr + len ) = 0;
/* Search block for first character in text */
while( spec = StrFindChar( text[0], ptr, 0 ) )
{
/* If initial character found, compare
* remaining characters in search text.
* If all characters match, display file
* name and break out of loop.
*/
ptr = StrCompare( ++spec, &text[1],
(strlen( text ) - 1) );
if( !ptr )
{
SetCurPos( row++, col );
puts( file.name );
if( row == 16)
{
row = 6;
col += 20;
}
err = 1;
break;
}
}
}
CloseFile( handle );
}
else
{
err = 1;
break;
}
} while( !FindNext( &file ) );
if( (row == 6) && (col == 0) )
{
SetCurPos( 12, 22 );
puts( "Text not found in specified file(s)" );
}
press();
err = 0;
}
free( buffer ); /* Free allocated block */
break;
default:
continue;
}
if( err )
{
clear_scrn( disp_attr, 24, 24 );
SetCurPos( 24, 0 );
printf( "*** Error ***\a" );
press();
}
} while( ch != ESCAPE ); /* Exit if ESC key pressed */
clear_scrn( disp_attr, 0, 24 ); /* Clear screen before exit */
SetCurPos( 23, 0 ); /* and set cursor to bottom */
return( 0 );
}
/* get_spec - Prompts for file or path specifications.
*
* Params: n - Prompt number
*
* Return: Pointer to specification
*/
char *get_spec( int n )
{
static char spec[MAXSPEC];
switch( n )
{
case 1:
SetCurPos( 18, 0 );
printf( "Enter path: " );
break;
case 2:
SetCurPos( 18, 0 );
printf( "Enter source file: " );
break;
case 3:
SetCurPos( 20, 0 );
printf( "Enter target file: " );
break;
}
GetStr( spec, MAXSPEC );
return spec;
}
/* list_dir - Lists specified directory by invoking DOS function 4Eh (Find
* First Matching Entry), then DOS function 4Fh (Find Next Matching Entry).
*
* Params: spec - Pointer to path specification
*
* Return: err - Error code returned from FindFirst procedure:
* 0 = successful 1 = error
*/
int list_dir( char *spec, int disp_attr )
{
int row, col;
int err, end;
clear_scrn( disp_attr, 2, 23 );
strcat( spec, "\\*.*" );
err = FindFirst( 16, spec, &file ); /* Find directories, normal files */
if( !err )
{
for( end = 0, col = 0; (col < 80) && (end == 0); col += 22 )
{
for( row = 5; (row < 20) && (end == 0); row++ )
{
SetCurPos( row, col );
puts( file.name );
end = FindNext( &file );
}
}
}
return err;
}
/* press - Prompt for keyboard signal to continue.
*
* Params: None
*/
void press( void )
{
SetCurPos( 24, 49 );
printf( ". . . press a key to continue" );
SetCurPos( 24, 47 );
getch();
}

View File

@ -0,0 +1,45 @@
PROJ =FILEDEMO
DEBUG =1
CC =qcl
AS =qcl
CFLAGS_G =
CFLAGS_D =/Od /Gi$(PROJ).mdt /Zi /Zr
CFLAGS_R =/O /DNDEBUG
CFLAGS =$(CFLAGS_G) $(CFLAGS_D)
AFLAGS_G =/Cx /P1
AFLAGS_D =/Zi
AFLAGS_R =/DNDEBUG
AFLAGS =$(AFLAGS_G) $(AFLAGS_D)
LFLAGS_G =/NOI
LFLAGS_D =/INCR /CO
LFLAGS_R =
LFLAGS =$(LFLAGS_G) $(LFLAGS_D)
RUNFLAGS =
OBJS_EXT =
LIBS_EXT =
.asm.obj: ; $(AS) $(AFLAGS) -c $*.asm
all: $(PROJ).EXE
filedemo.obj: filedemo.c
file.obj: file.asm
common.obj: common.asm
$(PROJ).EXE: filedemo.obj file.obj common.obj $(OBJS_EXT)
echo >NUL @<<$(PROJ).crf
filedemo.obj +
file.obj +
common.obj +
$(OBJS_EXT)
$(PROJ).EXE
$(LIBS_EXT);
<<
ilink -a -e "link $(LFLAGS) @$(PROJ).crf" $(PROJ)
run: $(PROJ).EXE
$(PROJ) $(RUNFLAGS)

View File

@ -0,0 +1,654 @@
/* GRDEMO.C - Demonstrates capabilities of the QuickC graphics library.
* Uses MENU module to display menus. Uses TURTLE module for Turtle graphics.
*/
#include <graph.h>
#include <math.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <time.h>
#include "turtle.h"
#include "menu.h"
/* Function prototypes */
int main( void );
void Circles( void );
void Sphere( void );
int Polygons( void );
int Spiral( int angle, double inc );
int InSpiral( double side, int angle, int inc );
void Bug( void );
void Adjust( void );
/* Returns a random number between min and max, which must be in
* integer range.
*/
#define getrandom( min, max ) ((rand() % (int)((max) - (min))) + (min) + 1)
/* Constants */
#define PI 3.141593
#define LASTATR 15
#define NLASTATR 14
/* Array and enum for main menu */
struct ITEM mnuMain[] =
{ /* Highlight Char Pos */
0, "Quit", /* Q 0 */
0, "Circles", /* C 0 */
0, "Rotating Sphere", /* R 0 */
0, "Tunnel", /* T 0 */
0, "Spiral", /* S 0 */
0, "Inverted Spiral", /* I 0 */
0, "Bug", /* B 0 */
0, "Adjust Window", /* A 0 */
0, "Mode Change", /* M 0 */
0, NULL
};
/* Define constants (0, 1, 2,...) for menu choices */
enum CHOICES
{
QUIT, CIRCLES, SPHERE, TUNNEL, SPIRAL, INSPIRAL, BUG, ADJUST, CHANGE
};
/* Arrays of video mode menu items and of corresponding mode numbers.
* Each has a temporary array containing all items, and a pointer version
* including all except Olivetti.
*/
struct ITEM mnuModesT[] =
{ /* Highlight Char Pos */
0, "ORESCOLOR ", /* O 0 */
4, "MRES4COLOR ", /* 4 4 */
4, "MRESNOCOLOR", /* N 4 */
4, "HRESBW", /* B 4 */
0, "MRES16COLOR", /* M 0 */
0, "HRES16COLOR", /* H 0 */
0, "ERESCOLOR", /* E 0 */
4, "VRES2COLOR", /* 2 4 */
0, "VRES16COLOR", /* V 0 */
1, "MRES256COLOR", /* R 4 */
0, NULL
};
struct ITEM *mnuModes = &mnuModesT[1]; /* Default is no Olivetti mode */
int aModesT[] =
{
_ORESCOLOR,
_MRES4COLOR,
_MRESNOCOLOR,
_HRESBW,
_MRES16COLOR,
_HRES16COLOR,
_ERESCOLOR,
_VRES2COLOR,
_VRES16COLOR,
_MRES256COLOR,
_TEXTMONO,
_ERESNOCOLOR,
_HERCMONO
};
int *aModes = &aModesT[1]; /* Default is no Olivetti mode */
/* Global video configuration */
struct videoconfig vc;
int main()
{
int rowMid, colMid;
int fColor, fFirstTime = TRUE;
int iMode, iMainCur = 0, iModesCur = 0;
_displaycursor( _GCURSOROFF );
_getvideoconfig( &vc );
rowMid = vc.numtextrows / 2;
colMid = vc.numtextcols / 2;
/* Select best graphics mode, adjust menus, set color flag. Note
* that this requires checking both the adapter and the mode.
*/
switch( vc.adapter )
{
case _OCGA:
mnuModes = &mnuModesT[0]; /* Turn on Olivetti mode */
aModes = &aModesT[0];
case _CGA:
mnuModesT[4].achItem[0] = '\0'; /* Turn off EGA modes */
iMode = _MRES4COLOR;
break;
case _HGC:
mnuModesT[7].achItem[0] = '\0';
iMode = _HERCMONO;
break;
case _OEGA:
mnuModes = &mnuModesT[0]; /* Turn on Olivetti mode */
aModes = &aModesT[0];
case _EGA:
mnuModesT[7].achItem[0] = '\0'; /* Turn off VGA modes */
if( vc.memory > 64 )
iMode = _ERESCOLOR;
else
iMode = _HRES16COLOR;
break;
case _OVGA:
mnuModes = &mnuModesT[0]; /* Turn on Olivetti mode */
aModes = &aModesT[0];
case _VGA:
iMode = _VRES16COLOR;
break;
case _MCGA:
iMode = _MRES256COLOR;
break;
case _MDPA:
default:
puts( "No graphics mode available.\n" );
return TRUE;
}
switch( vc.mode )
{
case _TEXTBW80:
case _TEXTBW40:
fColor = FALSE;
break;
case _TEXTMONO:
case _ERESNOCOLOR:
case _HERCMONO:
fColor = FALSE;
if( iMode != _HERCMONO )
iMode = _ERESNOCOLOR;
mnuMain[8].achItem[0] = '\0'; /* Turn off mode change */
break;
default:
fColor = TRUE;
break;
}
/* Find current mode in mode array. */
for( iModesCur = 0; aModes[iModesCur] != iMode; iModesCur++ )
;
/* Seed randomizer with time. */
srand( (unsigned)time( NULL ) );
while( TRUE )
{
/* Set text mode and optionally clear the screen to blue. */
_setvideomode(_DEFAULTMODE );
if( fColor )
_setbkcolor( (long)_TBLUE );
_clearscreen( _GCLEARSCREEN );
/* Select from menu. */
iMainCur = Menu( rowMid, colMid, mnuMain, iMainCur );
/* Set graphics mode and initialize turtle graphics. Put border
* on window.
*/
if( iMainCur != CHANGE )
{
_setvideomode( iMode );
_displaycursor( _GCURSOROFF );
_getvideoconfig( &vc );
InitTurtle( &vc );
Rectangle( 2 * tc.xMax, 2 * tc.yMax );
}
/* Branch to menu choice. */
switch( iMainCur )
{
case QUIT:
_setvideomode( _DEFAULTMODE );
return FALSE;
case CIRCLES:
Circles();
break;
case SPHERE:
Sphere();
break;
case TUNNEL:
PenDown( FALSE );
MoveTo( -tc.xMax * .2, tc.yMax * .15 );
PenDown( TRUE );
Polygons();
while( !GetKey( NO_WAIT ) )
NextColorValue( DEFAULT ); /* Rotate palette */
break;
case SPIRAL:
if( Spiral( getrandom( 30, 80 ), (double)getrandom( 1, 5 ) ) )
break;
while( !GetKey( NO_WAIT ) )
NextColorValue( DEFAULT );
break;
case INSPIRAL:
NextColorIndex( 0 );
if( InSpiral( (double)getrandom( 8, 20 ),
getrandom( 4, 22 ),
getrandom( 3, 31 ) ) )
break;
while( !GetKey( NO_WAIT ) )
NextColorValue( DEFAULT );
break;
case BUG:
Bug();
break;
case ADJUST:
Adjust();
continue;
case CHANGE:
if( fColor )
_setbkcolor( (long)_TBLUE );
_clearscreen( _GCLEARSCREEN );
iModesCur = Menu( rowMid, colMid, mnuModes, iModesCur );
iMode = aModes[iModesCur];
if( vc.adapter == _MCGA )
switch( iMode )
{
case _MRES16COLOR:
case _HRES16COLOR:
case _ERESCOLOR:
case _VRES16COLOR:
_settextposition( 1, 22 );
_outtext( "Mode not recognized" );
iMode = _MRES256COLOR;
}
break;
}
}
}
/* Circles - Draw circles of varying sizes and colors on screen in a
* round pattern.
*
* Params: None
*
* Return: None
*
* Uses: tc
*/
void Circles()
{
double x, y, xyRadius;
int fFill, fPenDown;
/* Initialize and save pen and fill flags. */
if( tc.cci <= 4 )
fFill = SetFill( FALSE );
else
fFill = SetFill( TRUE );
fPenDown = PenDown( FALSE );
while( TRUE )
{
/* Draw circles. */
for( xyRadius = 10.0; xyRadius <= 130.0; xyRadius++ )
{
x = (tc.xMax - 30) * atan( sin( xyRadius / PI ) );
y = (tc.yMax - 30) * atan( cos( xyRadius / PI ) );
MoveTo( x, y );
PenColor( NextColorIndex( DEFAULT ) );
Circle( xyRadius );
if( GetKey( NO_WAIT ) )
{
PenDown( fPenDown );
SetFill( fFill );
return;
}
}
/* For palette modes (except 256 color), start over. */
if( tc.ccv == 64 || tc.ccv == 16 )
{
_clearscreen( _GCLEARSCREEN );
SetFill( FALSE );
MoveTo( 0.0, 0.0 );
PenColor( WHITE );
Rectangle( 2 * tc.xMax, 2 * tc.yMax );
SetFill( fFill );
NextColorValue( DEFAULT );
}
}
}
/* Sphere - Draw and fill slices of a sphere. Rotate colors in EGA+ modes
* with more than 4 color indexes.
*
* Params: None
*
* Return: None
*
* Uses: tc
*/
void Sphere()
{
double xCur, xSize, ySize, xInc;
short ciBorder, fFill;
short cvi = 0, ci = 0, c = 0;
extern long cvlColors[];
ySize = xSize = tc.yMax * 0.9 * 2;
fFill = SetFill( FALSE );
NextColorIndex( 0 );
xInc = xSize / 14;
ciBorder = PenColor( DEFAULT );
BorderColor( ciBorder );
/* Draw slices. */
for( xCur = xInc; xCur <= xSize; xCur += xInc * 2 )
Ellipse( xCur, ySize );
SetFill( TRUE );
PenDown( FALSE );
Turn( 90 );
xSize /= 2;
MoveTo( xSize - xInc, 0.0 );
NextColorValue( LIMITED );
/* Fill slices. */
while( tc.xCur >= (-xSize + xInc))
{
PenColor( NextColorIndex( DEFAULT ) );
FillIn();
Move( -xInc );
}
while( !GetKey( NO_WAIT ) )
NextColorValue( LIMITED );
PenDown( TRUE );
SetFill( fFill );
}
/* Polygons - Draws polygons (starting with triangle) of increasing
* size by incrementing the number of sides without changing the
* length of sides. Make sure pen is down.
*
* Params: None
*
* Return: 1 for user interrupt, 0 for edge of screen encountered
*
* Uses: tc
*/
int Polygons()
{
int cSides = 3, atrib = 1;
double dxy = tc.yUnit;
while( TRUE )
{
PenColor( NextColorIndex( DEFAULT ) );
if( !Poly( cSides++, dxy += 1.5 ) )
return FALSE;
if( GetKey( NO_WAIT ) )
return TRUE;
}
}
/* Spiral - Draw a spiral by incrementing the length of each side
* of a rotating figure.
*
* Params: ang - determines tightness
* xyInc - determines size of sides
*
* Return: 1 for user interrupt, 0 for edge of screen encountered
*
* Uses: tc
*/
int Spiral( int ang, double xyInc )
{
double xy = tc.yUnit;
while( TRUE )
{
PenColor( NextColorIndex( DEFAULT ) );
if( !Move( xy += xyInc ) )
return FALSE;
Turn( ang );
if( GetKey( NO_WAIT ) )
return TRUE;
}
}
/* InSpiral - Draw an inverted spiral by increasing each angle
* of a rotating figure while keeping the length of sides constant.
*
* Params: xy - determines size
* ang - initial angle determines shape
* angInc - determines tightness and shape
*
* Return: 1 for user interrupt, 0 for edge of screen encountered
*/
int InSpiral( double xy, int ang, int angInc )
{
while( TRUE )
{
PenColor( NextColorIndex( DEFAULT ) );
if( !Move( xy ) )
return FALSE;
Turn( ang += angInc );
if( GetKey( NO_WAIT ))
return TRUE;
}
}
/* Bug - Draws a winged bug on the screen. Then moves it randomly
* around the screen.
*
* Params: None
*
* Return: None
*
* Uses: tc
*/
void Bug()
{
static unsigned char uTopWing[] = { 0x81, 0x3c, 0xc3, 0x66,
0x66, 0x0f, 0xf0, 0x18 };
static unsigned char uBotWing[] = { 0x66, 0x0f, 0xf0, 0x18,
0x81, 0x3c, 0xc3, 0x66 };
char *buffer; /* Buffer for image */
/* Draw bug. */
PenDown( FALSE );
SetFill( TRUE );
Move( 40.0 ); /* Draw and fill front wings */
Turn( 90 );
Move( 80.0 );
PenColor( 1 );
_setfillmask( uTopWing );
Ellipse( 172.0, 70.0 );
Turn( 180 );
Move( 160.0 );
Ellipse( 172.0, 70.0 );
Turn(-90 );
MoveTo( 0.0, 0.0 );
Move( 25.0 ); /* Draw and fill back wings */
Turn( 90 );
Move( 70.0 );
PenColor( 2 );
_setfillmask( uBotWing );
Ellipse( 150.0, 70.0 );
Turn( 180 );
Move( 140.0 );
Ellipse( 150.0, 70.0 );
Turn(-90 );
MoveTo( 0.0, 0.0 );
_setfillmask( NULL ); /* Draw body */
PenColor( 3 );
BorderColor( 3 );
Ellipse( 52.0, 220.0 );
PenColor( 1 ); /* Drill eyes */
BorderColor( 1 );
SetFill( FALSE );
Move( 90.0 );
Turn( 90 );
Move( 22.0 );
Circle( 20.0 );
PenColor( 0 );
FillIn();
PenColor( 1 );
Turn( 180 );
Move( 44.0 );
Circle( 20.0 );
PenColor( 0 );
FillIn();
/* Move into position - top-right of image. */
MoveTo( 0.0, 0.0 );
TurnTo( 0 );
Move( 120.0 );
Turn( -90 );
Move( 175.0 );
Turn( 90 );
/* Size image and allocate memory for it. */
buffer = (char *)malloc( (size_t)ImageSize( 350.0, 240.0 ) );
GetImage( 350.0, 240.0, buffer );
/* Move randomly, adjusting at edges. */
while( !GetKey( NO_WAIT ) )
{
if( tc.xCur <= (-tc.xMax + 15.0) )
TurnTo( 90 );
else if( tc.yCur <= (-tc.yMax + 15.0) )
TurnTo( 180 );
else if( tc.xCur >= (tc.xMax - 365.0) )
TurnTo( 270 );
else if( tc.yCur >= (tc.yMax - 255.0) )
TurnTo( 0 );
else
Turn( getrandom( -20, 20 ) );
Move( 3.0 );
PutImage( buffer, _GPSET );
}
free( (char *)buffer );
}
/* Adjust - Allow the user to interactively adjust the display window.
* Unshifted direction keys adjust the window size. Shifted direction
* keys move the window. The numeric keypad plus and minus keys adjust
* aspect without changing the window. A window frame and a circle give
* visual feedback on adjustments.
*
* Params: None
*
* Return: None
*
* Uses: tc and vc
*/
#define WININC 4
void Adjust()
{
short i;
double xyRadius = 400.0;
char achT[40];
while( TRUE )
{
/* Display instructions. */
_settextposition( 2, 1 );
_outtext(" Grey PLUS and MINUS Adjust aspect\n" );
_outtext(" Cursor keys Size window\n" );
_outtext(" SHIFT cursor keys Move window\n" );
_outtext(" ENTER Finished\n\n" );
sprintf( achT, "\n ratio=%1.2f xMax=%.f yMax=%.f",
tc.yxRatio, tc.xMax, tc.yMax );
_outtext( achT );
Rectangle( 2 * tc.xMax, 2 * tc.yMax );
PenDown( FALSE );
/* Draw circle with cross. */
MoveTo( 75.0, 0.0 );
Circle( xyRadius );
for( i = 1; i <= 4; i++)
{
PenDown( TRUE );
Move( xyRadius );
Turn( 180 );
PenDown( FALSE );
Move( xyRadius );
Turn( 90 );
}
switch( GetKey( CLEAR_WAIT ) )
{
/* Adjust aspect. */
case N_MINUS:
tc.yxRatio = (tc.xMax - (WININC * tc.yUnit)) / tc.yMax;
break;
case N_PLUS:
tc.yxRatio = (tc.xMax + (WININC * tc.yUnit)) / tc.yMax;
break;
/* Adjust window size. */
case U_RT:
if( tc.xsLeft < (vc.numxpixels / 3) )
tc.xsLeft += WININC;
if( tc.xsRight > (vc.numxpixels - (vc.numxpixels / 3)) )
tc.xsRight -= WININC;
break;
case U_LT:
if( tc.xsLeft )
tc.xsLeft -= WININC;
if( tc.xsRight < vc.numxpixels )
tc.xsRight += WININC;
break;
case U_DN:
if( tc.ysTop < (vc.numypixels / 3) )
tc.ysTop += WININC;
if( tc.ysBot > (vc.numypixels - (vc.numypixels / 3)) )
tc.ysBot -= WININC;
break;
case U_UP:
if( tc.ysTop )
tc.ysTop -= WININC;
if( tc.ysBot < vc.numypixels )
tc.ysBot += WININC;
break;
/* Adjust window position. */
case S_LT:
if( tc.xsLeft )
{
tc.xsLeft -= WININC;
tc.xsRight -= WININC;
}
break;
case S_RT:
if( tc.xsRight < vc.numxpixels )
{
tc.xsLeft += WININC;
tc.xsRight += WININC;
}
break;
case S_UP:
if( tc.ysTop )
{
tc.ysTop -= WININC;
tc.ysBot -= WININC;
}
break;
case S_DN:
if( tc.ysBot < vc.numypixels )
{
tc.ysTop += WININC;
tc.ysBot += WININC;
}
break;
/* Finished. */
case ENTER:
return;
/* Ignore unknown key. */
default:
Home( &vc );
continue;
}
/* Clear screen and reset defaults after each adjustement. */
_clearscreen( _GCLEARSCREEN );
Home( &vc );
}
}

View File

@ -0,0 +1,38 @@
PROJ =GRDEMO
DEBUG =1
CC =qcl
CFLAGS_G =
CFLAGS_D =/Od /Gi$(PROJ).mdt /Zi /Zr
CFLAGS_R =/O /DNDEBUG
CFLAGS =$(CFLAGS_G) $(CFLAGS_D)
LFLAGS_G =/NOI
LFLAGS_D =/INCR /CO
LFLAGS_R =
LFLAGS =$(LFLAGS_G) $(LFLAGS_D)
RUNFLAGS =
OBJS_EXT =
LIBS_EXT =
all: $(PROJ).exe
grdemo.obj: grdemo.c
menu.obj: menu.c
turtle.obj: turtle.c
$(PROJ).exe: grdemo.obj menu.obj turtle.obj $(OBJS_EXT)
echo >NUL @<<$(PROJ).crf
grdemo.obj +
menu.obj +
turtle.obj +
$(OBJS_EXT)
$(PROJ).exe
$(LIBS_EXT);
<<
ilink -a -e "link $(LFLAGS) @$(PROJ).crf" $(PROJ)
run: $(PROJ).exe
$(PROJ) $(RUNFLAGS)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
PROJ =LIFE
DEBUG =1
CC =qcl
CFLAGS_G =
CFLAGS_D =/Od /Gi$(PROJ).mdt /Zi /Zr
CFLAGS_R =/O /DNDEBUG
CFLAGS =$(CFLAGS_G) $(CFLAGS_D)
LFLAGS_G =/NOI
LFLAGS_D =/INCR /CO
LFLAGS_R =
LFLAGS =$(LFLAGS_G) $(LFLAGS_D)
RUNFLAGS =
OBJS_EXT =
LIBS_EXT =
all: $(PROJ).exe
life.obj: life.c
tools.obj: tools.c
$(PROJ).exe: life.obj tools.obj $(OBJS_EXT)
echo >NUL @<<$(PROJ).crf
life.obj +
tools.obj +
$(OBJS_EXT)
$(PROJ).exe
$(LIBS_EXT);
<<
ilink -a -e "link $(LFLAGS) @$(PROJ).crf" $(PROJ)
run: $(PROJ).exe
$(PROJ) $(RUNFLAGS)

View File

@ -0,0 +1,340 @@
.MODEL small, c
INCLUDE demo.inc
.CODE
;* AddLong - Adds two double-word (long) integers.
;*
;* Shows: Instructions - add adc
;*
;* Params: long1 - First integer
;* long2 - Second integer
;*
;* Return: Sum as long integer
AddLong PROC \
long1:DWORD, long2:DWORD
mov ax, WORD PTR long1[0] ; AX = low word, long1
mov dx, WORD PTR long1[2] ; DX = high word, long1
add ax, WORD PTR long2[0] ; Add low word, long2
adc dx, WORD PTR long2[2] ; Add high word, long2
ret ; Result returned as DX:AX
AddLong ENDP
;* SubLong - Subtracts a double-word (long) integer from another.
;*
;* Shows: Instructions - sub sbb
;*
;* Params: long1 - First integer
;* long2 - Second integer
;*
;* Return: Difference as long integer
SubLong PROC \
long1:DWORD, long2:DWORD
mov ax, WORD PTR long1[0] ; AX = low word, long1
mov dx, WORD PTR long1[2] ; DX = high word, long1
sub ax, WORD PTR long2[0] ; Subtract low word, long2
sbb dx, WORD PTR long2[2] ; Subtract high word, long2
ret ; Result returned as DX:AX
SubLong ENDP
;* MulLong - Multiplies two unsigned double-word (long) integers. The
;* procedure allows for a product of twice the length of the multipliers,
;* thus preventing overflows. The result is copied into a 4-word data area
;* and a pointer to the data area is returned.
;*
;* Shows: Instruction - mul
;*
;* Params: long1 - First integer (multiplicand)
;* long2 - Second integer (multiplier)
;*
;* Return: Pointer to quadword result
.DATA
PUBLIC result
result DQ WORD PTR ? ; Result from MulLong
.CODE
MulLong PROC \
long1:DWORD, long2:DWORD
mov ax, WORD PTR long2[2] ; Multiply long2 high word
mul WORD PTR long1[2] ; by long1 high word
mov WORD PTR result[4], ax
mov WORD PTR result[6], dx
mov ax, WORD PTR long2[2] ; Multiply long2 high word
mul WORD PTR long1[0] ; by long1 low word
mov WORD PTR result[2], ax
add WORD PTR result[4], dx
adc WORD PTR result[6], 0 ; Add any remnant carry
mov ax, WORD PTR long2[0] ; Multiply long2 low word
mul WORD PTR long1[2] ; by long1 high word
add WORD PTR result[2], ax
adc WORD PTR result[4], dx
adc WORD PTR result[6], 0 ; Add any remnant carry
mov ax, WORD PTR long2[0] ; Multiply long2 low word
mul WORD PTR long1[0] ; by long1 low word
mov WORD PTR result[0], ax
add WORD PTR result[2], dx
adc WORD PTR result[4], 0 ; Add any remnant carry
mov ax, OFFSET result ; Return pointer
mov dx, @data ; to result
ret
MulLong ENDP
;* ImulLong - Multiplies two signed double-word integers. Because the imul
;* instruction (illustrated here) treats each word as a signed number, its
;* use is impractical when multiplying multi-word values. Thus the technique
;* used in the MulLong procedure can't be adopted here. Instead, ImulLong
;* is broken into three sections arranged in ascending order of computational
;* overhead. The procedure tests the values of the two integers and selects
;* the section that involves the minimum required effort to multiply them.
;*
;* Shows: Instruction - imul
;*
;* Params: long1 - First integer (multiplicand)
;* long2 - Second integer (multiplier)
;*
;* Return: Result as long integer
ImulLong PROC \
USES si, \
long1:DWORD, long2:DWORD
; Section 1 tests for integers in the range of 0 to 65,535. If both
; numbers are within these limits, they're treated as unsigned short
; integers.
sect1: mov ax, WORD PTR long2[0] ; AX = low word of long2
mov dx, WORD PTR long2[2] ; DX = high word of long2
mov bx, WORD PTR long1[0] ; BX = low word of long1
mov cx, WORD PTR long1[2] ; CX = high word of long1
or dx, dx ; Both high words zero?
jnz sect2 ; No? Go to section 2
or cx, cx
jnz sect2
mul bx ; Yes? Multiply the low words
jmp SHORT exit ; and exit section 1
; Section 2 tests for integers in the range of -32,768 to 32,767. If
; both numbers are within these limits, they're treated as signed short
; integers.
sect2: push ax ; Save long2 low word
push bx ; Save long1 low word
or dx, dx ; High word of long2 = 0?
jnz @F ; No? Test for negative
test ah, 80h ; Low word of long2 in range?
jz skip1 ; Yes? long2 ok, so test long1
jmp SHORT sect3 ; No? Go to section 3
@@: cmp dx, 0FFFFh ; Empty with sign flag set?
jne sect3 ; No? Go to section 3
test ah, 80h ; High bit set in low word?
jz sect3 ; No? Low word is too high
skip1: or cx, cx ; High word of long1 = 0?
jnz @F ; No? Test for negative
test bh, 80h ; Low word of long1 in range?
jz skip2 ; Yes? long1 ok, so use sect 2
jmp SHORT sect3 ; No? Go to section 3
@@: cmp cx, 0FFFFh ; Empty with sign flag set?
jne sect3 ; No? Go to section 3
test bh, 80h ; High bit set in low word?
jz sect3 ; No? Low word is too high
skip2: imul bx ; Multiply low words
pop bx ; Clean stack
pop bx
jmp SHORT exit ; Exit section 2
; Section 3 involves the most computational overhead. It treats the two
; numbers as signed long (double-word) integers.
sect3: pop bx ; Recover long1 low word
pop ax ; Recover long2 low word
mov si, dx ; SI = long2 high word
push ax ; Save long2 low word
mul cx ; long1 high word x long2 low word
mov cx, ax ; Accumulate products in CX
mov ax, bx ; AX = low word of long1
mul si ; Multiply by long2 high word
add cx, ax ; Add to previous product
pop ax ; Recover long2 low word
mul bx ; Multiply by long1 low word
add dx, cx ; Add to product high word
exit: ret ; Return result as DX:AX
ImulLong ENDP
;* DivLong - Divides an unsigned long integer by an unsigned short integer.
;* The procedure does not check for overflow or divide-by-zero.
;*
;* Shows: Instruction - div
;*
;* Params: long1 - First integer (dividend)
;* short2 - Second integer (divisor)
;* remn - Pointer to remainder
;*
;* Return: Quotient as short integer
DivLong PROC \
USES di, \
long1:DWORD, short2:WORD, remn:PTR WORD
mov ax, WORD PTR long1[0] ; AX = low word of dividend
mov dx, WORD PTR long1[2] ; DX = high word of dividend
div short2 ; Divide by short integer
LoadPtr es, di, remn ; Point ES:DI to remainder
mov es:[di], dx ; Copy remainder
ret ; Return with AX = quotient
DivLong ENDP
;* IdivLong - Divides a signed long integer by a signed short integer.
;* The procedure does not check for overflow or divide-by-zero.
;*
;* Shows: Instruction - idiv
;*
;* Params: long1 - First integer (dividend)
;* short2 - Second integer (divisor)
;* remn - Pointer to remainder
;*
;* Return: Quotient as short integer
IdivLong PROC \
USES di, \
long1:DWORD, short2:WORD, remn:PTR WORD
mov ax, WORD PTR long1[0] ; AX = low word of dividend
mov dx, WORD PTR long1[2] ; DX = high word of dividend
idiv short2 ; Divide by short integer
LoadPtr es, di, remn ; ES:DI = remainder
mov es:[di], dx ; Copy remainder
ret ; Return with AX = quotient
IdivLong ENDP
;* Quadratic - Solves for the roots of a quadratic equation of form
;* A*x*x + B*x + C = 0
;* using floating-point instructions. This procedure requires either a math
;* coprocessor or emulation code. If executing within the QuickAssembler
;* environment, emulation is automatically provided if a coprocessor is not
;* installed. If executing from the QCL command line, the /FPi switch must
;* be specified if a coprocessor is not installed. For example, to create
;* the MATHDEMO.EXE example program with floating-point emulation, enter the
;* following line:
;* QCL /Cx mathdemo.c /FPi math.asm common.asm
;*
;* Shows: Instructions - sahf fld1 fld fadd fmul
;* fxch fsubr fchs fsubp fstp
;* fst fdivr fwait ftst
;*
;* Params: a - Constant for 2nd-order term
;* b - Constant for 1st-order term
;* c - Equation constant
;* r1 - Pointer to 1st root
;* r2 - Pointer to 2nd root
;*
;* Return: Short integer with return code
;* 0 if both roots found
;* 1 if single root (placed in r1)
;* 2 if indeterminate
Quadratic PROC \
USES ds di si, \
a:DWORD, b:DWORD, c:DWORD, r1:PTR DWORD, r2:PTR DWORD
LOCAL status:WORD ; Intermediate status
LoadPtr es, di, r1 ; ES:DI points to 1st root
LoadPtr ds, si, r2 ; DS:SI points to 2nd root
sub bx, bx ; Clear error code
fld1 ; Load top of stack with 1
fadd st, st ; Double it to make 2
fld st ; Copy to next register
fmul a ; ST register = 2a
ftst ; Test current ST value
fstsw status ; Copy status to local word
fwait ; Ensure coprocessor is done
mov ax, status ; Copy status into AX
sahf ; Load flag register
jnz @F ; If C3 set, a = 0, in which case
; solution is x = -c / b
fld b ; Load b parameter
ftst ; Test current ST value
fstsw status ; Copy status to local word
fwait ; Ensure coprocessor is done
mov ax, status ; Copy status into AX
sahf ; Load flag register
jz exit2 ; If C3 set, b = 0, so don't divide
fld st ; Copy b to next register
fld c ; Load C parameter
fchs ; Reverse sign
fxch ; Exchange ST and ST(1)
fdiv ; Divide c by b
fst DWORD PTR es:[di] ; Copy result
jmp SHORT exit1 ; Return with code = 1
@@: fmul st(1), st ; ST(1) register = 4a
fxch ; Exchange ST and ST(1)
fmul c ; ST register = 4ac
ftst ; Test current ST value
fstsw status ; Copy status to local word
fwait ; Ensure coprocessor is done
mov ax, status ; Copy status into AX
sahf ; Load flag register
jp exit2 ; If C2 set, 4*a*c is infinite
fld b ; Else load b parameter
fmul st, st ; Square it; ST register = b*b
fsubr ; ST register = b*b - 4*a*c
ftst ; Test current ST value
fstsw status ; Copy status to local word
fwait ; Ensure coprocessor is done
mov ax, status ; Copy status into AX
sahf ; Load flag register
jc exit2 ; If C0 set, b*b < 4ac
jnz @F ; If C3 set, b*b = 4ac, in which
inc bx ; case only 1 root so set flag
@@: fsqrt ; Get square root
fld b ; Load b parameter
fchs ; Reverse sign
fxch ; Exchange ST and ST1
fld st ; Copy square root to next reg
fadd st, st(2) ; ST = -b + sqrt(b*b - 4*a*c)
fxch ; Exchange ST and ST1
fsubp st(2), st ; ST = -b - sqrt(b*b - 4*a*c)
fdiv st, st(2) ; Divide 1st dividend by 2*a
fstp WORD PTR es:[di] ; Copy result, pop stack
fdivr ; Divide 2nd dividend by 2*a
fstp WORD PTR ds:[si] ; Copy result, pop stack
jmp SHORT exit ; Return with code
exit2: inc bx ; Error code = 2 for indeterminancy
exit1: inc bx ; Error code = 1 for single root
exit: mov ax, bx
ret
Quadratic ENDP
END

View File

@ -0,0 +1,376 @@
/* MATHDEMO.C - Creates a simple on-screen calculator with functions for
* basic integer arithmetic and for solving for the roots of a quadratic
* equation. MATHDEMO invokes QuickAssembler procedures that illustrate
* assembly-language instructions related to mathematics, including those
* specific to the 8087 family of coprocessors.
*
* MATHDEMO.EXE is built from the following files:
* MATHDEMO.C - Main program
* MATH.ASM - QuickAssembler procedures for MATHDEMO
* COMMON.ASM - QuickAssembler procedures shared by other example programs
* DEMO.INC - Assembly include file with macros and structure declarations
* DEMO.H - C include file with prototypes and structure declarations
*
* Procedures: AddLong MulLong DivLong Quadratic
* SubLong ImulLong IdivLong
*/
#include "demo.h"
#include <dos.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
/* Function prototypes */
void display_calc( void );
void display_help( void );
void press( void );
void push( int sign );
/* Global variables */
long s1, s2, s3; /* Stack values: 1st, 2nd, 3rd */
char entry[11]; /* Entry window string */
int col; /* Current display column for entry */
main()
{
int ch, err; /* Keyboard character, return val */
static int sign, mode; /* Sign flag, signed/unsigned flag */
static float root1, root2; /* Roots of quadratic equation */
static short quotient, remainder; /* Results of division */
static long *product, result;
static char *rmsg[2] = { "roots", "indeterminate" };
static char *highmsg = { "high:" };
static char *lowmsg = { "low:" };
GetVidConfig();
display_calc();
StrWrite( 9, 14, "+" );
col = 20;
while( ch != ESCAPE )
{
SetCurPos( 9, col );
ch = getch();
switch( (ch = toupper( ch )) )
{
/* Display number in entry window. */
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
putch( (char) ch );
entry[col - 20] = (char) ch;
entry[++col - 20] = 0;
if( col == 30 )
col--;
break;
/* Toggle between signed and unsigned arithmetic modes. */
case 'M':
if( mode )
{
mode = 0; /* For signed mode, */
StrWrite( 14, 57, " (" ); /* toggle flag off */
StrWrite( 9, 14, "+" ); /* and restore sign */
}
else
{
mode++; /* For unsigned mode, */
StrWrite( 14, 57, "(un" ); /* toggle flag on */
StrWrite( 9, 14, " " ); /* and blank sign */
}
sign = 0;
break;
/* Solve for x in quadratic equation s3*x*x + s2*x + s3 = 0. */
case 'Q':
push( sign );
err = Quadratic( (float)s3, (float)s2, (float)s1,
&root1, &root2 );
ClearBox( 7, 9, 15, 9, 29 ); /* Clear entry window */
ClearBox( 7, 9, 49, 10, 66 ); /* Clear result window */
if( err < 2 )
{
SetCurPos( 9, 50 );
printf( "%16.3f", root1 ); /* Display 1st root */
if( !err )
{
SetCurPos( 10, 50 );
printf( "%16.3f", root2 ); /* Display 2nd root */
}
}
if( err == 2)
{
StrWrite( 9, 50, rmsg[0] ); /* Display "roots */
StrWrite( 10, 50, rmsg[1] ); /* indeterminate" */
}
break;
/* Change sign. */
case 'S':
if( !mode ) /* Allow sign changes only */
{ /* in signed mode */
if( sign )
{
StrWrite( 9, 14, "+" );
sign = 0;
}
else
{
StrWrite( 9, 14, "-" );
sign++;
}
}
break;
/* Clear stack, reinitialize variables. */
case 'C':
s3 = s2 = s1 = 0;
ClearBox( 7, 9, 15, 9, 29 ); /* Clear entry window */
ClearBox( 7, 9, 49, 10, 66 ); /* Clear result window */
entry[0] = 0;
col = 20;
break;
/* Push values down stack when Enter key pressed. */
case CR:
push( sign );
break;
/* Display help screen. */
case '?':
case 'H':
display_help(); /* Display help */
display_calc(); /* Redisplay calculator */
StrWrite( 9, 20, entry ); /* and entry number */
if( mode )
{
StrWrite( 14, 57, "(un" ); /* Make "unsigned" */
StrWrite( 9, 14, " " ); /* and blank sign */
}
else
{
if( sign )
StrWrite( 9, 14, "-" );
else
StrWrite( 9, 14, "+" );
}
break;
/* Add or subtract s1 and s2. */
case '+':
case '-':
push( sign );
if( (char) ch == '+' )
s1 = AddLong( s1, s2 );
else
s1 = SubLong( s2, s1 );
ClearBox( 7, 9, 15, 9, 29 ); /* Clear entry window */
ClearBox( 7, 9, 49, 10, 66 ); /* Clear result window */
SetCurPos( 9, 56 );
if( mode )
printf( "%lu", s1 ); /* Display unsigned or */
else
printf( "%li", s1 ); /* signed result */
break;
/* Multiply s1 and s2. */
case '*':
push( sign );
if( mode )
product = MulLong( s1, s2 );
else
s1 = ImulLong( s1, s2 );
ClearBox( 7, 9, 15, 9, 29 ); /* Clear entry window */
ClearBox( 7, 9, 49, 10, 66 ); /* Clear result window */
if( mode )
{
StrWrite( 9, 50, highmsg );
StrWrite( 10, 50, lowmsg );
SetCurPos( 9, 56 );
printf( "%lu", *++product ); /* Display high and low */
SetCurPos( 10, 56 ); /* double-word of */
printf( "%lu", *--product ); /* unsigned product */
s1 = *product; /* Copy low word to stack */
}
else
{
SetCurPos( 9, 56 );
printf( "%li", s1 ); /* Display signed product */
}
break;
/* Divide s2 by s1. */
case '/':
push( sign );
if( mode )
quotient = DivLong( s2, (int) s1, &remainder );
else
quotient = IdivLong( s2, (int) s1, &remainder );
ClearBox( 7, 9, 15, 9, 29 ); /* Clear entry */
ClearBox( 7, 9, 49, 10, 66 ); /* Clear result */
if( abs( (int) remainder ) >= (abs( (int) s1 ) >> 1) )
{
if( quotient >= 0 ) /* Round up if */
quotient++; /* remainder > s1/2 */
else
quotient--;
}
SetCurPos( 9, 56 );
if( mode )
printf( "%u", quotient ); /* Display result */
else
printf( "%i", quotient );
s1 = (long) quotient; /* Copy quotient to stack */
break;
}
}
clear_scrn( 7, 0, 24 ); /* Clear screen before exit */
SetCurPos( 23, 0 ); /* and set cursor to bottom */
return( 0 );
}
/* display_calc - Clears screen and displays calculator.
*
* Params: None
*/
void display_calc( void )
{
static char *calculator[19] =
{
" *** QuickAssembler Math Demonstration Program ***",
"",
"",
"ÚÄ Integer Calculator ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿",
"³ ³",
"³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³",
"³ ³ ³ ³ ³ ³",
"³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ³",
"³ entry ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³",
"³ result ³",
"³ 7 8 9 + - ? = Help ³",
"³ M = Mode (signed) ³",
"³ 4 5 6 * / S = Change sign ³",
"³ Q = Solve quadratic ³",
"³ 1 2 3 ÄÙ Enter C = Clear all ³",
"³ ³",
"³ 0 Esc = Quit ³",
"³ ³",
"ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ"
};
int i;
clear_scrn( 7, 0, 24 );
if( vconfig.display )
ClearBox( 31, 6, 2, 21, 77 );
else
ClearBox( 15, 6, 2, 21, 77 );
ClearBox( 7, 9, 14, 9, 29 ); /* Clear entry window */
ClearBox( 7, 9, 49, 10, 66 ); /* Clear result window */
for( i = 0; i < 19; i++) /* Display calculator */
StrWrite( i + 3, 3, calculator[i] );
}
/* display_help - Clears screen and displays help text.
*
* Params: None
*/
void display_help( void )
{
static char *help_msg[23] =
{
"The Integer Calculator works somewhat like a Hewlett-Packard hand " \
"calculator.", "Type the first integer, press Enter (ÄÙ), type the " \
"second integer, and press", "the desired operator key. The answer " \
"appears in the result window.",
"",
"To keep things simple, the Integer Calculator handles only long or " \
"short", "integers -- no floating point numbers allowed. Unsigned " \
"numbers can range", "from 0 to 4,294,967,295; signed numbers from " \
"-2,147,483,648 to 2,147,483,647.", "There's one exception to " \
"this: when dividing two numbers, the divisor must", "be a short " \
"integer from 0 to 65,535 for unsigned division, or from -32,768",
"to 32,767 for signed division.",
"",
"Press the M key to toggle between signed and unsigned arithmetic. " \
"Press the", "S key to change the sign of the number in the entry " \
"window. You'll notice", "the Calculator allows a change of sign " \
"only in \"signed\" mode.",
"",
"The Calculator uses coprocessor instructions (either real or " \
"simulated) to", "solve for the roots of a quadratic equation in " \
"the form",
"",
" A*x*x + B*x + C = 0",
"",
"Enter the three equation constants A, B, and C in order, then " \
"press Q. The", "roots, if they exist, appear in the result " \
"window. If the equation has only", "one root, then only a single " \
"number is displayed."
};
int i;
clear_scrn( 7, 0, 24 );
for( i = 0; i < 23; i++)
StrWrite( i, 0, help_msg[i] );
press();
}
/* push - Pushes values down one stack position: s3 becomes s2,
* s2 becomes s1, and s1 becomes the value in the entry window.
*
* Params: sign - Current sign status (0 = positive, 1 = negative)
*/
void push( int sign )
{
unsigned long place;
s3 = s2;
s2 = s1;
s1 = 0;
place = 1;
if( entry[col - 20] )
{
s1 = (long) (entry[col - 20] - '0');
place = 10;
}
while( col > 20 )
{
s1 += place * (long) (entry[--col - 20] - '0');
place *= 10;
}
if( sign )
s1 = -s1;
ClearBox( 7, 9, 15, 9, 29 ); /* Clear entry window */
entry[0] = 0; /* Reinitialize entry string */
col = 20; /* Reset column count */
}
/* press - Prompt for keyboard signal to continue.
*
* Params: None
*/
void press( void )
{
SetCurPos( 24, 49 );
printf( ". . . press a key to continue" );
SetCurPos( 24, 47 );
getch();
}

Some files were not shown because too many files have changed in this diff Show More