home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
epm603b.zip
/
EPMATR.ZIP
/
ATTRIBUT.DOC
< prev
next >
Wrap
Text File
|
1989-07-06
|
27KB
|
547 lines
Attribute Support
Jason Crawford
June 3, 1989
Much talk has been going around the industry about hypertext. We do
not want to enter into any heated discussion on the issue, but we believe
that one of the basic ingredients of a hypertext system is the ability to
bind metainformation into text. In its simplest forms this information
might simply be a flag that indicates that a section of the text is to
appear in a certain color or font when displayed. In an advanced form
this information may refer to an action to take when the associated text
is manipulated.
In order to turn some the armchair hypertext programmers into real
hypertext programmers, we have taken a first step by giving E macro pro-
grammers the ability to imbed information within their text. We call
this first step "attribute support."
In this initial release of we allow a macro application to request a
set of attribute "classes" to support its needs. How the requested
attribute classes are used is determined by the application. That
application need not worry about other applications using the same
attribute classes for other purposes since other applications will be
granted other attribute classes for their use.
In this release of attribute support, only 256 attribute classes are
allowed. Attribute class 0 is reserved for use as a wildcard or an error
flag. Class 1 is now reserved for controling the displayed color of text.
Classes 2..63 are reserved for future internally supported uses, and the
remaining 192 attribute classes can be allocated to macro applications
through the allocate_attr() function.
Once an application has been allocated an attribute class, "attribute
records" of that class can be inserted into the text of the document with
the insert_attribute statement. The position of an attribute record is
generally specified with four coordinates: fileid, line, column, and
offset. The first three of these coordinates should already be well
understood by macro programers, but the fourth coordinate is new. In this
initial version of attribute support, no attribute record or character can
occupy the exact same location, so the offset coordinate (which is either
negative or positive; but never zero) indicates whether the attribute
record is before or after the character of the specified column. If
several attribute records exist at the same column, then the offset
coordinate also specifies the relative position of those attribute
records. For example, lets say that we have a line of text in our
document as follows:
This is my line of text.
And let's say that there are three attribute records at the same
column as the "m" in the word "my", as follows:
[arA][arB]m[arC]
If this is the case, then the location of attribute record A is column 9
and offset -2. Attribute record B is at offset -1, and Attribute Record C
is at column 9 offset +1.
Each attribute record has a class field, a value field, and a support
field. The class field (as described above) is a flag that indicates what
kind of information the attribute record conveys. The value field can
hold a value from 0..64k-1, and the meaning of the value field is defined
by the application that is supporting the attribute class specified in the
class field. The support field conveys information that the editor can
use to provide internal support. For example, an attribute records with a
class of COLOR, a value field of 30, and a support field of PUSH indicates
that the text following this record should be colored ???? (which
corresponds to a value of 30), and that that color should be used until a
corresponding COLOR POP attribute record is encountered in the text.
In general, these attributes will not be visible to the user,
but they are accessable within the macro language [see "query_attribute"].
An attribute class can follow one of many attribute models. An
attribute model defines the extent of influence of each attribute record
of each class using that attribute model. The simplest attribute model is
the tag model. An attribute record that has a class that uses a tag model
just denotes a position in a file. A typical usage would be to mark
the location of footnotes or hidden text.
A second attribute model is what I will call a "set-until-next-set"
model. In this model, an attribute record rules over all the text
following itself and preceding the next attribute record in the document
that has the same class. For example, if one turns on font A
just before column 2 and turns on font B just before column 32, then
characters in columns 2..31 should have a font type of A, and characters
after column 31 and characters after the present line should have a font
type of B.
The Color class is the first internally supported attribute class in
E. Its purpose is to allow an application to control the color (foreground
only on PS/55's) of the text when displayed by E. The Color class
attributes use a push/pop attribute model. The basic concept behind this
third model is that all text following an attribute that pushes a color
will appear in that color until a color-pop attribute record occurs. Text
following a color-pop attribute record will be displayed in the same color
as the text that occured before the previous color-push attribute record.
Using this model, an application can nest several levels of color by
inserting several color-push attribute records in the text before a
color-pop attribute record. If no color attributes appear in the text,
then the whole text appears in the default background color. If, at a
certain point in the file, the number of pops occuring earlier in the file
is equal to (or higher than) the number of pushes, then the default color
is used until the next color push occurs. If a color push attribute
record lacks a corresponding color pop attribute record, then the pushed
color will remain active until the end of the file. The included demo
will attempt to clarify any confusion on the matter.
As you play with push/pop modeled attribute classes, you will notice
that the push/pop model does not use the value field of a pop attribute
record. This is because the pop record indicates that the last push
attribute record of the specified class should be popped (regardless of
its value).
We think the push/pop model is a good one. We encourage macro
programers to use the push/pop model for attribute classes that they
engineer because all support that we add for the color's push/pop model
can be used by applications using a push/pop model.
[assert: at this point reader understands colors and push/pop, and binding]
We have built attribute support so that copying, moving, and deleting
a character will take the same action on the attribute records bound to
that character as is done to that character. To illustrate this, create a
line with a variety of color attributes. Just begin editing the text.
Notice that if you deleted a character that had a Push-Color attribute
record with it, then the region after that character will revert to the
previous color rather than the color that was pushed at that character.
The same can be seen with moving, copying, and deleting marked regions,
but that may be more difficult to see.
Although the push/pop model of attribute support is fairly
straightforward, we expect macro programmers to initially run into
some complications.
One of these complications is crossing of attribute pairs of the same
class. The push/pop model only supports "imbedding" of regions within
other regions. If one tries to specify two "overlapping" regions with
attribute records of the same class, one will run into problems because the
new and old attribute records will be interpretted by other applications
as imbedded regions. If it becomes necessary to have overlapping regions
of the same class, then an alternative attribute model should be designed.
[Demo this one.]
A second inconvenience that the macro programmer will face is the
lack of support for attribute strings. This means that the insertline and
replaceline statements only insert attributeless lines into a file, and
the getline statement will only fetch the text of a line. The typical
solution to this problem is to use copy, move, and delete actions on
marked regions rather than insertline's, replaceline's, and getline's.
A third dilemna is that attribute support is provides an API;
but no user interface. We expect that macro programmers will be facing
many dilemna. For example, "What should be done
with attributes attached to a character that the user wants to remove or
replace?" This is a user interface dilemna. Simply deleting the
character and all its associated attribute records may not provide the
best user interface because if the attribute records for a character were
deleted, and one of those attributes had a color CLASS (using a push/pop
model), then the color of almost all text from that character to the EOF
will change. [See Demo ???] This is probably not what was the user intended,
but deciding what was intended is not necessarily easy.
This version of attribute support does not attempt to make such
decisions. Instead, it leaves such decsions to macro programmers, so that
the community of macro programmers can experiment with serveral user
interfaces. In a few weeks we expect several UI's will emerge, and we
will begin supporting them.
This version of attribute support allows a maximum of 255 attributes
per line. Any attempt to add more attributes than 255 attributes will
result in a truncation error being flagged. Similarly, shifting any
attribute beyond column 255 will result in a truncation error being
flagged and the truncated attribute record being lost.
This first version of attribute support does not provide any means for
saving attributes in a file. Such functionality can be expected in
upcoming versions of EPM when OS/2 1.2 becomes more readily available.
Until that time, macro programmers can obtain (undocumented) macros from
JASON at YKTVMV that support the loading and saving of files and their
attributes under OS/2 1.1.
Lastly, EPM is in a rapid state of flux. This is especially true of
attribute support. Any documentation provided for attribute support is
likely to become quickly outdated. Therefore macro programmers should
monitor the EPM FORUM on the IBMPC conference disk to get the most
up-to-date information.
The Classes
This version of attribute supports several predefined attribute
classes to various extents:
COLORCLASS
This attribute class can be used to color regions of text. The color
used is determined by the value field of attribute records of this
class. The values should be the same as those used for CGA monitors
except that "flashing" is not supported.
HIDNCLASS
Attribute records of this class act as tags that flag the location of
text that is hidden. At the moment, hidden text is text that has been
temporarily hidden. This is implmented by a set of macros that move
the text to a hidden file. For further details, please refer to the
macros provided with attribute support.
This class is currently only experimental, so please feel to modify
the supporting macros if you want to do some experimenting of your
own. If you come up with something clever, please let the rest of us
know.
ASSOCCLASS
Attribute records of this class flag the existance of an associated
string. This class is helpful when implementing buttons within a
document (see BUTTONCLASS), and it could be used by a spell checker
for remembering alternate spellings or by a voice recognition system
for remembering probable alternate interpretations. For further
details, please refer to the macros provided with attribute support.
BUTTONCLASS
This attribute class delimits a region (with the push/pop model) that
should be associated with a command. This attribute class works in
conjuntion with the ASSOCCLASS attribute class. For further details
see the BUTTONS.E file provided with this package.
Attribute Statements
The Attribute Support API consists of two macro language statements:
attribute_action, insert_attribute, and query_attribute.
Query_Attribute
this statement allows a macro program to deterine what
attribute record can be found at the specified location.
var Class
returns the class of the found attribute record. A value of
zero is returned if no attribute was found. A value between
1 and 63 is returned if an internally supported attribute
record was found. A value from 64 to 255 is returned if an
application supported attribute record was found. The
meaning of an application supported attribute record is not
predictable at compile time. Some administrative macros
will be provided for determining the meaning of a macro
during runtime.
var Value
returns the value of the found attribute record. Its value
is unchanged if no attribute record was found at the
specified location.
var IsPush
returns the value of the support field of the found
attribute. This parameters value is unchanged if no
attribute record was found at the specified location.
Offset
The offset of the position being queried. Zero is an
illegal offset. A negative value indicates a position
before the specified character location, and a positive
value indicates a value to the right of the specified
character location.
...[ar-2][ar-1][char][ar+1]...
Column
The column number of the position being queried.
Line
The line number of the position being queried.
ViewID (optional)
The fileid of the position being queried. If unspecified,
the current file will be assumed.
Insert_Attribute
this statement (non destructively) inserts an attribute
record at the specified location.
Class
The class of the attribute record to be inserted.
Value
The value field of the attribute record to be inserted.
IsPush
The support field of the attribute to insert.
Offset
The offset of the position being queried. Zero is an
illegal offset. A negative value indicates a position
before the specified character location, and a positive
value indicates a value to the right of the specified
character location.
...[ar-2][ar-1][char][ar+1]...
If an offset is specified that is greater than the largest
offset of an attribute record at the specified column, then
the attribute record is placed at an offset directly to the
right of the attribute record with the greatest offset. The
only exception to this rule is when there are no attribute
records with positive offset at the specified column. In
that case, the attribute record is placed at offset 1.
Similarly, if a negative offset is specified that is less
(more negative) than the smallest offset of an attribute
record at the specified column, then the new attribute
record is placed at an offset that is one less than the
smallest offset.
If an attribute record already exists at the specified
offset, then the old attribute record (and any attribute
records at an offset of larger magnitude) is shifted to an
offset of greater magnitude to vacate the specified
offset for the new attribute record.
Column (optional)
The column number where the new attribute record should be
placed. If this parameter is omitted, the current column of
the cursor is assumed.
Line (optional)
The line number where the new attribute record should be
placed. If this parameter is omitted, the current line
number of the cursor is assumed.
ViewID (optional)
The fileid of the file where the new attribute record
should be placed. If this parameter is omitted, the active
file is assumed.
Attribute_Action
this statement is actually several statements. The
first parameter determines what action is executed. We put
several actions on this statement in order to conserve
opcodes. Each action will be described in turn.
Attribute_Action FIND_NEXT_ATTR_SUBOP
This action finds the next occurance (not including the
specified location) of an attribute record of the specified
class.
var Class
input
This specifies the attribute class of the attribute
records of interest. A value of ANY_CLASS (zero)
indicates that the position of the next attribute record
of any class should be returned.
output
The class of the found attribute. A class of zero
indicates that no attribute record was found.
var Offset, var Column, var Line
input
These parameters specify the location (non-inclusive)
where the search is to begin.
output
These parameters specify the location of the found
attribute record. If none was found, then none of these
parameters will be modified.
var FileId (optional)
The fileid of the file where the search is to occur.
Attribute_Action FIND_PREV_ATTR_SUBOP
This action is just like the FIND_NEXT_ATTR_SUBOP except
that it finds the previous occurance of an attribute record
of the specified class rather than the next occurance.
Attribute_Action FIND_MATCH_ATTR_SUBOP
This action finds the (push/pop model) attribute record
that matches the specified attribute record. For example,
if a push attribute record was specified, the location of
the corresponding pop attribute record is returned.
var Class
unused parameter.
var Offset, var Column, var Line
input
These parameters specify the location (non-inclusive)
where the search is to begin. An attribute record must
exist at this location or an error code will be flagged.
output
These parameters specify the location of the found
attribute record. If none was found, then none of these
parameters will be modified.
var FileId (optional)
The fileid of the file where the search is to occur.
Attribute_Action DELETE_ATTR_SUBOP
Deletes the attribute record at the specified location. If
attribute records exists at the specified character
position having an offset of the same sign as the specified
attribute record but of larger magnitude, then those
attribute records will be shifted in (their offset will be
incremented or decremented) to fill in the vacated
location.
var Class
input
unused input parameter.
output
The class of the deleted attribute record. Zero if no
attribute record exists at the specified location.
var Offset, var Column, var Line
The location of the attribute record to be deleted.
var FileId (optional)
The fileid of the file where the specified attribute
record is to be found.
Demo
Several "GeeWhiz" demos are provided with this package in order help
people realize the capabilities of attribute support. (Tutorials are
also provided for educational purposes.)
Demo 1 - EPM Calc
This demo simulates a reverse Polish notation calculator.
It also provides good sample code of the use of buttons.
Instructions
1) Compile BUTTONS.E, ATTR.E, EPMCALC.E, and HIDEIT.
2) Start EPM
3) Issue the command "LINK EPMCALC"
4) Wait a moment for a calculator to appear
5) To "press" the calculator's buttons, move the
pointer over the button to be pressed, hold
down the Alt key, and double click on the
left mouse button.
Advanced Instructions
6a)
Do a block mark of the calculator. Now duplicate
it. Notice that both calculators work
independently. This is because each instances
state information is stored in the file with it's
graphic representation. (See EPMCALC.E)
6b)
Do a block mark on a button. Duplicate it outside the
calculator. Notice that the button still works. Now
move (if you have done 6a) the button close to another
calculator. Notice that it now acts upon this second
calculator rather than its original calculator. This
is because EPMCALC's buttons apply their action on the
nearest calculator. (See EPMCALC.E)
6c)
Color the calculator by block marking it,
The Code
FindCalc
Demo 2 - Highlight Phrase
Instructions
1) Compile ATTR.E.
2) Start EPM
3) Issue the command "LINK ATTR"
4) Edit an interesting file.
5) Highlight all occurances of a phrase. This
can be done by invoking the HIGHLIGHT_PHRASE
command with the word to be highlighted as
the first argument.
6) The default color is 93. An alternate color
can be selected by giving a second argument
in the range of 0 to 255.
Advanced Instructions
7)
The HIGHLIGHT_IDENTIFIER command may be more
useful when attempting to highlight all occurances
of an identifier in a Pascal, C, or E program.
8)
Highlight a many words in a paragraph using this
method. Change the margins, and reflow the
paragraph.
Demo 3 - Hide C Blocks
Instructions
1) Compile ATTR.E, CBLOCK.E and HIDEIT.E.
2) Start EPM
3) Issue the command "LINK CBLOCK"
4) Edit a .C file.
5) Place the pointer over a { character.
6) Ctrl-Right-DoubleClick
7) Notice that logical block that was delimited by
by the clicked '{' (and it's matching '}') was
compressed.
8) Place the pointer on the green '*'.
9) Alt-Right-DoubleClick.
10) Notice that the "hidden" block has reappeared.
Advanced Instructions
11) Same as above, but try to imbed hidden regions.
12) For further details see CBLOCK.E.
Tutorial 1 -
Demo 2 is really simple. Just look at the code for
HIGHLIGHT_PHRASE in ATTR.E.
Tutorial 2 - Complications of attributes
1) Mark a region of a file. Preferably "CHAR" mark.
2) invoke "set_marked_region_to_color 43"
3) Unmark the region.
4) Notice that the formally marked region now
appears a different color. (Color 43).
5) Continue doing step 4.
6) Experiment with insertion of characters, deletion,
mark copies, mark moves, etc. of attributes.
Tutorial 3 - Making a button
1) link in BUTTONS.EX
2) Block mark a large region.
3) Fill that region with spaces by invoking
"FILL"
4) Draw a border in the mark by invoking
"NICE_BOX"
5) Put the words "List files" in the button box
6) Block mark the button again.
7) Associate the "dir" command with the button by invoking
"associate_phrase_with_mark 4 DIR"
8) Block mark the button region.
9) Color the button by invoking
"set_marked_region_to_color 43"
10) Now we have a colored button with a border that
should execute a "dir" command when it is
pressed.
11) Enable the mouse for button depression by invoking
"enable_attr_keys"
12) Move pointer over the button.
13) Alt-Left-DoubleClick