home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
xbase
/
compiler
/
doobject
/
do.doc
< prev
next >
Wrap
Text File
|
1991-08-23
|
165KB
|
4,621 lines
dObject Version 1.0 User Guide
Object-Oriented Programming Language for DBASE(tm)
Copyright (c) 1991 Intelligent Systems Research
All Rights Reserved
dObject Version 1.0 (c) 1991 Intelligent Systems Research
1.0 Introduction
1.1 Introduction
Welcome to Object-Oriented programming for DBASE(tm) ! dObject is an
object-oriented programming language with built-in base classes for
handling DBASE data, memo, and index files. Using dObject, you can
build complex applications that use your existing DBASE files and a
class library of over 15 classes and 300 methods. You can define
your own classes and methods that inherit the features of the base
classes. You can create new DBASE data, memo, and index files, and
you can write graphics and full-color windowed hypertext applications
that display your DBASE data.
dObject includes the following features:
* a fast, efficient interpreted language for writing
object-oriented DBASE applications
* a built-in full screen text editor callable from your
applications with hypertext on-line help
* over 300 built-in methods for integer and real
arithmetic, characters, strings, and dates
* a text-mode windowing system
* a graphics system based on the Borland BGI
* a pop-up menu facility
* DBASE-like SAY and GET output to windows, and code for a
full screen DBASE field editor
* output logging to printers and DOS text files
* LAN-compatible row and file locking of DBASE files
* a powerful GREP-like pattern matching function for
strings and DBASE character fields
* a hypertext facility linked to DBASE
* multi-dimensional arrays
* an advanced Collection class for managing complex data
structures
* a C-style preprocesssor for constant definitions and
program text inclusions
- 2 -
Chapter 1: Introduction
dObject provides the following advantages over the DBASE programming
language:
* facilities for defining classes and methods that are far
superior to the UDF facility in DBASE, including support
for inheritance and polymorphism
* advanced date handling including international formats,
julian dates, and date arithmetic
* facilities for providing sophisticated user interfaces
for DBASE(tm) applications, including use of multiple,
overlapping full-color windows and pop-up menus
* facilities for building hypertext applications that use
DBASE data and index files
* graphics
1.2 Manual Overview
This manual is both a user guide and a reference guide to dObject.
The chapters include:
* Chapter 1 - Introduction
* Chapter 2 - Getting Started
* Chapter 3 - dObject Statements
* Chapter 4 - dObject Classes
* Chapter 5 - Numeric Classes
* Chapter 6 - Logical Operations
* Chapter 7 - Characters and Strings
* Chapter 8 - Dates
* Chapter 9 - Windows and Menus
* Chapter 10 - Arrays and Collections
* Chapter 11 - Files and Devices
* Chapter 12 - DBASE File Programming
* Chapter 13 - BGI Graphics
- 3 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
1.3 How to Contact ISR
If you need technical support or would like to contact Intelligent
Systems Research with comments, suggestions, or questions about
dObject, please write to us at:
Intelligent Systems Research
P.O. Box 3690
Chicago IL 60654 USA
(312)-878-6054
CompuServ: Send E-mail to userid 70304,2520
Please include your dObject version number, your computer make and
model number, and your operating system make and model number if you
have technical questions or need detailed technical support.
2.0 Getting Started
2.1 Hardware Requirements
dObject requires the following minimal hardware configuration:
* an 80286, 80386 or 80406 CPU
* 640KB main memory
* a hard disk drive
* MS-DOS 3.0 or above
2.2 Installing dObject
The shareware version of dObject does not need to be installed beyond
the "unzip" of the distribution .ZIP file. The files DO.EXE,
HELP.DBF, HELP.DBT, HELP.NDX, ERROR.DBF, ERROR.NDX, and DO.CFG should
reside in the hard disk directory "DOBJECT".
The registered version of dObject comes with an INSTALL program on
the distribution diskette. The INSTALL program will prompt you for
the name of a directory to create on your hard disk, and then copy
the dObject distribution files to that directory. If you wish, you
can duplicate this yourself by issuing the DOS commands below:
C:\>md dobject
- 4 -
Chapter 2: Getting Started
C:\>cd dobject
C:\DOBJECT>copy a:do.exe
C:\DOBJECT>copy a:do.cfg
C:\DOBJECT>copy a:*.dbf
C:\DOBJECT>copy a:*.dbt
C:\DOBJECT>copy a:*.ndx
C:\DOBJECT>copy a:*.do
C:\DOBJECT>copy a:*.bgi
C:\DOBJECT>copy a:*.chr
You should also specify the DOBJECT directory as one of the PATH
options in your DOS AUTOEXEC.BAT file. dObject will always look in
the directory that the DO.EXE file is in for the HELP and ERROR
databases (including memo and index files). Make sure that when you
install dObject, all these files are in the same directory as the
executable file DO.EXE, otherwise the on-line help and error
reporting systems will not work properly.
Because dObject provides direct access to existing DBASE III format
files, and becuase dObject uses several DBASE III files in its
runtime environment, you should set the DOS FILES and BUFFERS option
in your config.sys file to at least the following values:
FILES=20
BUFFERS=20
To run the BGI demonstration program (BGIDEMO.DO) you must also first
define a DOS environment variable named BGIPATH. This variable must
contain the name of the directory where the supplied BGI drivers and
font files are stored. If you install dObject in the directory
C:\DOBJECT, you should add this line to your autoexec.bat file:
SET BGIPATH=C:\DOBJECT
2.3 Running dObject
To run dObject, at the DOS prompt type "do":
C:\>do
dObject Version 1.0 (Shareware)
Copyright (c) 1991 Intelligent Systems Research
Please register this version for support and updates
Press any key to continue...
- 5 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
Pressing any key at this point will cause dObject to issue the
"dObject> " prompt and accept commands. (The registered version of
dObject goes directly to the "dObject> " prompt without pausing;
this is a small reminder to register the shareware version !). To
run a dObject source program directly from the DOS prompt, type "do"
followed by the name of the file to run, with a default extension of
"DO". For example, to run the dObject program in the file "demo.do"
in the current DOS directory, issue the command:
C:\> do demo
3.0 dObject Statements
3.1 Statements
dObject accepts statements at the "dObject>" prompt using free-form
input. Statements can be entered in any number of lines but must be
terminated with a semicolon. dObject will prompt for statement
continuation with the "more>" prompt until a semicolon is entered.
dObject accepts the following legal statements:
STATEMENT DESCRIPTION
help; enter online hypertext help system and
display table of contents
cls; clear screen (current window)
exit; exit dObject and return to DOS (also
recognizes "quit;")
edit <filename>; edit file (default extension .DO) ESC
- exit without saving changes; F10 -
exit and save changes
for(statement;exp;statement) execute statements for range of values
<statements>
while <exp> <statements> while expression is true execute
statements
if <exp> <statements> else conditional execution of statements
<statements> with else clause
if <exp> <statements> conditional execution of statements
do <filename>; execute statements in file (default
extension .DO)
dos; suspend dObject and shell to DOS
return(<exp>); return expression as method result
show <item>; shows internal information about
dObject. "show classes" shows defined
classes, "show methods" shows defined
methods, "show set" shows SET
variables, "show variables" shows all
defined user variables
switch (exp) {<cases>} conditional execution of cases
? <exp>[,<exp>...]; print expression values in current
- 6 -
Chapter 3: dObject Statements
window
<exp>; evaluate the expression
dObject accepts comments within source programs using the conventions
of the "C" programming language. Comments must begin with the
characters "/*" and end with the characters "*/". All characters in
between, including spaces, tabs, and newlines, are treated as comment
characters and are ignored by the interpreter. The following example
demonstrates legal dObject comments:
/*
this is a comment
*/
method Int::zero(self) /* comments are allowed anywhere */
{
return(0); % this is an end-of-line comment
}
To exit from dObject and return to the DOS prompt, issue the "exit"
command:
dObject> exit;
To review the on-line hypertext help, issue the "help" command:
dObject> help;
dObject provides a way to execute other dObject program source files
through the use of the "do" command with a filename to execute.
dObject will supply a default extension of ".do" if you do not supply
one. For example, to execute the statements in the file "test.do",
issue the statement:
dObject> do test;
3.2 Errors
If you make an error in a dObject statement, dObject will attempt to
locate the error and print out the offending statement with a
relevant error message. The error display will be shown in an Error
window displayed in the lower left corner of the screen. The
complete list of error codes generated by dObject is contained in the
supplied file ERROR.DBF.
- 7 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
To produce the error displauy, dObject calls the built-in
Int::onError() method and passes it the Int error code of the error.
You can re-define this method in your applications to change the way
that error messages are displayed:
/*
demonstration of the Int::onError() method
this method is called whenever dObject detects a parse or runtime
error in a program; normally dObject creates a 1-line window
at the bottom of the display screen and prints out the error
number, an error message, and the statement where the error
was detected. you can re-define this method to handle errors
for your own applications
*/
method Int::onError(self)
{
w = new(Window,1,112,112," Error ",10,10,5,50);
db = new(Dbffile,"error");
ndx = new(Ndxfile,db,"error");
seek(db,self);
? "ERROR ",self,": ",msg;
readchar();
remove(w);
}
/*
cause an error
*/
exit(10002);
3.3 Breaks
To interrupt a dObject program during execution, press the Control
key and the Break key at the same time (Ctrl-Break). This will cause
dObject to issue an error message for the break, and then return to
the dObject> prompt.
3.4 Preprocessor
dObject includes a built-in preprocessor for defining compile-time
constants and file includes. dObject accepts constant definitions of
the form:
#define NAME VALUE
- 8 -
Chapter 3: dObject Statements
where NAME is the name of the constant to define, and VALUE is the
value to assign to it. Values can be any single token of text, or
any string of text delimited with double quotes. For example, the
following are all legal dObject constant definitions:
/*
define some commonly used integer codes for characters
*/
#define ESC 27
#define CR 13
#define TRUE "T"
/*
define an alias name for a dObject function
*/
#define CURRENT_DATE "date()"
Whenever dObject encounters a defined constant anywhere in the text
of a program, it will substitute the defined text before parsing and
executing the statement. Use of this technique makes your programs
more readable and understandable. For example, the following code
uses the constants defined above:
/*
read a character from the keyboard
*/
c = inkey();
if(c == ESC) ? "the escape key was pressed";
if(c == CR) ? "the return key was pressed";
A file can be included in the source text before it is parsed by
using the "include" directive:
#include "keydef.do"
3.5 Variables
In dObject, variables are used to store any kind of value in memory
for use by your program. The names of these variables must begin
with a lower case alphabetic character (since upper case names are
reserved for class names); and can then contain any number of
alphabetic or numeric characters, as well as the underscore. The
variable name must not be one of the following dObject reserved
keywords: while, for, if, then, else, do, return or method.
For example, the following are legal dObject variable names:
* a
- 9 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
* a1
* my_variable
The following are NOT legal variable names:
* 1a (begins with a numeric character)
* My_variable (begins with an uppercase character)
* my-variable (uses the '-' character)
* while (uses the reserved dObject keyword while)
Variables use memory space within dObject that can be re-used later
if your program no longer needs the variable. To reclaim the storage
space for a variable, send the "release" message to an Exp object
containing the name of the variable:
dObject> a = 32;
dObject> release(#a);
3.6 Literals
Literal values are sequences of numbers, letters, and special
characters that are interpreted as actual values by dObject, not
variable names. dObject accepts literal values in the following
formats (note that hex integer constants are defined using a leading
dollar sign):
CLASS FORMAT EXAMPLE
Nil: nil nil
Date: mm/dd/yyyy 5/10/1990
Char: 'c' 'a'
String: "ccc" "this is a string"
Int (decimal): n 123
Int (hex): $n $1ff
Long: nL 123L
Real: n.d 12.34
Logical: T or F T
Collection: [v1,v2,v3...] [1,2,$1ff,T,3.3,"four",'5',(1,"one"),5/10/90]
Exp: #exp #date()
3.7 Expressions
Expressions in dObject are combinations of literal values, variable
names, and "messages". Messages are sent to objects in dObject either
as operators or as named messages. Operators are special characters
(usually one or two characters) that have a special meaning when
- 10 -
Chapter 3: dObject Statements
applied to values, and are generally used in messages of the form
"object operator object". For example, in dObject the expression 1 +
2 means send the "plus" message to Int 1 with an argument of Int 2.
Named messages are always of the form name(object,args), where "name"
is the name of the message to send, "object" is the object to send
the message to, and "args" is zero or more values to use as arguments
to the message. For example, the expression "clear(w)" in dObject
means send the "clear" message to the object stored in the variable
"w" (presumably a Window object) with no argument. The only exception
to this convention are messages sent to the Nil object, which
effectively have no object or arguments in the calling sequence. The
expression "memory()" means send the "memory" message to the Nil
object.
dObject allows the assignment of values and expressions to variables
through the use of the assignment operator, denoted by the equals (=)
sign:
dObject> v = 1+2*3;
dObject recognizes literal expressions beginning with the '#'
character and defers evaluation of the expression until runtime.
Such expressions are useful when you are actually passing an
expression to a method to evaluate later, such as using the built-in
"avg" method on a DBASE(tm) file. The argument to the "avg" method
is an expression to evaluate for each record in the file. For
example, the following statements print the average length of the
"lname" field within a DBASE(tm) file:
dObject> db = new(Dbffile,"patient");
dObject> ? avg(db,#len(trim(lname)));
Passing the literal expression #len(trim(lname))) instructs dObject
to defer evaluating the expression until the "avg" method runs; if
you forget the '#' sign before the expression, dObject will evaluate
the expression and pass the resulting Int value to the "avg" method
as an argument, which will result in an error !
3.8 Program Control Statements
dObject provides the "for", "while" and "switch" statements to
control the flow of program execution, all of which are similar to
their counterparts in the C programming language. The "for"
statement executes a block of statements while an iteration
expression is true:
- 11 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
/*
demonstrate the for statement
*/
for(i=0;i<10;i=i+1) ? i;
In this case, dObject will execute the first statement in the for
expression, i=0, and then execute the statements in the block after
the for expression. After each pass through the block, the statement
i=i+1 will be executed, and the expression i<10 evaluated. If the
expression is true dObject will continue to execute the statement
block. Execution stops whenever the expression is found to be
false. After the for statement is completed any variables used in
the statements will still exist; in the above example i will have
the value of 11 after the for statement executes.
The "while" statement executes a block of statements while an
expression evaluates to logical "true":
/*
demonstrate the while statement
*/
i = 1;
while(i < 10) {
? " i = ",i;
i = i+1;
}
The "switch" statement is similar to the one found in the C
programming language. An expression is evaluated and then matched
against the values found in a series of "case" statements. The first
case matching the expression value is executed:
/*
demonstrate the switch statement
*/
i = 3;
switch(i) {
case 1: ? "i is one ";
case 2: ? "i is two ";
case 3: ? "i is three ";
case 4: ? "i is four ";
}
In the above example only the statement ? "i is three " would
execute within the switch.
- 12 -
Chapter 3: dObject Statements
3.9 Editing Text Files
dObject provides a built-in full screen text editor for creating and
modifying text files, including dObject source files. To invoke the
editor, issue the "edit" command followed by the name of the file in
the current directory to edit. dObject will supply a default
extension of ".DO" for the file to make it easy to edit dObject
source files. For example, to edit the file "test.do", issue the
command:
dObject> edit test;
dObject will invoke the text editor in the current window, which by
default is the full screen. Editing can occur in other windows by
first creating the window and the issuing the "edit" command. The
built-in editor is similar to the WordStar(tm) text editor and
responds to the following keystroke commands:
FUNCTION KEY
View dObject help for word at cursor Ctrl-F1
Move cursor right one character right arrow
Move cursor left one character left arrow
Move cursor up one line up arrow
Move cursor down one line down arrow
Scroll up one line Ctrl-W
Scroll down one line Ctrl-Z
Move cursor right one word Ctrl-Right arrow
Move cursor left one word Ctrl-A
Move cursor to right end of line End
Move cursor to left end of line Home
Move cursor to top of window Ctrl-Home
Move cursor to bottom of window Ctrl-End
Move cursor up one screen PgUp
Move cursor down one screen PgDn
Move cursor to top of file Ctrl-PgUp
Move cursor to bottom of file Ctrl-PgDn
Delete character at cursor Del, Ctrl-G
Delete character left of cursor Backspace
Delete word at cursor Ctrl-T
Delete line at cursor Ctrl-Y
Delete left from cursor to start of line Ctrl-Q T
Delete right from cursor to start of line Ctrl-Q Y
Mark beginning of block Ctrl-K B
Mark end of block Ctrl-K K
Copy (insert) marked block at cursor Ctrl-K C
Move (insert) marked block at cursor Ctrl-K V
Delete marked block Ctrl-K Y
Write marked block to diskfile Ctrl-K W
Write marked block to printer Ctrl-K P
- 13 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
Block select on/off Ctrl-K M
Copy block to pastebuffer Ctrl-K I
Move block to pastebuffer Ctrl-K Y
Paste Ctrl-U
Search Ctrl-F3 or Ctrl-Q F
Search again Shift-F3 or Ctrl-O
Replace F4
Replace again Shift-F4 or Ctrl-L
The key assignments for the editor are contained in the file "do.cfg"
that is loaded at runtime by dObject. You can change these default
combinations by calling the Nil::setupKeyboard() method from the
dObject prompt, changing the key assignments using the menu choices
provided, and then saving the current key configuration using the
String::saveConfig method. The following example illustrates this
procedure:
dObject> setupKeyboard();
dObject> saveConfig("new.cfg");
dObject> exit;
C:\DOBJECT:> rename do.cfg old.cfg
C:\DOBJECT:> rename new.cfg do.cfg
From within the Nil::setupKeyboard() method, a series of menu choices
will be presented that allow you to choose the particular functions
within the editor to be re-assigned to a key or keystroke
combination. To redefine a command's keystroke(s), highlight the
menu item for the command using the arrow keys and press Enter. In
the input box that appears, you can define one or two sets of
keystrokes for the command. Press Enter to skip over the first set
of keystrokes, or press the new key combination for the first setup
and then press Enter. When the cursor is in the second column, press
Enter to skip the second setup, or press a new key combination
followed by Enter. To abort this process at any time press the Esc
key.
Your application can load a special .CFG file at runtime using the
String::loadConfig method and passing it the name of the file to
load. The file should be one of the supplied .CFG files that comes
with dObject, or a .CFG file you have created using the procedure
described above.
Comprehensive on-line help for editor commands is available from
within the editor by pressing the F1 key. Help for dObject
statements and built-in classes and methods is available from within
the editor by placing the cursor on a dObject keyword, class name, or
method name and pressing the Ctrl-F1 key.
- 14 -
Chapter 3: dObject Statements
3.10 Input and Output Statements
The "?" statement prints the value of an expression onto the current
window, followed by a carriage return and line feed:
dObject> ? 1+1;
2
dObject>
The String::accept() method provides a simple way to write a prompt
and read Strings from the keyboard:
dObject> line = accept("enter value> ");
For a detailed description of the input, output, and file handling
capabilities of dObject, refer to the chapters titled "Files and
Devices" and "Windows and Menus" later in this manual.
3.11 Output Logs
dObject will also log the output from the "?" command to a file
and/or an attached printer using the built-in log feature. Pressing
the ALT-P key combination will display a popup menu showing the
current on/off status of the logs to the printer and to the file
PROLOG.LOG. To toggle the status from off to on and vice versa, use
the arrow keys to position the menu bar, and press the RETURN key to
toggle the value. Press the ESC key to exit the menu and return to
the dObject prompt.
3.12 Environment Variables
dObject maintains a small set of environment variables that can be
set using the String::set() method and interrogated by the "show"
command. These environment variables are:
VARIABLE DEFAULT DESCRIPTION
echo F when true, causes dObject to echo the
statement just about to be executed to the
current window
hyperhelp T when true, allows use of Ctrl-F1 key from
within editor to access dObject help stored
in HELP.DBF file; when false, disables
Ctrl-F1
newline nl dObject will print this value at the end of
each "?" statement
prompt "dObject>" the String to be used as the command prompt
- 15 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
softseek F when true, all String comparisons return true
(T) if a "partial match" occurs; that is if
the first string being compared is a
substring of second string. when off,
dObject returns true only if the strings
being compared are identical, including
trailing blanks
space "" dObject will print this value between
expressions in the "?" statement; normally
set to a null String
status T when true, status lines appear for text
editor, window resize, etc. when false,
turns off display of all status lines
step F when true, causes dObject to pause between
executing statements and print the message:
Press SPACE to continue, ESC to abort...
pressing the space key executes the next
statement pressing the ESC key returns to the
dObject> prompt
To set an enviroment variable to a value, use the String::set method,
with the "self" argument set to the name of the SET variable:
dObject> set("echo",T);
For example, to change the dObject prompt, set the prompt variable:
dObject> set("prompt","--> ");
-->
To show the value of all the environment variables, use the "show
set" command:
dObject> show set;
echo=logical(false)
step=logical(false)
softseek=logical(false)
status=logical(true)
hyperhelp=logical(true)
prompt=string("dObject> ")
space=char(' ')
The value of a particular set variable is available by calling the
String::set() method with self set to the name of the set variable to
retrieve and with no other arguments:
dObject> ? set("echo");
F
- 16 -
Chapter 3: dObject Statements
To show all the currently defined dObject variables, use the "show
variables" command:
dObject> a = 1;
dObject> b = 2;
dObject> show variables;
a=1
b=2
To show all the classes you have defined in a dObject session beyond
the built-in classes, use the "show classes" command (refer to the
next chapter for a description of how to create these classes):
dObject> show classes;
To show all the methods currently defined, use the "show methods"
command.
3.13 The RETURN Statement
The return statement is used to return a value from a dObject method
back to a calling program. The format of this statement is
return(exp), where exp is any dObject expression as described above.
The use of this statement is appropriate only when defining you own
dObject classes and methods, a topic that is described in detail in
the next chapter.
4.0 dObject Classes
4.1 Objects
dObject provides a powerful facility for you to write complex
applications using the "Object" paradigm. With this way of thinking,
you define an object as something within the problem you are trying
to solve that you want the computer to represent and store
information about. For example, in a small business accouting
system, the objects might include Companies, Departments, Employees,
Products, and Accounts, to name but a few. Each of these objects has
a certain correct behavior in the computer, such as a behavior to add
a new Employee to a Company, or a behavior for calculating the profit
from the sale of a Product to a Customer.
In dObject, the object types within the application are called
"Classes", and the rules that tell the computer how a class is to
behave are called "Methods". Each class has a set of methods that it
- 17 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
knows about that allow it to perform calculations on the class.
dObject provides a large library of built in classes, each with its
own set of methods, that allow you to create complex applications
right away. However, to fully exploit the power of object-oriented
programming, you will eventually want to create your own classes and
methods that apply directly to the problems you want to solve. You
create these new classes and methods by building them on top of the
existing classes and methods.
4.2 Class Definitions
To create a new object class, use the "inherit" message on an already
existing dObject class:
inherit(Parentclass,Newclass,variables);
where "Newclass" is the name of the new class to define,
"Parentclass" is the class to inherit from, and "variables" is an
array of strings that name instance variables within the class. In
dObject, the names of classes must always begin with an uppercase
letter, followed by upper or lower-case characters or numerals. For
example, the statement:
inherit(Date,Mydate,["julian"]);
You should use the "Nil" class as a parent class that does not
inherit data or methods from any parent.
To create a variable of a given class type, use the "new" message:
v = new(Class,arguments)
where "v" is the name of the variable to create, and "Class" is the
object class of the variable. For example, to create a new instance
of the "Mydate" class and store it into a variable named "d", use the
statement:
d = new(Mydate);
dObject provides a number of base classes as building blocks,
including:
* Nil - an empty class
* Int - 2-byte signed integers
- 18 -
Chapter 4: dObject Classes
* Long - 4 byte signed integers
* Real - floating point numbers
* Char - single characters
* String - strings of characters (up to 64K in length)
* Logical - true (T) or false (F)
* Date - dates
* Array - an array of object at locations indicated by an
index
* Collection - an ordered collection of objects
* File - DOS ASCII text files and devices (such as the
printer)
* Exp - literal dObject expressions that can be passed as
arguments
* Dbffile - DBASE files
* Ndxfile - DBASE index files
* Address - addresses of other objects
The class of any dObject variable can always be found by sending the
object the built-in "class" message:
dObject> ? class(5/10/91);
Date
dObject> ? class("this is a test");
String
dObject> ? class(T);
Logical
4.3 Method Definitions
To create a named method for a class, use the format:
method Class::name(self,arguments)
{
statements...
}
- 19 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
Values are returned to the calling program through the use of the
"return" statement. This should be the last statement executed from
within a method. Methods that do not use a "return" statement have a
return value of Nil.
The special variable "self" always refers to the specific instance of
the object that the method is being performed on. You can treat
"self" as any other argument in the calling sequence. For example:
method Mydate::asString(self)
{
return(asString(slot(self,"julian"));
}
defines a method for the "Mydate" class to convert itself to a
String.
To define an operator for a class, use the character representing the
operator as the method name. For example, to define the '+' operator
for the Mydate class:
method Mydate::+(self,d)
{
return(asDate(julian(self) + julian(d)));
}
Variables within a class can be set by using the "replace" method,
and referenced by the "slot" method. However, these two methods are
only available from within methods defined for the class! This
implements an important feature of object-oriented programming: data
hiding. Using data hiding, it is good programming form to provide a
method that returns the value of a variable within a class, instead
of allowing a calling program to access that variable directly. That
way, if the implementation of the object changes at some later date,
and the variables within the class change, only the methods for the
class need to understand the change ! The "outside world" still
accesses information about the class through the methods.
4.4 Private Methods
By default, methods defined using the syntax described above are
"public" in scope - they are available to any other method or main
program that wants to use them. In some cases, however, you may wish
to define methods that are hidden from other methods in the same way
that variables are hidden. dObject lets you do this by substituting
the keyword "private" for "method" in the method definition. The
following example shows how to define a private method for a class:
- 20 -
Chapter 4: dObject Classes
private Mydate::yearPlusOne(self)
{
return(year(self)+1);
}
In the example above, the "yearPlusOne" method is only available to
other methods of the Mydate class. Attempts to call it from a method
of another class or from a main program will generate an error
message.
The following example illustrates the use of a private method:
/*
demo of a private method for a class
private methods are only callable from within a method for a class
*/
inherit(Nil,Temp,[]);
private Temp::testPrivate(self)
{
? "within testPrivate";
}
method Temp::test(self)
{
? "enter Temp::test";
testPrivate(self);
? "exit Temp::test";
}
v = new(Temp);
test(v); % this will work, Temp::testPrivate will be called by Temp::test
? "the next statement will cause an error !...";
testPrivate(v); % this will cause an error !
4.5 Friend Classes
In some cases, you may wish to share the variables and/or the private
methods defined for a class with another class. In this case,
dObject provides the Exp::friend() method to allow such access. The
following example shows how to define one class as a friend of
another:
/*
demo of a private method for a class
private methods are only callable from within a method for a class
*/
- 21 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
inherit(Nil,Temp,[]);
inherit(Nil,Temp2,[]);
/*
defining class Temp2 as a friend of class Temp
means that methods of Temp2 can access variable and private
methods of Temp
*/
friend(Temp,Temp2);
/*
define a private method for Temp
*/
private Temp::testPrivate(self)
{
? "within Temp::testPrivate()";
}
/*
define a public method for Temp2 that creates a variable of
type Temp and calls a private method for it
*/
method Temp2::test(self)
{
? "enter Temp2::test";
v = new(Temp);
testPrivate(v); % this won't work unless Temp2 is a friend of Temp !
? "exit Temp2::test";
}
v = new(Temp2);
test(v);
4.6 Inheritance
dObject stores variables for classes you define by allocating storage
for a variable of its parent class type, and storage for all the
variables defined in the "inherit" statement for its class. For
example, consider a class called "Time" that inherits its behavior
from the Date class. The "Time" class also contains internal
variables for hours, minutes, and seconds, as defined in the
following statement:
dObject> inherit(Date,Time,["hours","minutes","seconds"]);
A new variable of type "Time" can be constructed as follows:
dObject> t = new(Time,7/20/1990,1,2,3);
- 22 -
Chapter 4: dObject Classes
Internally, the variable "t" would be stored as an object of class
"Time", with 4 internal variables. The first variable is of type
Date (the parent class), with the value of 7/20/1990. The remaining
variables are the values for "hours", "minutes", and "seconds" as
defined in the inherit statement above, with values of 1, 2, and 3
respectively.
dObject classes "inherit" all the variables and methods from their
parent class. If you send a message to a variable of a class you
create and a method for the message has not been defined, dObject
will begin searching backwards through the parent class(es) to try to
find a method definition it can use. If a method is found, the
variable storing the parent class value is passed to the method,
without any of the variables for the original class. This process
continues until no more parent classes are found.
For example, if you send the "asString" message to a Time variable as
defined below, and you have not defined a version of "asString" for
the Time class, then dObject will take the parent Date value and send
it the "asString" message:
dObject> inherit(Date,Time,["hours","minutes","seconds"]);
dObject> t = new(Time,7/20/1991,1,2,3);
dObject> ? asString(t);
7/20/1991
4.7 Parameter Passing
dObject normally passes arguments to methods by creating an internal
stack and pushing the value for all the arguments to the method onto
it. This is exactly the way the C language calls functions.
However, in dObject, this implies that you cannot internally change
the value of a variable within a class, but must instead return a
copy of the variable containing the change. This leads to an easy
error to make:
/*
define a class for Money
*/
inherit(Int,Money,["cents"]);
method Money::setCents(self,c)
{
return(replace(slot(self,"cents"),i));
}
/*
- 23 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
create a variable of type Money
*/
m = new(Money);
setCents(m,100); % this is wrong !
While it may appear simple to set a Money variable to a value from a
calling program, be careful ! You must remember to store the
returned copy of the variable back into itself:
/*
assign "m" a value the wrong way
*/
setCents(m,100); % this returns a copy of m with "cents"=100 that is lost
/*
assign "m" a value the right way
*/
m = setCents(m,100); % this stores the copy back in m !
dObject allows a program to circumvent the need to always pass copies
of variables around through the use of the Address class. Using the
"address-of" operator (the "&" symbol, as in C), you can instead pass
the address of a variable to a method:
setCents(&m,100);
However, to do this correctly, the method must be expecting an
address of a variable and not a copy of the variable itself. This is
done by using an asterik before the argument in the method definition
wherever an address is to be used. The following example shows how
to define and use a method that replaces the value of an internal
class variable directly in memory:
/*
define a new version of the setCents method that
replaces a memory location and does not return a copy
*/
method Money::setCents(*self,c)
{
replace(slot(*self,"cents"),c);
}
/*
now this is OK !
*/
m = new(Money);
setCents(&m,100); % m will be updated in-place
- 24 -
Chapter 4: dObject Classes
To access the contents of an address, use the "contents" operator
(the asterik character), again just like in the C language:
dObject> ?class(&1);
Address
dObject> ? *&1;
1
4.8 Space Management
To reclaim the space used by a variable, send an expression
containing the name of the variable the "release" message:
dObject> a = 1;
dObject> release(#a);
To reclaim the space used by a method definition once it is no longer
needed by your program, use the "release" method of the Exp class.
Send the message to the Class name for the method you wish to delete,
and pass the message a String argument containing the method name:
dObject> release(Myint,"value");
To reclaim all the space used by a class, including its definition,
its methods, and any variables, use the releaseClass method:
dObject> releaseClass(Mydate);
4.9 Input and Output
To print the value of an object (while executing the "?" command, for
example), dObject first sends the object the "asString" method to try
to convert it to a String. If this succeeds, the resulting String is
printed and the next object to print is processed. Each of the
built-in classes provided in dObject has an asString method defined
for it. If there is no such method for the class, dObject attempts
to print a representation of the internal form of the object. For
user defined classes, this printout will be of the form:
object(Class,[slot(Name,Value)...])
4.10 Sample Application
As a final example of how to create classes and methods, the
following program completes the implementation of the abstract class
"Money" used in the examples above:
- 25 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
/*
this is an example of a class to handle money as an abstract type
first, define a Money class with a variable to hold an
integer number of cents; this will be converted into
dollars and cents whenever the Money variable is converted to a String
*/
inherit(Int,Money,[]);
/*
set the number of cents in self
NOTE: self must be passed by address for this to work !
*/
method Money::setCents(*self,c)
{
replace(parent(*self),c);
}
/*
return the number of dollars in self
*/
method Money::dollars(self)
{
return(self/100);
}
/*
return the number of cents in self
*/
method Money::cents(self)
{
return(self - (dollars(self)*100));
}
/*
the "asString" method allows a Money variable to be converted
to a String and/or printed
*/
method Money::asString(self)
{
return("$ "+asString(dollars(self))+"."+format(cents(self),"%02d"));
}
method Int::asMoney(self)
{
return(new(Money,self));
}
/*
test case
*/
m = new(Money,100);
setCents(&m,104);
- 26 -
Chapter 4: dObject Classes
? m;
? asMoney(m+1);
? asMoney(m*10);
5.0 Numeric Classes
5.1 Numeric Classes
dObject supports three types of numeric classes: Int, Long, and
Real. Class Int supports signed 2-byte integer values between
-32,768 to 32,767. Long values are signed 4-byte integer numbers in
the range -2147483648 to 2147483647. Real numbers are 8 bytes long
and in the range -1e+307 to 1e+308. dObject provides operators for
performing arithmetic on Int, Long and Real classes. For example, to
add two integers together to get a third, send the "plus" message to
the first integer, using the second integer as an argument. This is
accomplished in the statement:
dObject> n = 1+2;
dObject> ? n;
3
where the variable "n" will be assigned the value Int 3. dObject
responds to the '+' (plus), '-' (minus), '*' (multiply), and '/'
(divide) operators on both Int and Real variables. Mixed mode
arithmetic is also supported for calculations involving Ints and
Reals, in which case the result is always Real. Mixed mode
arithmetic involving Long values is not supported.
A wide variety of named messages are supplied for numeric classes,
including:
* max(self,Int), max(self,Real), max(self,Long) - returns
max value of self and arg
* min(self,Int), min(self,Real), min(self,Long) - returns
min value of self and arg
* abs(self) - returns absolute value of self (Int or Real)
* log(self) - returns log base e of self (Real)
* log10(self) - returns log base 10 of self (Real)
* sqrt(self) - returns square root of self(Real)
- 27 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
* sin(self) - returns sine of self (Real, self in radians)
* cos(self) - returns cosine of self(Real, self in radians)
* tan(self) - returns tangent of self (Real, self in
radians)
Refer to the accompanying file "CLASSLIB.DOC" for a complete
description of the built-in numeric methods and operators.
Of course, you can define new methods for the numeric classes if you
so choose. This example show defining a new method "factorial" for
the Long class, which calls itself recursively:
/*
define a recursive factorial method for the "Long" class
*/
method Long::factorial(self)
{
if(self <= 1L) return(self);
else return(self*factorial(self-1L));
}
/*
calculate some factorials
*/
i = 0;
while(i < 10) {
? i," ",factorial(asLong(i));
i = i+1;
}
6.0 Logical Operations
6.1 Logical Operations
dObject provides the built-in class "Logical" for representing the
boolean values of "true" and "false". dObject also provides built-in
operators for a variety of comparison operations between classes that
result in a Logical value:
OPERATOR NAME CLASS(ES) DESCRIPTION
[eq][eq] equal all returns true if self
and arg are equal
!= not equal all returns true if self
and arg are not
equal
- 28 -
Chapter 6: Logical Operations
> greater than Int,Real,Char,String returns true if self
greater than arg
>= greater than/eqInt,Real,Char,String returns true if self
greater than or
equal to arg
< less than Int,Real,Char,String returns true if self
less than arg
<= less than/eq Int,Real,Char,String returns true if self
less than or equal
to arg
To create a logical value, use the "new" method, a literal Logical
value, or make an assignment using one of the comparison operators
above:
dObject> l = new(Logical);
dObject> l = T;
dObject> l = 1 < 2;
7.0 Characters and Strings
7.1 Characters and Strings
dObject provides the built-in classes "Char" and "String" for
handling character calculations. A Char literal should be a single
character surrounded by single quotes, while a String literal can be
any number of characters delimited by the double quote character.
To create a string, use the "new" method or make an assignment using
a literal:
dObject> s = new(String);
dObject> s2 = "this is a string";
To find the length of a String, use the "len" method:
dObject> ? len(String);
16
Strings respond to the normal set of comparison operators (==,!=, <,
<=,>, >=). Trailing blanks can be removed from a String by the
"trim" method:
dObject> ? len(trim("aaa "));
3
- 29 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
Strings can be concatenated together using the "+" operator:
dObject> a = "string1";
dObject> b = "string2";
dObject> ? a + " and " + b;
"string1 and string2"
To access a particular character in a String, use the "at" method:
dObject> c = at("test",2);
dObject> ? c;
e
The same built-in text editor that is used by the "edit" command to
edit text files is callable as a method of the String class. This
causes the contents of the string to be edited in the current window,
and returns the value of the edited string. For a read-only display
of the string contents in the current window with no editing allowed,
use the "display" method:
dObject> s = "this is a string";
dObject> edited_string = edit(s);
dObject> display(edited_string);
dObject also provides String methods to interface directly with DOS.
A DOS command within a String can be executed using the "system"
method, passing it the command string in the "self" argument and an
Int indicator for resetting the screen to the state it was in prior
to executing the command string (0=do not reset, 1=reset):
dObject> cmd = "dir *.do";
dObject> system(cmd,0);
The value of a DOS environment variable can be accessed through the
"envSymbol" method:
dObject> s = envSymbol("path");
A named file can be edited using the "editFile" method:
dObject> editFile("test.txt");
The contents of an existing DOS file can be placed in a String very
quickly by the "fileString" method, where "self" is the name of the
file:
- 30 -
Chapter 7: Characters and Strings
dObject> text = fileString("test.do");
dObject> edit(text);
String values can be converted to Int, Real, Date, and Logical values
using the "asInt", "asReal", "asDate", and "asLogical" methods
respectively:
dObject> s = "123";
dObject> ? class(asInt(s))," ",asInt(s);
Int 123
String values can be forced to upper or lower case using the
"asUpper" and "asLower" methods:
dObject> s = "This is a Test";
dObject> ? asUpper(s);
THIS IS A TEST
dObject> ? asLower(s)
this is a test
dObject provides a pattern match function in the String::match()
method. This method matches a pattern against the string and returns
a Int index specifying the portion of the string that matched the
pattern:
dObject> s = "This is a test";
dObject> ? match(s,"is a test");
6
The special codes recogized by the String::match() method are those
recognized by the UNIX GREP utility and include:
* ' start-of-line anchor
* '$' end-of-line anchor
* '.' matches any character
* '[' start a character class
* ']' end a character class
* ' negates character class if 1st char
* '*' Keene closure (matches 0 or more)
* '+' positive closure (1 or more)
- 31 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
* '?' optional closure (0 or more)
There are other String methods provided by dObject that are described
in CLASSLIB.DOC.
8.0 Dates
8.1 Dates
dObject provides a rich set of methods for handling dates using the
built-in "Date" class. To create a new date variable, use the "new"
method, or a date literal:
dObject> d = new(Date);
dObject> d = 5/1/91;
The built in Nil::date() method returns the current system date as a
Date variable.
You can access the month, day, and year parts of a date using the
"month", "day", "year", and "century" methods. For example, the
expression below will return just the year of the current date as an
Int:
dObject> ? year(date());
You can also set the values of these parts of the date using the
"setMonth", "setDay", "setYear", and "setCentury" methods:
dObject> d = date();
dObject> d = setMonth(d,1);
dObject supports the addition and subtraction of an integer number of
days to and from a Date variable, and also supports conversion of
Dates to a julian value. For example, to find the date that is 30
days from the current date:
dObject> future_date = date()+30;
The "asJulian" method returns a Real value that is the julian date
for a Date value. The Real::asDate method performs the inverse
operation, returning a Date for a given julian number:
dObject> j = asJulian(date());
dObject> d = asDate(j);
- 32 -
Chapter 8: Dates
Dates can be formatted into and from String variables in a variety of
formats, including international formats. dObject provides the
"asString" method for the Date class and the "asDate" method for the
String class to accomplish these format conversions. In both cases a
format String is passed to the method indicating how the date is to
be formatted or scanned:
/*
test the dObject date conversion functions
*/
? date();
s = asString(date(),"MMM DD/YY");
? s;
d = asDate(s,"MMM DD/YY");
? d;
The valid date format codes recognized by dObject are:
* CC 2-digit century
* YY 2-digit year
* MM 2-digit month
* MMM 3-char month (JAN, FEB, etc.)
* DD 2-digit day
These codes can be used in format strings to indicate how the date
should be formatted or scanned. For example, the following are
typical date formats:
* YY.MM.DD
* CCYY.MM.DD
* MM/DD/YY
* DD-MM/YY
* DD-MM/CCYY
* MMM DD/YY
As a final example, the following code implements the "cday" method,
which returns a String that contains the name of the day for the
date:
/*
this is an example of how to define methods for the built-in
Date class
- 33 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
"cday" returns a character string naming the day
*/
method Date::cday(self)
{
if(dow(self) == 1) return("Sunday");
if(dow(self) == 2) return("Monday");
if(dow(self) == 3) return("Tuesday");
if(dow(self) == 4) return("Wednesday");
if(dow(self) == 4) return("Thursday");
if(dow(self) == 5) return("Friday");
if(dow(self) == 6) return("Saturday");
}
/*
define the same function, using the "switch" statement
*/
method Date::cday2(self)
{
switch(dow(self)) {
case 1: return("Sunday");
case 2: return("Monday");
case 3: return("Tuesday");
case 4: return("Wednesday");
case 5: return("Thursday");
case 6: return("Friday");
case 7: return("Saturday");
}
}
/*
call the methods defined above
*/
? cday(date());
? cday2(date());
9.0 Windows and Menus
dObject provides classes that allow you to write professional-looking
applications that use character-cell windows and pop-up menus. The
"?" command, the "say" method of the Window class, and the built-in
"Field" base class all send their output to a specified window.
9.1 Windows
Windows are created using the "new" method, and passing it the window
number, window attribute, frame attribute, title, left corner y,x
position, and the y and x lengths for the window as parameters. The
x,y co-ordinates of a window or other object within a window are
- 34 -
Chapter 9: Windows and Menus
always counted down and right from the (0,0) origin in the upper left
corner. For example, to create a new window that is the size of the
entire screen, contains the title "test window", and has a white on
blue display color and a lite blue border:
dObject> w = new(Window,1,31,3,"test window",0,0,24,80);
Color attributes can be calculated from the following formula:
* Choose one foreground color and one background color
* Add the corresponding integer values below.
* Add 128 if you want whatever is displayed with that
attribute to blink
BACKGROUND FOREGROUND
Black 0 Black 0
Blue 16 Blue 1
Green 32 Green 2
Cyan 48 Cyan 3
Red 64 Red 4
Magenta 80 Magenta 5
Brown 96 Brown 6
White 112 White 7
Grey 8
Light Blue 24
Light Green 40
Light Red 72
Light Magenta 88
Yellow 104
White (High 120
Intensity)
You can also include the supplied file "COLORS.DO" that defines
symbolic names for the colors.
When the "new" method creates the window it also displays it
immediately and makes the new window the current window. To write
output to a window, you must first make the window current. You can
do this explicitly by sending the window the "shiftwindow" message:
dObject> shiftwindow(w);
You can always obtain the current window as a Window object through a
call to the Nil::currentWindow() method:
dObject> shiftwindow(currentWindow());
- 35 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
You can clear the contents of a window with the "clear" message. To
remove a window from the screen, send it the "remove" message:
dObject> remove(w);
To interactively resize or setup the color for a window, use the
"resize" and "setupColor" methods. These methods allow for
interactive resizing and color setup using the cursor keys and a
color display that shows the foreground and background colors
available as well as the color attribute number. When interactively
resizing a window, use the following keys to change the window's
size:
* Width - Press the left arrow key to make the window
narrower or the right arrow key to make it wider. To make
changes in larger increments, hold down the Ctrl key at the
same time. Use the end key to expand the window at the
start of the screen.
* Length - Press the up arrow key to decrease or the down
arrow key to increase the length of the window. Use the
page down key to extend the window to the bottom of the
screen and the page up key to extend the window to the top
of the screen.
To change the position of the window on the screen, use the following
keys:
* Shift-Up Up one row
* Shift-Down Down one row
* Shift-Right Right one column
* Shift-left Left one column
* Shift-Home To left screen edge
* Shift-End To right screen edge
* Shift-PgUp To top of screen
* Shift-PgDn To bottom of screen
* Ctrl-Home To top left screen corner
* Ctrl-End To bottom left screen corner
* Ctrl-PgUp To top right screen corner
- 36 -
Chapter 9: Windows and Menus
* Ctrl-PgDn To bottom right screen corner
To setup the color for the window text, pass the setupColor method an
Int argument of 0; to setup the color of the frame, pass it an Int
argument of 1. For example, the following statement invokes the
setup display for the color of the current window:
dObject> setupColor(currentWindow(),0);
dObject creates windows with a default frame consisting of a
single-width line border, and with the window title centered above
the window in the border. to change this, you can use the "setFrame"
message. The first argument to setFrame is the color attribute of
the frame, followed by the title of the frame, the integer position
to place the title counting from the left-hand side (a value of 0
instructs dObject to center the title), and finally a String
containing 6 characters to build frame with using the following
convention:
* 1st char: Upper left corner
* 2nd char: Upper right corner
* 3rd char: Lower left corner
* 4th char: Lower right corner
* 5th char: Horizontal line
* 6th char: Vertical line
For example, to frame a window with the title "My Window" starting at
position 3, with a white frame and a the '#' character for a border,
use the message:
dObject> setFrame(w,7,"My Window",3,"######");
9.2 Output using SAY and GET
dObject provides methods to build full-screen data entry and review
forms through the Int::say() and Window::say() methods, and through
the built-in Field base class. The SAY/GET facility in dObject is
similar in function to the @ say and @ get commands provided by the
DBASE language. In dObject these methods work within a window,
providing a way to create very sophisticated data handling forms.
To produce output from an expression at a y,x point within a window,
send the window the Int y coordinate, the Int x coordinate, the
expression to output, an Int length of the field to display, and an
- 37 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
Int color attribute to display the expression in:
dObject> say(currentWindow(),5,5,"this is a test",14,7);
To set up a get field for input, call the Exp::new method for the
class "Field", and send it the Window to place the field in, the Int
y coordinate, the Int x coordinate, a String name of the variable to
place the result into, an Int length of the field to display, and Int
color attribute. Make sure that the variable you will store the
value into is already defined:
dObject> a = "this is a test";
dObject> new(Field,currentWindow(),6,6,"a",14,112);
Alternatively, the field name can be the name of a DBASE field in the
currently active DBF file:
dObject> db = new(Dbffile,"patient");
dObject> new(Field,currentWindow(),6,6,"lname",14,112);
The Exp::new(Field,...) method returns a variable of type Field that
represents the field within the window. Once defined, a list of get
variables can be read in a full-screen input mode using the
Window::read() method:
dObject> read(currentWindow());
Entering this mode causes dObject to position the cursor at the
beginning of the first get field defined, and to wait for the user to
enter new values for data fields and scroll through records in the
current Dbffile. The specific keys recognized are:
KEY ACTION DESCRIPTION
Esc Escape exits the form and returns to dObject>
prompt
Home Goto top Positions the current DBF file at the
first record and displays it
End Goto bottom Positions the current DBF file at the
last record and displays it
PgUp Prev Record Positions the current DBF file at the
previous record and displays it
PgDn Next Record Positions the current DBF file at the
next record and displays it
Tab Next Field Positions the cursor at the beginning of
the next display field
Up Up cursor Positions the cursor up one line
- 38 -
Chapter 9: Windows and Menus
Down Down cursor Positions the cursor down one line
Right Right cursor Positions the cursor right one space
within current display field
Left Left cursor Positions the cursor left one space
within the current display field
F10 Quit exits the form and returns to dObject>
prompt
You can modify the actions associated with these or any other key
while in read mode by calling the Int::onKey() method and passing it
an expression to evaluate. For example, the following example shows
how to call the built-in text editor to edit the contents of a GET
field by pressing the F8 key while in read mode:
/*
this method implements a callable text editor for the contents of
a field
*/
method Window::myEdit(self)
{
f = currentField(self);
s = eval(asId(name(f)));
if(class(s) == "String") {
w = new(Window,1,31,3,name(f),5,5,10,40);
display(s);
remove(w);
gotoField(self,f);
}
}
db = new(Dbffile,"patient");
new(Field,currentWindow(),6,6,"lname",14,112);
onKey(w,F8,#myEdit(w));
read(currentWindow());
To clear the existing list of get variables from future reads, use
the Window::clearGets() method:
dObject> clearGets(currentWindow());
The following example program shows setting up two get fields with
prompts:
/*
sample full screen field output
*/
w = new(Window,1,31,3,"",0,0,24,80);
clearGets(2);
a = "test";
- 39 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
b = "test2";
say(w,5,5,"field a",7,7);
say(w,6,5,"field b",7,7);
new(Field,w,5,20,"a",10,112);
new(Field,w,6,20,"b",10,112);
read(w);
remove(w);
9.3 Pictures
You can assign a picture template to a GET field that will cause
dObject to format the value being displayed in the field, and
validate keystrokes upon entry to the field. Do this by calling the
Field::setPicture() method, and passing it a String containing the
picture:
dObject> a = "test";
dObject> f = new(Field,w,5,20,"a",10,112);
dObject> setPicture(f,"!!!!!!!!!!");
dObject recognizes the following picture code characters:
* ! - Converts letters to uppercase; accepts all
characters
* A - Allows letters only
* L - Translates characters to logical values (T, t, F, f,
Y, y, N, n)
* N - Allows letters and numbers
* 9 - Allows digits only
* X - Allows numbers, spaces, signs, and decimal points
only
* Other characters are copied literally into the displayed
value
The following example demonstrates the use of picture clauses:
/*
demonstrate the use of a picture within a GET field
*/
w = currentWindow();
clearGets(w);
cls;
- 40 -
Chapter 9: Windows and Menus
a = "test";
prompt = "Enter a value: ";
say(w,5,5,prompt,len(prompt),7);
f = new(Field,w,5,len(prompt)+5,"a",10,112);
setPicture(f,"!!!!!!!!!!");
read(w);
? "the value you entered was ",a;
9.4 Key Codes
The special key codes recognized by the Window::read() and
Nil::inkey() methods are defined in the supplied file KEYDEF.DO (you
can include this file in programs by using the #include preprocessor
statement):
#define BACK_SPACE "$08"
#define TAB "$09"
#define ESC "$1B"
#define CTRL_A "$01"
#define CTRL_B "$02"
#define CTRL_C "$03"
#define CTRL_D "$04"
#define CTRL_E "$05"
#define CTRL_F "$06"
#define CTRL_G "$07"
#define CTRL_H "$08"
#define CTRL_I "$09"
#define CTRL_J "$0A"
#define CTRL_K "$0B"
#define CTRL_L "$0C"
#define CTRL_M "$0D"
#define CTRL_N "$0E"
#define CTRL_O "$0F"
#define CTRL_P "$10"
#define CTRL_Q "$11"
#define CTRL_R "$12"
#define CTRL_S "$13"
#define CTRL_T "$14"
#define CTRL_U "$15"
#define CTRL_V "$16"
#define CTRL_W "$17"
#define CTRL_X "$18"
#define CTRL_Y "$19"
#define CTRL_Z "$1A"
#define RETURN "$D"
#define HOME "$4700"
#define END "$4F00"
#define PGUP "$4900"
#define PGDN "$5100"
#define UP "$4800"
#define DOWN "$5000"
- 41 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
#define RIGHT "$4D00"
#define LEFT "$4B00"
#define SHIFT_TAB "$0F00"
#define INS "$5200"
#define DEL "$5300"
#define CTRL_HOME "$7700"
#define CTRL_END "$7500"
#define CTRL_PGUP "$8400"
#define CTRL_PGDN "$7600"
#define CTRL_RIGHT "$7400"
#define CTRL_LEFT "$7300"
#define ALT_1 "$7800"
#define ALT_2 "$7900"
#define ALT_3 "$7A00"
#define ALT_4 "$7B00"
#define ALT_5 "$7C00"
#define ALT_6 "$7D00"
#define ALT_7 "$7E00"
#define ALT_8 "$7F00"
#define ALT_9 "$8000"
#define ALT_0 "$8100"
#define ALT_MINUS "$8200"
#define ALT_EQUAL "$8300"
#define ALT_Q "$1000"
#define ALT_W "$1100"
#define ALT_E "$1200"
#define ALT_R "$1300"
#define ALT_T "$1400"
#define ALT_Y "$1500"
#define ALT_U "$1600"
#define ALT_I "$1700"
#define ALT_O "$1800"
#define ALT_P "$1900"
#define ALT_A "$1E00"
#define ALT_S "$1F00"
#define ALT_D "$2000"
#define ALT_F "$2100"
#define ALT_G "$2200"
#define ALT_H "$2300"
#define ALT_J "$2400"
#define ALT_K "$2500"
#define ALT_L "$2600"
#define ALT_Z "$2C00"
#define ALT_X "$2D00"
#define ALT_C "$2E00"
#define ALT_V "$2F00"
#define ALT_B "$3000"
- 42 -
Chapter 9: Windows and Menus
#define ALT_N "$3100"
#define ALT_M "$3200"
#define F1 "$3B00"
#define F2 "$3C00"
#define F3 "$3D00"
#define F4 "$3E00"
#define F5 "$3F00"
#define F6 "$4000"
#define F7 "$4100"
#define F8 "$4200"
#define F9 "$4300"
#define F10 "$4400"
#define CTRL_F1 "$5E00"
#define CTRL_F2 "$5F00"
#define CTRL_F3 "$6000"
#define CTRL_F4 "$6100"
#define CTRL_F5 "$6200"
#define CTRL_F6 "$6300"
#define CTRL_F7 "$6400"
#define CTRL_F8 "$6500"
#define CTRL_F9 "$6600"
#define CTRL_F10 "$6700"
#define SHIFT_F1 "$5400"
#define SHIFT_F2 "$5500"
#define SHIFT_F3 "$5600"
#define SHIFT_F4 "$5700"
#define SHIFT_F5 "$5800"
#define SHIFT_F6 "$5900"
#define SHIFT_F7 "$5A00"
#define SHIFT_F8 "$5B00"
#define SHIFT_F9 "$5C00"
#define SHIFT_F10 "$5D00"
#define ALT_F1 "$6800"
#define ALT_F2 "$6900"
#define ALT_F3 "$6A00"
#define ALT_F4 "$6B00"
#define ALT_F5 "$6C00"
#define ALT_F6 "$6D00"
#define ALT_F7 "$6E00"
#define ALT_F8 "$6F00"
#define ALT_F9 "$7000"
#define ALT_F10 "$7100"
9.5 Menus
- 43 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
dObject provides a pop-up menu facility in the built-in Menu and
Linemenu classes. Menus are created by passing the "new" method the
Int y,x location of the upper left corner of the menu, the Int length
of the menu (number of lines to show), the Int text and frame color
attributes, a Collection of menu choices, and a String title. Menus
are executed using the "choice" method containing an Int argument
that specifies what choice to highlight upon entry to the menu. The
"choice" method returns the index of the menu item chosen within the
Collection; the calling program can retrieve the actual value chosen
by indexing the Collection with the "at" method.
Menus remain displayed in the current Window until the "remove"
message is sent to them. The following example shows putting up a
menu of numeric values and asking the user to choose:
/*
create a menu using a Collection of choices
*/
myCollection = [1.0,2.0,3,4,5,6,7,8,9];
a= new(Menu,3,3,5,31,3,myCollection," test ");
b = choice(a,1);
remove(a);
? "result of menu is ",b;
/*
the actual value chosen is found by getting the value
in the collection at index "b"
*/
value = at(myCollection,b);
To exit the menu without making a choice, press the ESC key while the
menu is active. This causes the Menu::choice() method to return 0 as
the chosen value.
The number of values in the Collection in a Menu can be much larger
than the display size of the Menu. When this occurs, the user can
press the up and down arrow keys to scroll through the menu before
making a choice with the "Enter" key.
9.6 Line Menus
dObject also provides a "Linemenu" class that implements lotus-style
line menus with optional help lines. You can create a line menu
using the "new" method, and passing it the Int window number of the
window to create for the menu, an Int row and column for the upper
left corner of the menu, an Int width of the menu, a Collection of
values to put in the menu, and a corresponding Collection of status
lines to show for each menu choice. When the menu is created and
- 44 -
Chapter 9: Windows and Menus
shown using the Linemenu::choice() method, the choices will be evenly
spaced across the width of the menu in the first line of the menu,
and the status line text for a given choice will be displayed on the
second line, much like the style of a Lotus 1-2-3 menu. The
following example illustrates the use of the Linemenu class:
/*
demo of the Linemenu class
*/
color = 54;
width = 40;
m = new(Linemenu,1,5,width,color,color,[1,2,3,4,5,6],
["first","second","third","fourth","fifth","sixth"]);
c = choice(m);
remove(m);
? "your choice was ",c;
You can create a Linemenu that does not display status lines
underneath the choices by passing an empty Collection to "new" for
the status line text. In this case a one-line menu will be created:
m = new(Linemenu,1,5,5,54,54,[1,2,3,4,5,6],[]);
9.7 Hypertext
dObject provides the capability to use the Window class described
above to display hypertext built from DBASE data and index files. To
build a hypertext string that can be displayed or edited using the
built-in text editor, use the Dbffile::htExpand() method. The "self"
argument to this method is a Dbffile object that contains at least
two text fields: one field containing a one-word topic string, and
one field containing the text to show whenever that topic is selected
from within a display. For example, the supplied dObject files
HELP.DBF, HELP.DBT, and HELP.NDX are DBASE files that are used as the
dictionary for the on-line help within the text editor and are an
example of suitable hypertext files:
dObject> db = new(Dbffile,"help");
dObject> displayStructure(db);
Structure for: HELP.DBF
Number of records: 8
Last update: 6/2/91
Version: 3
Number of fields: 2
Field Field Name Type Width Dec
0 TOPIC C 8 0
1 TEXT M 10 0
- 45 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
You must also pass an Ndxfile object that is a DBASE index on the
topic field, a String name of the text field to use in the Dbffile
for the text to show for a topic, an Int color to highlight the words
in the string being converted that have topic entries in the Dbffile,
and a String containing the text to convert. The method returns a
String containing embedded control codes telling the built-in editor
to highlight the topic words in the color you have chosen. The
following example illustrates the proper calling sequence:
dObject> db = new(Dbffile,"help");
dObject> ndx = useIndex(db,"help");
dObject> keylen = 32; % length of the topic field
dObject> htext = htExpand(db,ndx,"text",31,keylen,
"this is some text");
To display the hypertext within the current window, use the
String::display() method:
dObject> display(htext);
Calling this method will display the text within the current window
with words that have matching entries in the topic field of the
Dbffile highlighted with the color attribute chosen above. You can
position the cursor using the normal editor keys, and you can
"follow" the hypertext link for a highlighed word by positioning the
cursor on that word and pressing the CTRL-F1 key. Pressing this key
causes dObject to execute the String::onHyperKey() method with the
contents of the "text" field for the topic that was found in the
Dbffile. You should always supply a version of String::onHyperKey as
part of your hypertext application; If you do not, pressing the
CTRL-F1 key will have no effect will look for the word at the cursor
in the HELP.DBF file.
The following example shows how to define the String::onHyperKey()
method and build a small hypertext application using the supplied
dObject HELP.DBF, HELP.NDX, and HELP.DBT files:
/*
this is a demo of dObject's hypertext display feature
first, define a method to handle the "follow hyper link"
key when it is pressed from a window
*/
method String::onHyperKey(self)
{
/*
create a window for the text
*/
w = new(Window,1,31,31,"",8,8,10,40);
/*
- 46 -
Chapter 9: Windows and Menus
the color attribute is the first character token in the string
*/
color = asInt(token(self,#s));
/*
turn off the dObject hypertext help key (CTRL-F1) from within
the display
*/
set("hyperhelp",F);
/*
display the text
to follow the link for a highlighted field, hit the SHIFT-F8 key
*/
display(htExpand(db,index,"text",32,color,s));
remove(w);
}
/*
demo hypertext
*/
#define COLOR 79
db = new(Dbffile,"help");
index = useIndex(db,"help");
w = new(Window,1,31,31," Hypertext ",5,5,10,50);
display(htExpand(db,index,"text",COLOR,32,":while for if then else dos"));
remove(w);
close(db);
10.0 Arrays and Collections
10.1 Arrays
dObject provides classes for handling Arrays and Collections of
objects. The primary difference between an Array and a Collection is
that a Collection can be considered an ordered list of values that
can easily be inserted into, appended to , and deleted from, while an
Array is similar to a DBASE array that can be easily indexed by a set
of integer indexes, but not easily ordered, inserted into, or deleted
from. Both Collections and Arrays can contain any kind of dObject
class, including other Collections and Arrays. There is no
pre-defined limit on the size of an Array or Collection, but attempts
to use more memory than is available will cause an error message.
Arrays are similar to those provided in the DBASE programming
language. An array element can be stored or retrieved from a
specific location within an array through the use of the "replace"
and "at" messages, passing a Collection of integer indexes as an
argument.
- 47 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
For example, to create an array of 10 elements and store a String
value in the first location:
dObject> a = new(Array,[10]);
dObject> replace(a,[1],"this is the first element");
dObject> ? at(a,[1]);
t
To create multi-dimensional arrays, create the array with more than
one dimension in the dimension Collection, and address it with more
than one element in the index Collection:
dObject> a = new(Array,[3,3,3]);
dObject> replace(a,[1,1,1],"this is the first element");
/*
this is a test of dObject's Array class
*/
method Array::print(self)
{
i = 0;
while(i < len(self)) {
print(at(self,i));
print(' ');
i = i+1;
}
}
/*
create a single-dimension array of 4096 locations
*/
a = new(Array,[4096]);
i = 0;
while(i < 4096) {
replace(a,[i],i);
i = i+1;
}
? a;
10.2 Collections
dObject's Collection class provides an advanced way to store ordered
collections of objects. The Collection class comes with a
comprehensive set of built-in methods for adding, deleting, finding,
and replacing members within the collection. Collections are most
easily created using the literal convention of surrounding a
comma-separated list of literal values with brackets:
dObject> myCollection = [1,2,3,4,5];
- 48 -
Chapter 10: Arrays and Collections
Empty Collections can also be created using the Exp::new() method:
dObject> myCollection = new(Collection);
dObject> ? myCollection;
[]
As with Arrays, members of a Collection can be any valid dObject
class, including other Collections:
dObject> myCollection = [[1,2,3],[4,5,6],[7,8,9]];
To add a value to the end of a Collection, use the "append" method:
dObject> myCollection = [1,2,3];
dObject> myCollection = append(myCollection,4);
dObject> ? myCollection;
[1,2,3,4]
To replace an existing value within a Collection, use the "replace"
method, passing it a value to replace and the new value to replace it
with:
dObject> myCollection = [1,2,3];
dObject> myCollection = replace(myCollection,1,32);
dObject> ? myCollection;
[32,2,3]
The number of values within a Collection can be found by the "len"
method:
dObject> ? len([1,2,3,4,5]);
5
The first value in a Collection is called the "head" of the
Collection, and the remaining Collection without the head is called
the "tail":
dObject> ? myCollection = [1,2,3];
dObject> ? head(myCollection);
1
dObject> ? tail(myCollection);
[2,3]
- 49 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
Individual values within a Collection can be retrieved using an Int
index, but this is not nearly as efficient as using an Array for this
purpose:
dObject> ? at(["one","two","three"],2);
two
The last element in a collection is available using the "last"
method:
dObject> ? last([1,2,3,4]);
4
The maximum and minimum values from within a Collection can be found
with the "max" and "min" methods respectively:
dObject> ? max([1,2,3]);
3
A Collection can be filtered into another Collection by the "sort"
and "unique" methods. The "sort" method returns a Collection that is
the sorted version of the variable it is called on. The sort is
accomplished using the ">" operator on whatever class is in the
Collection, and is done in ascending order:
dObject> ? sort([3,1,4,6,5,2]);
[1,2,3,4,5,6]
The "unique" method returns a Collection consisting of the unique
elements in the Collection it is called on:
dObject> ? unique([1,1,2,2,3,3,4,4,5,5,6,6]);
[1,2,3,4,5,6]
The following example demonstrates many of the methods available for
handling Collections:
/*
this is a demonstration of dObject's Collection class
*/
a = [5,3,9,5,100,44,5];
? "Collection is ",a;
? "length is ",len(a);
? "reversed is ",reverse(a);
? "third element is ",at(a,3);
? "last element is ",last(a);
? "with 100 removed is ",remove(a,100);
- 50 -
Chapter 10: Arrays and Collections
? "substitute 1005 for 5 is ",replace(a,5,1005);
? "is 44 in collection ?: ",44 $ a;
? "sorted array is ",sort(a);
? "unique array is ",unique(a);
? "unique sorted Collection is ",sort(unique(a));
? "sum of elements is ",sum(a);
? "minimum value is ",min(a);
? "maximum value is ",max(a);
? "average value is ",avg(a);
/*
fill a collection
*/
a = [];
i = 0;
while(i < 10) {
a = append(a,i);
i = i+1;
}
? a;
11.0 Files and Devices
11.1 Files and Devices
dObject allows output to DOS text files and to devices such as the
printer through the built-in "File" class. Files are created by
passing the "new" method the name of the file to create, an Int
switch indicating if the file is to be opened in read, write, or
append mode (1,2, or 3 respectively), an Int containing the DOS
attributes of the file, and an Int specifying what to do if the file
already exists:
dObject> f = new(File,"new.out",1,0,0);
Constant definitions for the open mode, the DOS file attributes, and
the creation option flag are provided in the file IODEF.DO:
/*
some constant definitions for new(File,...)
*/
/* File Attributes */
#define FA_RDONLY "$01" /* Read only file */
#define FA_HIDDEN "$02" /* Hidden file */
#define FA_SYSTEM "$04" /* System file */
#define FA_SUBDIR "$10" /* Subdirectory */
#define FA_ARCH "$20" /* Archive file */
#define FA_NORMAL "$40" /* Normal file - No read/write restrictions */
- 51 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
/* File usage Modes */
#define FM_ACCESS_WO "$0001" /* write only */
#define FM_ACCESS_RW "$0002" /* read/write */
#define FM_ACCESS_RO "$0004" /* read only */
#define FM_SH_DENYRW "$0010" /* deny read/write mode */
#define FM_SH_DENYWR "$0020" /* deny write mode */
#define FM_SH_DENYRD "$0030" /* deny read mode */
#define FM_SH_DENYNO "$0040" /* deny none mode */
/* Exclusively for OS2 and DOS >4.0 */
#define FM_RETURNERR "$2000" /* return error rather than call crit hand. */
#define FM_WRITETHRU "$4000" /* write through */
/* Creation Flags */
/* Actions if file exists (low nibble) : */
#define CR_EX_FAIL "$00"
#define CR_EX_OPEN "$01"
#define CR_EX_REPLACE "$02"
/* Actions if file doesn't exist (high nibble): */
#define CR_NOEX_FAIL "$00"
#define CR_NOEX_CREATE "$10"
dObject maintains "current" input and output devices which are
normally the keyboard and the screen respectively. These devices can
be redirected to files through the "readDevice" and "writeDevice"
methods:
dObject> writeDevice(f);
Files can be flushed and closed through the "flush" and "close"
methods. For example, to open a file and write a line of output to
it:
You can read a character from the current input device using the
Nil::readchar() method, which returns the next character as a Char
variable. To read a complete keycode from the keyboard as an Int,
use the Nil::inkey() method. The key definitions returned by
Nil::inkey() are defined in the include file "keydef.do".
If you use Nil::readchar() to read characters, you can "push back"
characters into the input buffer using the Char::unread() method.
This method pushes its Char argument back into the input buffer where
it can be read later using Nil::readchar().
The following example describes how to create a file and write output
to it:
- 52 -
Chapter 11: Files and Devices
/*
this is a demonstration of dObject's file handling capabilities
*/
f = new(File,"new.out",1,0,0);
writeDevice(f);
? "this is a test";
close(f);
When opening a file in the "new" command, the filename can also be a
device name, such as "prn:". The printer can be accessed as shown in
the following example:
/*
this is a demonstration of dObject's printer handling features
open the printer and print 10 lines to it without echoing the
lines to the screen
*/
p = new(File,"prn:",1,0,0);
writeDevice(p);
i = 1;
while(i < 10) {
? "printing line ",i;
i = i+1;
}
/*
note: on some printers (HP II, Epson EPL-6000) it is necessary
to send an ESC E to flush the printer... consult your printer
manual to see if the next line is necessary, otherwise the
"flush" method should work OK by itself
*/
? chr(27),'E';
flush(p);
close(p);
? "printout is done";
12.0 DBASE File Programming
12.1 DBASE File Programming
dObject provides an extensive set of built-in methods for handling
DBASE data, memo, and index files. You can create your own new
DBASE-format files for storing data, or use existing files already in
the DBASE format. You can also use and create DBASE index (.NDX)
files.
- 53 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
12.2 Creating DBASE Files
The following example demonstrates how to create a .DBF file using
the String::createDbf() method. The argument to "createDbf" is an
Collection of Collections of field defintions. Each field definition
Collection should contain a string that is the DBASE field name, a
character field type ('C' = char, 'N' = numeric, 'D' = date, 'M' =
memo), an Int length, and an Int number of decimals for numerics:
/*
create a new Dbffile
*/
db = createDbf("test",[
["cfield",'C',32,0],
["nfield",'N',5,0],
["dfield",'D',0,0],
["mfield",'M',512,0]);
displayStructure(db);
dObject will create a .DBT file for each MEMO field specified in the
Collection of field definitions.
To set the value of a field within the current DBASE file, set a
variable with the same name as the field to a value, just like in
DBASE. Once set, the field value can be updated in the current
record by the "write" method, or a new record can be appended to the
file using the "write" method:
/*
store some test data to the database
*/
select(db); % make sure the Dbffile to process is the "current" file
i = 1;
while(i < 10) {
cfield = "test"+asString(i);
nfield = i;
dfield = date();
mfield = "memo" + asString(i);
write(db,0L);
i = i+1;
}
The structure (field definitions) from a DBF file can be obtained by
using the Dbffile::structure() method. This returns a Collection of
field definitions like the one described above. The following is an
example of how to use the structure method to simulate some common
DBASE commands:
- 54 -
Chapter 12: DBASE File Programming
/*
Dbffile::copyStructure(self,newname)
this method copys the structure of self to a new database
with name of "newname"
only the structure of self is copied; no records are copied
*/
method Dbffile::copyStructure(self,newname)
{
l = structure(self);
createDbf(newname,l);
}
/*
Dbffile::list(self)
this method lists the records in a Dbffile to the screen
*/
method Dbffile::list(self)
{
top(self);
fields = structure(self);
newline = set("newline");
set("newline","");
while(!eof(self)) {
for(i=1;i<numFields(self);i=i+1) {
f = at(fields,i);
name = at(f,1);
? eval(asId(name))," ";
}
? "\n";
skip(self,1L);
}
set("newline",newline);
}
dObject> db2 = copyStructure(db,"test2");
12.3 Reading DBASE Files
DBF files can be opened through the use of the "new" message with the
name of the DBF file passed as an argument. Once opened, the records
and fields within a DBF file are available for reading and for update
by your dObject program. For example, to open the "patient.dbf"
file, use the statement:
dObject> db = new(Dbffile,"patient");
The number of records and fields defined within a DBF file are
available through calls to the "numRecords" and "numFields" methods:
- 55 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
dObject> ? numFields(db);
6
dObject> ? numRecords(db);
20
The current record number is available as a Long using the "recno"
method:
dObject> top(db);
dObject> ? recno(db),class(recno(db));
1 Long
Dbffiles can be positioned by sending them the "top", "bot",
"locate", and "seek" messages. The "eof" method returns logical T
when a Dbffile is positioned beyond the last record in the file (and
otherwise returns logical F). The following example demonstrates a
program that loops over all the records in a DBF file:
db = new(Dbffile,"patient");
top(db);
while(!eof(dbf)) {
? "at record ",recno(db);
skip(db,1L);
}
The "locate" method can be used to locate specific field values of
type Int, Real, Char, String, Date, or Logical. The first argument
to the method should be the name of the field to perform the
comparison on, and the second the value to find. The search will
always start at the current record, so to always search from the top
of the database, the "top" method can be used to position the Dbffile
first:
dObject> db = new(Dbffile,"patient");
dObject> locate(top(db),"lname","lname6");
Fields within DBF files are accessed by using a variable name with
the same name as a field in the currently selected database, as in
DBASE:
dObject> db = new(Dbffile,"patient");
dObject> top(db);
dObject> ? lname;
lname0
dObject> select(db);
- 56 -
Chapter 12: DBASE File Programming
The currently selected Dbffile is available through a call to the
Nil::currentDbffile() method:
dObject> top(currentDbffile());
You can also perform sophisticated calculations over all the records
in a DBASE file using the built-in "sum", "max", "min", and "avg"
methods. These methods accept a literal dObject expression as an
argument, and evaluate the sum, max, min, or average of the
expression over all the records in the file. For example, to
calculate the minimum and maximum length of a DBASE char field named
"lname", your need to evaluate the length of the trimmed field value
across all the records in the file. The following commands perform
this task:
dObject> ? db = new(Dbffile,"patient");
dObject> ? min(db,#len(trim(lname)));
dObject> ? max(db,#len(trim(lname)));
These methods always start from the top of the file.
12.4 Using Filters
dObject allows you to specify an expression as a "filter" for a .DBF
file to make it appear to your application that certain records do
not exist. The expression is evaluated for each record within a .DBF
file, and unless the expression evaluates to logical true for a given
record, the record appears as if it does not exist. To create an
expression filter for a database, call the Dbffile::setFilter
method:
dObject> setFilter(db,#(recno(db) > 5L) & (recno(db) < 15L));
The above example creates a filter for a Dbffile making it appear
that only the records having record numbers between 6 and 14
inclusive actually exist in the file. The expression can be any
valid dObject expression, and setting a filter in this way affects
every future operation done on the database, including repositioning
with the Dbffile::top, Dbffile::bot, Dbffile::skip, and Dbffile::go
methods, as well as editing within the interactive DBASE editor.
When created, Dbffile objects have an implied filter of
logical(true), which succeeds for any record. To clear the filter
for a Dbffile object, use the Dbffile::clearFilter() method:
dObject> clearFilter(db);
- 57 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
Collections can be created from DBASE fields using the "asCollection"
method. The argument to this method is an expression to evaluate for
each record in the DBASE file. The Collection returned contains one
entry for the value of the expression for each record. The filtering
process descibed above applies to filter out unwanted records. The
following is an example of how to create a menu using information
from a DBF file using a Collection as the list of items to show in
the menu:
/*
create a menu of all the last names within a range
of records in the dbf file
*/
d = new(Dbffile,"patient");
top(d);
d = setFilter(d,#(recno(d) >= 8L) & (recno(d) <= 15L));
a = sort(asCollection(d,#trim(lname)));
m = new(Menu,3,3,5,31,3,a," Last Name ");
c = choice(m,1);
remove(m);
? "your menu choice was ",c;
12.5 Using DBASE Index Files
Records containing field values of interest can be accessed much more
quickly using DBASE index files than can be using the "locate" method
described above. dObject provides the built-in Ndxfile class to
represent DBASE index files. To open an existing index file and
associate it with a Dbffile variable, use the "useIndex" method of
the Dbffile class. This method returns a new Ndxfile variable:
dObject> db = new(Dbffile,"patient");
dObject> ndx = useIndex(db,"patient");
This method opens the named index (with the default extension of
.NDX) and associates it with the Dbffile. This permits the
Ndxfile::seek method to be used to position the current record in the
Dbffile:
dObject> seek(db,"1");
To create a new index file, use the "createIndex" method of the
String class. The "self" argument in this case is the name of the
index file to create, followed by a String containing the expression
to evaluate for the index, and finally an Int indicator specifying if
the index is to be unique (0=not unique, 1=unique). It also returns
a new Ndxfile variable:
dObject> ndx = createIndex("test","test",1);
- 58 -
Chapter 12: DBASE File Programming
The following program demonstrates how to create an index file and
use it to access fields within a Dbffile:
/*
create an index file for a database
*/
db = new(Dbffile,"patient");
index = createIndex(db,"patient","LNAME",0,0);
? "type of index is ",type(index);
close(db);
/*
open the index and print out records in index order
*/
db = new(Dbffile,"patient");
useIndex(db,"patient");
top(db);
while(!eof(db)) {
? recno(db)," ",lname;
skip(db,1L);
}
close(db);
12.6 Using Relations
dObject provides a facility to relate two DBF files throught the use
of the Dbffile::setRelation() method. Calling this method creates a
relation between a controlling database (the self parameter) and a
related database. Each time the controlling database is
re-positioned (using the Dbffile::go(), Dbffile::seek(),
Dbffile::top(), or Dbffile::bot() methods), the related database is
re-positioned by looking up an expression in an index file. If no
index file is specified when the relationship is created, then the
expression is evaluated and interpreted as a record number to go to
in the related database.
The following example illustrates the use of relations in dObject:
/*
demonstrate the dObject relation facility between two related
DBF files, first, create a customer file with customer names
*/
custDb = createDbf("customer",[
["cId",'N',8,0],
["cName",'C',32,0],
["cAddress",'C',48,0],
["cCity",'C',16,0],
["cState",'C',2,0],
["cZip",'C',5,0]]);
- 59 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
/*
fill in some test customer names
*/
#define MAXCUST 5
for(i=0;i<MAXCUST;i=i+1) {
cId = i;
cName = "name"+asString(i);
cAddress = "";
cCity = "Chicago";
cState = "IL";
cZip = "60640";
? "writing record ",i;
write(custDb,0L);
}
close(custDb);
/*
create a database of customer purchases
*/
purchaseDb = createDbf("purchase",[
["cId",'N',8,0],
["pItem",'C',32,0],
["pDate",'D',0,0],
["pAmount",'N',8,2]]);
/*
create some test data
*/
for(i=0;i<MAXCUST;i=i+1)
for(j=0;j<2;j=j+1) {
cId = i;
pItem = "item"+asString(i);
pDate = date();
pAmount = 5.25;
write(purchaseDb,0L);
}
close(purchaseDb);
/*
find the purchases for customer #3
*/
custDb = new(Dbffile,"customer");
purchaseDb = new(Dbffile,"purchase");
ndx = createIndex(purchaseDb,"CID","cId",0,0);
setRelation(custDb,"cId",select(purchaseDb),select(ndx),0);
top(custDb);
locate(custDb,"cId",3);
? "record number for customer 3 is ",recno(custDb);
? "customer id field in purchase database is ",recno(purchaseDb);
- 60 -
Chapter 12: DBASE File Programming
12.7 Editing DBASE Files
Using the built-in Window::say() and read() methods and the "Field"
class, the file DBFLIB.DO provides an example of a DBASE full-screen
editor that is invoked by sending the "edit" message to a Dbffile
object. You can include this editor in your own programs as is, or
customize it to fit your own application. When invoked, the editor
will display the field name and value for each field within the
database in the current window, at the current record position.
The "edit" method is implemented in the following library of Dbffile
methods:
/*
DBFLIB.DO
This is a collection of methods for handling DBASE files
Includes:
Dbffile::displayStructure(self)
Dbffile::copyStructure(self)
Dbffile::list(self)
Dbffile::edit(self)
*/
#include "keydef.do"
#include "colors.do"
/*
Dbffile::displayStructure(self)
this methods prints a description of the structure of a DBASE
file similar to that in the DBASE DISPLAY STRUCTURE command
*/
method Dbffile::displayStructure(self)
{
? "Structure for\t\t",name(self);
? "Last udpate:\t\t",date(self);
? "Number of records:\t",numRecords(self);
fields = structure(self);
? "FIELD\t\t\tTYPE\tLEN\tDEC";
for(i=1;i<numFields(self);i=i+1) {
f = at(fields,i);
? format(at(f,1),"%-24s"),at(f,2),"\t",
at(f,3),"\t",at(f,4);
}
}
/*
Dbffile::copyStructure(self,newname)
this method copys the structure of self to a new database
with name of "newname"
only the structure of self is copied; no records are copied
*/
- 61 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
method Dbffile::copyStructure(self,newname)
{
l = structure(self);
create(newname,l);
}
/*
Dbffile::list(self)
this method lists the records in a Dbffile to the screen
*/
method Dbffile::list(self)
{
top(self);
fields = structure(self);
newline = set("newline");
set("newline","");
while(!eof(self)) {
for(i=1;i<numFields(self);i=i+1) {
f = at(fields,i);
name = at(f,1);
? eval(asId(name))," ";
}
? "\n";
skip(self,1L);
}
set("newline",newline);
}
/*
The following methods implement a DBASE field editor using the
dObject Window SAY and READ methods and the FIELD class.
first, define a new class called MYFIELD that inherits the behavior of
Field, but adds a prompt that is displayed at the bottom of the form
*/
inherit(Field,Myfield,["prompt"]);
/*
define a method to get the prompt field from a Myfield variable
*/
method Myfield::prompt(self)
{
return(slot(self,"prompt"));
}
/*
this method will execute whenever the DOWN key is pressed
from within a form
*/
method Window::myNextField(self)
{
n = num(currentField(self));
if(n < len(fields)) {
- 62 -
Chapter 12: DBASE File Programming
f = at(fields,n+1);
say(promptWindow,0,0,prompt(f),80,112);
gotoField(self,nextField(self));
}
}
/*
this method will execute whenever the UP key is pressed
from within a form
*/
method Window::myPrevField(self)
{
n = num(currentField(self));
if(n > 1) {
f = at(fields,n-1);
say(promptWindow,0,0,prompt(f),80,112);
gotoField(self,prevField(self));
}
}
/*
this method implements a callable text editor for the contents of
a field
*/
method Window::myEdit(self)
{
f = currentField(self);
s = eval(asId(name(f)));
if(class(s) == "String") {
w = new(Window,1,31,3,name(f),5,5,10,40);
display(s);
remove(w);
gotoField(self,f);
}
}
/*
edit a Dbffile using a full screen editor
*/
method Dbffile::edit(self)
{
/*
make a window to run the editor in
*/
w = new(Window,1,FWHITE+LIGHTBLUE,FWHITE+LIGHTBLUE,
name(self),0,0,24,80);
/*
create the DBASE form based on field definitions within self
*/
clearGets(w);
- 63 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
sayExp(w,0,1,#name(self),len(name(self)),FWHITE+LIGHTBLUE);
sayExp(w,0,20,#"Record=",7,FWHITE+LIGHTBLUE);
sayExp(w,0,30,#recno(self),7,FWHITE+LIGHTBLUE);
l = structure(self);
fields = [];
/*
for each field in the DBF file, create:
a SAY field with the name of the DBF field
a GET field right next to it to read its value
*/
for(i=1;i<=numFields(self);i=i+1) {
field_def = at(l,i);
fname = at(field_def,1); % name is first element in field def
len = at(field_def,3);
if(len > 40) len = 40;
say(w,i,1,fname,10,31);
fields = append(fields,new(Myfield,w,i,15,fname,len,112,
"Enter the "+asUpper(trim(fname))+ " field"));
}
/*
execute the form
*/
top(self);
promptWindow = new(Window,80,112,0,"",24,0,1,80);
onKey(w,DOWN,#myNextField(w));
onKey(w,UP,#myPrevField(w));
onKey(w,F8,#myEdit(w));
say(promptWindow,0,0,prompt(at(fields,1)),80,112);
read(w);
remove(w);
remove(promptWindow);
}
As another example, the following program displays a directory of DBF
files in the current directory and edits the one selected from the
menu:
/*
this program creates a window, and displays a menu of DBF files
available in the current directory. When the user selects one,
the DBF file editor is called to edit the fields and records
*/
- 64 -
Chapter 12: DBASE File Programming
w = new(Window,1,7,7," select DBF ",1,1,10,40);
s = dir("","*.dbf");
while(s != "") {
d = new(Dbffile,s);
height = numFields(d)+2;
edit(d);
s = dir("","*.dbf");
}
remove(w);
12.8 Closing DBASE Files
To close a Dbffile, use the "close" method:
dObject> close(db);
To close all the open Dbffiles at once, use the Nil::closeAllDbfs
method (this will close all open .NDX files also):
dObject> closeAllDbfs();
13.0 Graphics Programming
13.1 BGI Graphics
dObject comes complete with a built-in graphics system based on the
Borland Graphics Interface (BGI). The BGI provides over 70 methods
for handling graphics, including methods to draw lines, arcs,
circles, polygons, and other shapes; methods for filling shapes in a
variety of styles; and methods for setting text in a variety of
fonts.
13.2 Graphics Drivers
To begin with, you must call the Int::initGraph() method to
initialize the graphics system. This will put the screen into
graphics mode and allow further calls to the BGI system. dObject
comes with graphics drivers for the following graphics adapters:
* CGA
* MCGA
* EGA
* VGA
- 65 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
* Hercules
* AT&T 400-line
* 3270 Graphics Adapter
* IBM-8514 Graphics Adapter
The self argument to Int::initGraph() is an integer flag specifying
the device driver to use ( a value of 0 will detect the best driver
to use):
* 0 - autodetect
* 1 - CGA
* 2 - MCGA
* 3 - EGA
* 4 - EGA64
* 5 - EGAMONO
* 6 - IBM8514
* 7 - Hercules
* 8 - AT&T 400
* 9 - VGA
* 10 - PC 3270
You can obtain the name of the current graphics driver through a call
to the Nil::getDriverName() method.
dObject provides the following methods for initializing and shutting
down the BGI graphics system:
NAME ARGUMENTS DESCRIPTION
Int::initGraph self, Int, String initializes the BGI system;
must be called before any
other BGI method. Sets the
graphics driver to self, the
graphics mode to the Int
arg, and the driver path to
the String arg.
- 66 -
Chapter 13: Graphics Programming
Nil::detectGraph returns a Collection of 2
Int values specifying the
current graphics driver and
mode.
Nil::getDriverName returns a String containing
the name of the current
graphics driver.
Int::getModeName self returns a String containing
the graphics mode name for
the mode with Int code of
self.
Int::getModeRange self returns a Collection of 2
Int values specifying the
min and max mode values for
the graphics driver with Int
code of self.
Int::setGraphMode self changes the graphics mode to
self.
Nil::getGraphMode returns an Int containing
the current graphics mode.
Nil::getMaxMode returns an Int containing
the maximum mode number for
the currently loaded driver.
Nil::graphDefaults sets the graphics system to
default values (see next
section).
Nil::closeGraph closes the graphics system,
unloads the driver from
memory, and restores the CRT
to its original state before
initGraph() was called.
Nil::restoreCrtMode restores the CRT to its
original state.
13.3 Default Graphics Settings
You can set the graphics system to its default settings through a
call to the Nil::graphDefaults() method. These defaults settings are
as follows:
* Viewport: mamimum device resolution
* Clipping: on
* Palette: default for drive
* Background color: 0
* Drawing color: max color
* Fill style: solid fill
- 67 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
* Fill color: max color
* Line style: solid line
* Hardware font direction: horizontal
* Font size: 1
* Font justification: left top
* Current position: home (0,0)
13.4 Current Graphics Position
The BGI system maintains the current X,Y graphics co-ordinate that is
referred to as the current position (CP). The current position can
be obtained through calls to the Nil::getx() and Nil::gety() methods,
each of which return an Int value. The CP can be set using the
Int::moveto() and Int::moveRel() methods, with the self arg equal to
the X value to move to, and the first argument being an Int Y
co-ordinate. Int::moveTo() uses and absolute co-ordinate, whereas
Int::moveRel() moves relative to the current position:
/*
move the graphics CP
*/
moveto(100,100); % now at 100,100
moveRel(100,100); % now at 200,200
dObject provides the following methods for maintinaing the graphics
CP:
NAME ARGUMENTS DESCRIPTION
Nil::getX returns the x co-ordinate of
the CP
Nil::getY returns the y co-ordinate of
the CP
Int::moveTo self, Int moves the CP to X,Y of self,
Int arg
Int::moveRel self, Int moves the CP the X,Y
relative distance of self,
Int arg
Nil::getMaxX returns the max X value for
the current graphics driver
and mode
Nil::getMaxY returns the max Y value for
- 68 -
Chapter 13: Graphics Programming
the current graphics driver
and mode
13.5 Drawing Lines
Lines are drawn using the Int::line() method, passing it the X,Y
positions of the beginning and end points. The following example
draws a line from the point 5,5 to the point 100,100:
dObject> line(5,5,100,100);
The following methods are provided for drawing lines:
NAME ARGUMENTS DESCRIPTION
Int::setLineStyle self, Int, Int sets the current line style
to the code in self; sets
the current pattern to the
first Int arg code, and the
current thickness to the
second Int arg. Line style
codes are 0=solid, 1=dotted,
2=center, 3=dashes,
4=user-defined. You can
define a line style by using
a 16-bit pattern in the
first Int arg, where whenver
a bit in the pattern is set
to one, the corresponding
pixel in the line is drawn
in the current drawing
color. For example, a solid
line is represented by the
value $FFFF (all one's), and
a dashed line is $3333 or
$0F0F. Thickness codes in
the second Int arg are 0=1
pixel wide, 3=3 pixels wide.
Nil::getLineSettings returns collection of 3 Int
args representing current
line style, user-defined
pattern, and thickness code
as described above.
Int::line self, Int, Int, Int draws a line in the current
drawing color. Arguments are
X,Y of start point and X,Y
of end point.
Int::linerel self, Int draws a line in the current
drawing color from current
position to relative offset
- 69 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
of self, Int arg.
Int::lineto self, Int draws a line in the current
drawing color from current
position to X,Y position of
self, Int arg.
Int::setWriteMode self sets the writing mode for
line drawing to self; if
self = 0 the line will
overwrite what is on the
screen; if self=1 the line
pixels will be XOR'd with
the pixels on the screen.
13.6 Drawing Circles
The following methods are provided for drawing circles and arcs:
NAME ARGUMENTS DESCRIPTION
Int::arc self, Int, Int, Int, draws a circular arc in the
Int current drawing color.
Arguments are X,Y center,
start angle, end angle, and
radius.
Int::circle self, Int, Int draws a circle in the
current drawing color.
Arguments are X,Y of center,
and radius.
Nil::getArcCoords returns a Collection of 6
Int values containing the
x,y center point, x,y start
pos, and x,y end pos of the
arc. This is useful if you
need to make a line meet at
the end of an arc.
13.7 Drawing Ellipses and Pie Charts
The following methods are provided for drawing ellipses and pie
charts:
NAME ARGUMENTS DESCRIPTION
Int::ellipse self, Int, Int, Int, draws an ellipse in the
Int, Int current drawing color. Args
are center point X,Y, start
angle, end angle, and X and
Y radius.
Int::fillEllipse self, Int, Int, Int draws an ellipse and fills
it with the current fill
- 70 -
Chapter 13: Graphics Programming
pattern in the current fill
color. Args are X, Y, X
radius, and Y radius.
Int::pieSlice self, Int, Int, Int, draws and fills a pie slice
Int using current fill pattern
and drawing color.
Arguments are X,Y center,
start angle, end angle, and
radius.
Int::pieSliceXY self, Int, Int, Int, draws and fills an
Int, Int elliptical pie slice using
current fill pattern and
drawing color. Arguments
are X,Y center, start angle,
end angle, X radius, and Y
radius.
Nil::getAspectRatio returns Collection of 2 Int
value representing the x and
y aspect ratio correction
values of the current
graphics mode.
setAspectRatio self, Int sets the x and y
aspect-ratio correction
factors to self and Int arg
respectively.
13.8 Drawing Rectangles and Bars
dObject provides the following methods for drawing rectangles, bar
graphs, and polygons:
NAME ARGUMENTS DESCRIPTION
Int::rectangle self, Int, Int, Int draws a rectangle in the
current line style,
thickness, and drawing
color. Arguments are left,
top, right, and bottom
co-ordinates of the
rectangle to draw (from
(left,top) to
(right,bottom)).
Int::bar self, Int, Int, Int draws a rectangular bar in
the current line style,
thickness, and drawing
color, and fills it using
the current fill pattern and
fill color. Arguments are
left, top, right, and bottom
co-ordinates of the
rectangle to draw (from
- 71 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
(left,top) to
(right,bottom)).
Int::bar3d self, Int, Int, Int, draws a rectangular 3-D bar
Int, Int in the current line style,
thickness, and drawing
color, and fills it using
the current fill pattern and
fill color. Arguments are
left, top, right, and bottom
co-ordinates of the
rectangle to draw (from
(left,top) to
(right,bottom)), the depth
of the bar, and a flag
indicating if a top to the
bar should be drawn (0=no,
1=yes).
13.9 Drawing Polygons
dObject provides the following methods for drawing polygons:
NAME ARGUMENTS DESCRIPTION
Collection::drawPoly self draws a polygon with as many
points as Int value pairs in
the collection; each Int
pair is an x,y co-ordinate
of a vertex on the polygon.
Collection::fillPoly self draws a polygon with as many
points as Int value pairs in
the collection and fills it
using the current fill style
and fill color; each Int
pair is an x,y co-ordinate
of a vertex on the polygon.
13.10 Palettes
The BGI graphics screen consists of an array of pixels controlled by
a color table called a palette. The background color always
corresponds to pixel value 0. The drawing color is the value to
which pixels are set when lines or shapes are being drawn. You can
select a drawing color with the Int::setColor() method.
NAME ARGUMENTS DESCRIPTION
Int::setBkColor self sets the current background
color to self
Nil::getBkcolor self returns the current
- 72 -
Chapter 13: Graphics Programming
background color
Int::setColor self sets the current drawing
color to self
Nil::getColor returns the current drawing
color
Nil::getMaxColor returns the maximum color
value available in the
current graphics mode
Int::setPalette self, Int changes the color value
stored under self to the
color in the Int arg
Collection::setAllPaletteself sets list of new palette
colors. self must be a
Collection of 8 Int values
specifying the colors.
13.11 Filling Shapes
You can fill the shapes drawn with the circle, ellipse, bar, and
polygon shape drawing methods with the Int::floodFill() method, or
combine drawing and filling into one step with the fillPoly() and
pieSlice() methods. You can select a predefined fill pattern with
setFillStyle, and define your own fill pattern with
setFillPattern().
The predefined fill pattern codes recognized by Int::setFillStyle()
are as follows (as defined in the included file BGIDEF.DO):
* 0 (EMPTY_FILL) - fill with background color
* 1 (SOLID_FILL) - solid fill
* 2 (LINE_FILL) - fill with ----
* 3 (LTSLASH_FILL) - fill with ///
* 4 (SLASH_FILL) - fill with ///, thick lines
* 5 (BKSLASH_FILL) - fill with backslash, thick lines
* 6 (LTBACKSLASH_FILL) - fill with backslash
* 7 (HATCH_FILL) - light hatch fill
* 8 (XHATCH_FILL) - heavy cross hatch fill
* 9 (INTERLEAVE_FILL) - interleaving line fill
* 10 (WIDE_DOT_FILL) - widely spaced dot fill
* 11 (CLOSE_DOT_FILL) - closely spaced dot fill
- 73 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
* 12 (USER_FILL) - user-defined fill pattern (see
Collection::setFillPattern())
The following methods are provided for filling shapes:
NAME ARGUMENTS DESCRIPTION
Nil::getFillSettings returns a Collection of 2
Int values; the first is the
current fill pattern; the
second is the current fill
color
Int::setFillStyle self, Int sets the current fill
pattern to the predefined
pattern with a code of self
and the current fill color
to the Int arg
Collection::setFillPatternself, Int sets the current fill
pattern to a user-defined
Collection of 8 Int color
values. Each Int value
represents a byte of 8
pixels; whenever a bit in
the pixel pattern is set to
1, the corresponding pixel
will be plotted. The Int
arg is the fill color to
use.
Nil::getFillPattern returns the current
user-defined fill pattern as
a Collection of 8 Int
values.
Int::floodFill self, Int, Int fills an enclosed area on
the graphics screen. Self
and the first Int arg form a
"seek point": within the
enclosed area to be filled.
The are bounded by the color
indicated in the second Int
arg is flooded with the
current fill pattern and
fill color. If the seed
point is within an enclosed
area, the the inside will be
filled. If the seed is
outside the enclosed the
area, then the exterior will
be filled.
- 74 -
Chapter 13: Graphics Programming
13.12 Fonts and Text in Graphics Mode
You can also output text in a variety of fonts, sizes, and styles
from within dObject's BGI graphics mode. Text output is accomplished
by calling the String::outText() or Int:outTextXY() methods after
defining a current character font.
Text justification constants in horizontal mode:
* 0 - left horizontal
* 1 - center horizontal
* 2 - right horizontal
Text justification constants in vertical mode:
* 0 - bottom vertical
* 2 - top vertical
dObject provides the following methods for manipulating text in
graphics mode:
NAME ARGUMENTS DESCRIPTION
String::outText self outputs a string to the
current graphics position
(CP).
Int::outTextXY self, Int, String outputs String arg to x,y
location of self, Int arg
String::textHeight self returns height of self in
pixels as Int
String::textWidth self returns width of self in
pixels as Int
Nil::getTextSettings returns Collection of 4 Int
values indicating current
text font, direction, size,
and justification
Int::setTextJustify self, Int sets justification to
horizontal code of self and
vertical code of Int arg.
Horizontal values:
0=left,1=center,2=right
Vertical values:
0=bottom,1=top
Int::setTextStyle self, Int, Int sets current text font to
self; sets current direction
to first Int arg, and
current char size to second
- 75 -
dObject Version 1.0 (c) 1991 Intelligent Systems Research
Int arg. Text direction
codes are 0=horizontal (left
to right), 1=vertical
(bottom to top).
Int::setUserCharSize self, Int, Int, Int sets width and height ratio
for stroked fonts. Sets
scale factors for x width, x
height, y width, and y
height to self and the 3 Int
args respectively.
13.13 Viewports
Your system contains between one and four screen-page buffers where
screen images are stored dot-by-dot, depending on the graphics
hardware installed. You can specify which screen page is active
(where graphics methods place their output) and which page is visible
using the Int::setActivePage() and Int::setVisualPage() methods. You
can specify a region of the display screen where clipping is active
through a call to the setViewPort() method.
dObject provides the following viewport-related methods:
NAME ARGUMENTS DESCRIPTION
Int::setViewPort self, Int, Int, Int, sets the current viewport to
Int the absolute screen
co-ordinates left, top,
right, bottom corresponding
to the self argument and the
first three Int arguments
respectively. The final Int
arg is a flag indicating if
clipping is on or off (0 =
off, 1 = on).
Nil::getViewSettings returns a Collection of 5
Int value specifying the
left, top right, and bottom
screen co-ordinates of the
current viewport, and an Int
flag indicating if clipping
is on or off.
Int::setActivePage self sets the active graphics
page to page number of
self.
Int::setVisualPage self sets the visible graphics
page to page number of self.
Nil::clearViewPort self clears the current viewport
and moves the CP to (0,0).
Nil::clearDevice self clears the entire screen and
- 76 -
Chapter 13: Graphics Programming
moves the CP to (0,0).
13.14 Pixels and Images
The BGI system also provides several methods for manipulating images
and pixels on the graphics screen:
NAME ARGUMENTS DESCRIPTION
Int::getPixel self, Int returns the pixel color at
location x,y specified by
self and Int arg
Int::putPixel self, Int, Int sets the pixel at location
x,y (self, Int arg) to color
specified by second Int arg
Int::getImage self, Int returns image stored at x,y
of self, Int arg
Int::imageSize self, Int, Int, Int returns an Int number of
bytes necessary to store a
rectangular area of the
screen. Args are left, top,
right, and bottom
co-ordinates of the region.
Int::putImage self, Int, Image, Intwrites an image to the
screen at x,y of self, first
Int arg. Second Int arg
specifies how bits of the
image will be combined with
bits already on the screen:
copy = 0, xor = 1, or = 2,
and = 3, not = 4.
- 77 -