v01i065: hype - a SunView object-oriented window builder, Part05/11
Charles Mcgrew
mcgrew at dartagnan.rutgers.edu
Fri Sep 15 12:47:04 AEST 1989
Submitted-by: apctrc!zmls04 at uunet.uu.net (Martin L. Smith)
Posting-number: Volume 1, Issue 65
Archive-name: hype/part05
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# Tutorial
# archives
# This archive created: Thu Sep 14 20:53:16 1989
export PATH; PATH=/bin:$PATH
if test ! -d 'Tutorial'
then
echo shar: creating directory "'Tutorial'"
mkdir 'Tutorial'
fi
echo shar: entering directory "'Tutorial'"
cd 'Tutorial'
echo shar: extracting "'introduction'" '(597 characters)'
if test -f 'introduction'
then
echo shar: will not over-write existing file "'introduction'"
else
sed 's/^ X//' << \SHAR_EOF > 'introduction'
X.bp 1
X.ds CF -%-
X.SH
X.LG
XGetting Started
X.NL
X.PP
XThis document is a brief,
Xself-contained, tutorial introduction to \fBhype\fR.
XThe tutorial takes you, step by step,
Xthrough the construction of a simple, but complete,
X.B hype
Xapplication
X(or \fImachine\fR).
XAll you will require is this tutorial,
Xa Sun workstation,
Xaccess to the program
X.B hype ,
Xand the ability to use the
X.B vi
Xeditor.
X.PP
XThis tutorial is not a complete description of
X.B hype .
XMany of the script language features and functions
Xare not discussed.
XA more thorough exposition is available in
X.B "Hype: A Programmer's Guide" .
SHAR_EOF
if test 597 -ne "`wc -c < 'introduction'`"
then
echo shar: error transmitting "'introduction'" '(should have been 597 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'jumpstart'" '(5671 characters)'
if test -f 'jumpstart'
then
echo shar: will not over-write existing file "'jumpstart'"
else
sed 's/^ X//' << \SHAR_EOF > 'jumpstart'
X.bp
X.SH
X.LG
XI. Jump-starting Hype: Making a State File
X.NL
X.PP
X.B Hype
Xsupports a tree-structured hierarchy of
X.I objects.
XAn object contains zero or more
X.I panes.
XA pane is a visual sub-region of an object and may contain one or more
X.I items
X(widgets), through which a user may interact with
X.B hype.
XA
X.I template
Xis a pattern on which widgets are arranged;
Xwhen a template is added to an object for
Xdisplay it becomes a pane.
XThe class of objects, panes, items, and templates are
X.B hype 's
X.I entities .
X(For more on entities, see
X.B "Hype: A Programmer's Guide" .)
X.PP
X.B Hype
Xnormally begins life by reading a \fIstate \fIfile\fR.
XThe state file contains a complete description of the entities,
Xattributes, values, and scripts
Xwhich cause
X.B hype
Xto assume the personality programmed into it
X(and also the entity values and screen positions in use
Xthe last time
X.B hype 's
Xstate was saved).
XIn this section
Xwe will create a new state file,
Xone with a single object in it.
X.RS
X.IP \(em
XFrom within
X.B suntools
Xor
X.B sunview ,
Xstart
X.B hype
Xby typing the command
X.I "hype -s"
X.RE
X.LP
X(The \fB-s\fR tells
X.B hype
Xnot to look for a state file.)
XThis command causes a large,
Xnauseous-yellow window to open in the middle of the screen.
XThe window label will be (something like)
X.DS C
X\fB/MASTER\fR
X.DE
X.RS
X.IP \(em
XOpen the object's border menu
X(click the right mouse button on the frame or title bar of the yellow window).
X.IP \(em
XWalk through the
X.B Object\(rh
Xsub-menu,
Xand then select
X.B "Object Info" .
X(In the future we will refer to menu actions in this style:
X``from the object's border menu select \fBObject\fR\(rh\fBObject Info\fR''.)
X.RE
X.LP
XThis will open an
X.I "object info box"
Xsomewhere on the screen.
XIt has labeled fields for several of an object's
Xattributes and it shows the object's current attributes
Xin those fields.
XSome fields are read-only
Xand consist of ``field name = number''.
XThe fields that are changeable consist of
X``field name: changeable contents''.
XPressing the return key or the tab key moves
Xthe cursor forward through the changeable fields.
XPressing shift-tab moves the cursor
Xbackwards through the changeable fields.
X.PP
XWe wish to change the name,
Xlabel,
Xand (especially) the color of
X.B MASTER
X(which is the root object of your new
X.B hype
Xtree).
XTo do this,
Xperform the following steps:
X.RS
X.IP \(em
XDelete \fBMASTER\fR from the \fBObject Name\fR
Xfield and type in \fITutorial\fR.
X.IP \(em
XInto the
X.B Label
Xfield type \fIMy Tutorial Root\fR.
X.IP \(em
XInto the
X.B Color
Xfield type ``\fI214 183 27\fR''
X(without the quotes, but with the spaces);
Xthis is an earthy looking color that's easier to read
X(with some background colors) than the original.
XYou can type any legal \fIrgb\fR combination into this field.
X.IP \(em
XClick the left mouse button on the
X.B OK
Xbutton.
X.RE
X.LP
XNote that the label bar changes to the new label.
XThe color may not change
X(\fBhype\fR has a small problem here);
Xif it remains yellow,
Xclick the left mouse button on the object's frame.
XThis will cause the object to refresh its display
Xand it will assume its new color.
X.PP
XNow save
X.B hype 's
Xcurrent state to a file:
X.RS
X.IP \(em
XFrom the border menu select
X\fBFile\fR\(rh\fBFile\ State\fR.
X.IP \(em
X.B Hype
Xwill prompt for a file name for the state file.
XType in
X\fItut.hyp\fR
Xand click left on
X.B OK .
X(By convention,
X.B hype
Xstate files end in ``\fI.hyp\fR''.)
X.IP \(em
XFrom the border menu select
X\fBFile\fR\(rh\fBQuit,\ No Save\fR
Xand respond to the pop-up by clicking left on
X.B YES .
X.RE
X.LP
X.B Hype
Xexits and leaves us back in the shell.
XThere should be a small file named \fBtut.hyp\fR
Xin the current directory.
X.PP
XFor the rest of the tutorial use the command
X.DS C
X\fBhype -Stut.hyp\fR
X.DE
Xto start
X.B hype .
XThis will cause it to read
X.B tut.hyp
Xat start-up and to write its current state back to the same file
Xon a ``normal'' exit.
X(A normal exit is \fBFile\(rhSave\ &\ Quit\fR
Xfrom any object's border menu.)
X.SH
XSome Things to Note
X.PP
XObject info boxes have a field for the object color.
XYou will want to use
X.B colortool
Xto decide what
X.I rgb
Xinteger combination to use.
XWhen a menu or an info box is on the screen, however,
Xyou can't do anything except interact with it;
Xeverything else on the screen is frozen
X(even the clock is stopped).
XOne consequence of this is that you cannot
Xinvoke \fBcolortool\fR while an info box is open.
XThe simplest way to handle this is to play with
X.B colortool
Xto find a zippy color selection
X.I before
Xyou open the appropriate info box.
X.PP
XIt is not necessary to name the desired state file
Xon
X.B hype 's
Xcommand line;
Xthere are environment variables which will
Xprovide defaults for all command line options.
XThey are discussed in
X.B "Hype: A Programmer's Guide" .
XWe do not use them here for simplicity.
X.PP
X.B Hype
Xoffers facilities
X(all available under the
X.B File\(rh
Xsub-menu from any object's border menu)
Xfor
X.RS
X.IP \(bu
Xupdating the state file without exiting:
X\fBFile\(rh\fBSave\ State\fR.
XYou should use this fairly often since
X.B hype
Xoccasionally crashes.
XYou may do this any time you can get to
Xan object border menu.
X.IP \(bu
Xupdating the state file and exiting:
X\fBFile\(rh\fBSave\ &\ Quit\fR.
XThis is a normal quit.
X.IP \(bu
Xexiting \fIwithout\fR updating the state file:
X\fBFile\(rh\fBQuit,\ No\ Save\fR.
XUse this if you've really screwed up.
X.RE
X.LP
XThe state file is the \fIonly\fR
Xrecord of your programming effort.
XIt is source code as surely as any
X.SM
XFORTRAN
X.NL
Xor C file
Xand you should treat it with reverence and paranoia.
XMaking backup copies is appropriate.
X(This is known as
X.I "Do As I Say, Not As I Do" ,
Xand is the only fun part about writing tutorials.)
SHAR_EOF
if test 5671 -ne "`wc -c < 'jumpstart'`"
then
echo shar: error transmitting "'jumpstart'" '(should have been 5671 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lookingback'" '(4524 characters)'
if test -f 'lookingback'
then
echo shar: will not over-write existing file "'lookingback'"
else
sed 's/^ X//' << \SHAR_EOF > 'lookingback'
X.bp
X.LP
XReplace this page with figure V. Looking Back.
X.bp
X.PP
XLet's dissect the message-passing behavior
Xthat we programmed into the thermometer bars
Xand into the object (\fBThermometer\fR)
Xwhich owns them.
XWe assume that the object is open.
X(Refer to the figure a few pages after this one.)
X.PP
XIf the cursor is over any part of the slider portion of
X.B "DegF" ,
Xand the left button is pressed,
Xthe message
X.B mouseDown
X(which we don't intercept) is sent to the item
Xand then the slider
Xis set to the value indicated by the cursor.
XWhen the left button is released,
Xthe message
X.B mouseUp
Xis sent to the item.
XNote that if the cursor is moved off the slider bar
Xwhile the left mouse button is still depressed,
Xthe bar jumps back to its previous position
Xand (though you cannot tell from watching)
X.B mouseUp
Xis not sent.
X.PP
XUsing
X.B mouseUp
Xinstead of
X.B mouseDown
Xoffers two advantages:
XFirst,
Xwhen we read the item's value from inside of a script,
Xwe get the new value.
XSecond,
Xwe can retract our change by moving the cursor off of the
Xitem before releasing the button.
X.PP
XThe alternative choice,
X.B mouseDown ,
Xhas the advantage that the button you have activated
X(assuming you've clicked on an item of type button)
Xremains darkened while the script invoked is still active.
XThis is a useful way of telling the user that
X.B hype
Xis busy fulfilling some request and will not yet respond to new input.
XAt present, however,
X.B hype
Xsometimes gets confused about handling the display of active items.
XIf you wish to use
X.B mouseDown ,
Xyou should be prepared to do some experimentation to make
Xsure that it performs properly.
X(We will try to fix this soon.)
X.PP
XIf you click left on the label portion of the slider bar,
Xthe same messages are sent but the slider's value is not changed.
XObserve that doing so makes the bars flicker as they are redrawn
Xbut their values don't change.
X.PP
XWhen
X.B DegF
Xintercepts
X.B mouseUp ,
Xthe script snippet which handles that message is executed.
XThis snippet reads its item's own value and
Xconverts the value (presumed to be in Fahrenheit)
Xto centigrade (Celsius).
XThe script snippet then sends the message
X.B degreesC
Xto its owning object (\fBThermometer\fR),
Xreferred to as \fB"."\fR in the script,
Xwith the centigrade temperature as the message's parameter.
X.PP
XNote that we could instead have sent the message
Xto \fBself()\fR,
Xwhich in this case would have been the item
X.B DegF .
XIf we had written the script that way,
Xthe message would have passed \fIthrough\fR
X.B DegF
Xand its owning pane
X.B Mercury ,
Xsince neither of these provides a handler for
Xthe message
X.B degreesC .
XIt then would have been passed to the object
X.B Thermometer ,
Xwhose script would intercept the message.
X.PP
XWhen
X.B Thermometer
Xreceives
X.B degreesC ,
Xits script is executed.
XThat script sends the message
X.B changeTo ,
Xwith the centigrade temperature as its parameter,
Xto every item in every pane owned by the object.
XWe did it that way to avoid having to program pane and item
Xnames into the script but, as you can see,
Xthe resultant script is kludgy.
XWe will probably provide a smoother mechanism in the future,
Xbut the one we show works
X(and will do so in the future).
X.PP
XEach of the items to which
X.B changeTo
Xis sent either ignores the message
X(as the button \fBC\fR does)
Xor responds to it
X(as the slider bars do by changing their values).
X.PP
XWhen
X.B Thermometer 's
Xscript is finished,
Xit returns to its caller, the
X.B DegF
Xscript.
XAt this time,
Xthe
X.B mouseUp
Xhandler in
X.B DegF
Xis finished and it exits.
X.PP
XAt one time,
X.B DegF
Xhad two handlers active.
XThis occurred because
X.B DegF
Xsent a message that was intercepted by
X.B Thermometer
Xwhich in turn sent a message that was intercepted by
X.B DegF .
XA script snippet remains active until execution
Xhas encountered an explicit
X.B return
Xor has run off the end of the script.
XIt is legal for a script to invoke itself recursively
X(it can even send standard messages such as
X.B mouseUp ).
X.PP
XAll messages return a value to the entity that sent them.
XMessages which are not caught return an empty string to the sender.
XMessages which are caught may return anything specified by the catcher
Xin a \fBreturn\fR statement
X(although we haven't used that feature here).
XIf the intercepting script does not have an explicit
X.B return ,
Xthe empty string is returned.
XThe returned value of a message is available as the return value
Xof the
X.B send
Xfunction which created the message.
X.bp
X.LP
XReplace this page with figure Message-passing in the Tutorial.
SHAR_EOF
if test 4524 -ne "`wc -c < 'lookingback'`"
then
echo shar: error transmitting "'lookingback'" '(should have been 4524 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'macros'" '(20 characters)'
if test -f 'macros'
then
echo shar: will not over-write existing file "'macros'"
else
sed 's/^ X//' << \SHAR_EOF > 'macros'
X.nr PS 11
X.nr VS 13
SHAR_EOF
if test 20 -ne "`wc -c < 'macros'`"
then
echo shar: error transmitting "'macros'" '(should have been 20 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'maketree'" '(3058 characters)'
if test -f 'maketree'
then
echo shar: will not over-write existing file "'maketree'"
else
sed 's/^ X//' << \SHAR_EOF > 'maketree'
X.bp
X.SH
X.LG
XII. Building a Tree
X.NL
X.PP
X.B Hype
Xprogramming has two distinct aspects.
XOne is \fIentity \fIcreation\fR,
Xduring which we add to the
X.B hype
Xtree the entities
X(objects, panes, and items)
Xwhich the final state will need.
XThe other is \fIentity \fIprogramming\fR,
Xduring which we assign
X.I behavior
Xto entities by writing scripts which define
Xthe response of each entity to various messages.
XBuilding a
X.B hype
Xmachine is usually a process of alternating
Xbetween these two activities and incrementally
Xcreating a structure which does whatever we needed to do.
X.PP
XIn this section
Xwe are going to extend our
X.B hype
Xmachine by adding
Xa child subobject to our root object.
X.RS
X.IP \(em
XStart
X.B hype
Xwith \fIhype\ \ \fI-Stut.hyp\fR
X(We're not going to tell you how anymore.)
XThe root object will appear on the screen
Xin the position it had when the state file
Xwas last saved.
X(Sometimes
X.B hype
Xforgets its last position.
XDon't be alarmed if the next time you start
X.B hype
Xit has forgotten the positions of your entities on the screen.)
X.IP \(em
XFrom its border menu use
X.B Window\(rhMove
Xand
X.B Window\(rhResize
Xto make this object
Xa manageable size and to put it into a convenient position.
X.IP \(em
XNow use
X.B "File\(rhSave\ State"
Xto update the state file
X.B tut.hyp
Xwith these new positions and sizes.
X.RE
X.LP
XNow, to create a new object:
X.RS
X.IP \(em
XFrom the root's border menu select
X.B "Object\(rhCreate\ Child" .
XThis will create a large, yellow child
Xobject with a peculiar name.
X.IP \(em
XFrom the child's border menu select
X.B "Object\(rhObject\ Info" .
X.IP \(em
XChange
X.B "Object Name"
Xto
X.I Thermometer .
X.IP \(em
XInto
X.B "Object Label"
Xtype
X.I Thermometer .
X.IP \(em
XInto
X.B "Object Color"
Xtype
X(without the quotes)
X``\fI143 134 214\fR''
X(or any \fIrgb\fR combination you prefer).
X.IP \(em
XClick left on
X.B OK .
X.IP \(em
XClick left in
X.B Thermometer 's
Xborder to get the object to refresh, thus updating the color.
X.IP \(em
XMove and resize the object,
Xfrom its border menu,
Xto make it livable.
XIt would be best if it didn't overlap
Xthe root object.
X.IP \(em
X.I "Save your state" .
X(Use
X.B "File\(rhSave State" .)
X.RE
X.RE
X.LP
XYour
X.B hype
Xtree now has two objects.
XThe tree's root is named
X.B Tutorial
Xand the root's single child object is named
X.B Thermometer .
XThis
X.B hype
X``machine'' does not yet do anything useful.
X.RS
X.IP \(em
XNow leave
X.B hype
Xnormally,
Xby selecting
X.B "File\(rhSave\ &\ Quit"
Xfrom
X.I either
Xobject's border menu.
XThis method of quitting causes the state file
Xto be updated automatically.
X.IP \(em
XResume
X.B hype .
XOnly the root object appears on the screen,
Xalthough it
X.I should
Xbe where you last saw it.
X.IP \(em
XTo open
X.B Thermometer ,
Xselect
X.B "Object\(rhOpen\ Child\(rhThermometer" .
X.RE
X.LP
XIn this process,
X.B hype
Xallowed you to conveniently open
Xany of the root's children.
XMenu-based navigation like this is really intended
Xonly for programming
X.B hype .
XFor the casual user,
Xwe will
Xprovide a button
X(in the next section)
Xthat achieves the same effect.
X.RS
X.IP \(em
XExit
X.B hype
Xnormally.
X.RE
SHAR_EOF
if test 3058 -ne "`wc -c < 'maketree'`"
then
echo shar: error transmitting "'maketree'" '(should have been 3058 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'onward'" '(2926 characters)'
if test -f 'onward'
then
echo shar: will not over-write existing file "'onward'"
else
sed 's/^ X//' << \SHAR_EOF > 'onward'
X.bp
X.SH
X.LG
XVI. Additional Features
X.NL
X.PP
XThis section discusses some additional features
Xyou can add to your machine.
XWe strongly suggest you pursue these.
XThe suggestions illustrate new features of
X.B hype ,
Xand the experience is worthwhile.
X.NH 0
XExit
X.PP
XYour machine currently has no way to exit
X.B hype
Xwithout using an object border menu.
XA finished
X.B hype
Xapplication should be entirely item-driven;
Xthe user should not have to use the menu system for anything.
XOur first suggestion, then, is that you add an
X.B Exit
Xbutton to the root object.
XThe button's script should look like this:
X.RS
X.DS
X\fBmouseUp:
X{
X exit();
X}.\fR
X.DE
X.RE
X(Don't forget the trailing period.)
XThe
X.B exit()
Xcall saves your state before quitting.
X.PP
XThere is a certain amount of dexterity involved
Xin adding items to small panes and objects.
XWe suggest you proceed like this:
X.RS
X.IP \(em
XDelete the current pane from the object.
X(Look for the
X.B Pane\(rh
Xmenu.)
XThis does \fBnot\fR delete the template.
X.IP \(em
XOpen the appropriate template,
Xmake it larger,
Xand add the new item.
X.IP \(em
XSet the new item's info and script as appropriate.
X.IP \(em
XAlter the template to the desired final size.
X.IP \(em
XMake the host object bigger than the new template requires.
X.IP \(em
XAdd the template as a pane.
X.IP \(em
XSize the object as desired.
X.RE
X.NH
XinitHype
X.PP
XAt startup time,
X.B hype
Xbroadcasts the message
X.B initHype
Xto every object in its tree.
X(Note that
X.B broadcast
Xmessages only go to objects,
Xnot to panes or items.)
XThe parameter of this message,
Xif any,
Xis the last unrecognized option on
X.B hype 's
Xcommand line.
XIf
X.B hype
Xis invoked with
X.DS C
X\fBhype\ \ \-\Stut.hyp thermometer\fR
X.DE
Xthe parameter of
X.B initHype
Xwill be
X.B thermometer .
X.PP
XWe can use this feature to cause
X.B hype
Xto begin with selected windows open.
XTo use this,
Xopen an editor on the script of the
X.I object
X.B Thermometer
Xand
X.I add
Xthe following to its current script
X(look for
X.B "Object\(rhObj\ Script\(rhEdit\ Script" ):
X.RS
X.DS
X\fBinitHype:
X{
X if(param() == "thermometer")
X open(self());
X}.\fR
X.DE
X.RE
X.LP
Xand then try starting
X.B hype
Xwith
X.DS C
X\fBhype\ \ \-\Stut.hyp thermometer\fR
X.DE
X.NH
Xstderr()
X.PP
X.B Hype 's
Xscript supports the function
X.DS C
X\fBstderr(\fIstring\fB)\fR
X.DE
Xwhich prints its argument, followed by a newline,
Xto
X.B hype 's
X.I "standard error" .
XThe latter is usually directed to the shelltool from which
X.B hype
Xwas started.
X.PP
X.B Stderr()
Xis very useful for debugging scripts.
XTry adding calls to this function
Xin some of the scripts.
XFor example,
Xin the object script for
X.B Thermometer ,
Xwithin the script for
X.B degreesC
Ximmediately after the
X.B send()
Xcall and before the next ``}'',
Xadd the line
X.DS C
X\fBstderr(self() $$ " sent changeTo with " $$ newtemp $$ " to " $$ item);\fR
X.DE
Xand then see what shows up on the shelltool when you click on a slider.
X(The ``$$'' is
X.B hype 's
Xstring concatenation operator.)
SHAR_EOF
if test 2926 -ne "`wc -c < 'onward'`"
then
echo shar: error transmitting "'onward'" '(should have been 2926 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'title'" '(181 characters)'
if test -f 'title'
then
echo shar: will not over-write existing file "'title'"
else
sed 's/^ X//' << \SHAR_EOF > 'title'
X.TL
X.LG
X.LG
X.LG
XHype: A Tutorial
X.NL
X.sp 2
X.AU
X.LG
X.LG
XMartin Smith
XKim Dill
XTerri Fischer
XRob Read
X
XJanuary 10, 1989
X.NL
X.DA
X.ds CH Hype: A Tutorial \(em Version 1.2
X.ds CF
X.PP
X
X
X
SHAR_EOF
if test 181 -ne "`wc -c < 'title'`"
then
echo shar: error transmitting "'title'" '(should have been 181 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'usemessages'" '(7807 characters)'
if test -f 'usemessages'
then
echo shar: will not over-write existing file "'usemessages'"
else
sed 's/^ X//' << \SHAR_EOF > 'usemessages'
X.bp
X.SH
X.LG
XIV. Using Messages
X.NL
X.PP
XIn this section
Xwe will add a simple temperature conversion
Xsystem to thermometer.
XWe will dispense with most of the step-by-step
Xinstructions.
XRemember to save your current state frequently.
X.PP
X.RS
X.IP \(em
XStart
X.B hype
Xand click left on the
X.I button
Xlabeled
X.B "Open Thermometer"
Xto open the
X.I object
Xnamed
X.B Thermometer .
X.IP \(em
XAdd a template to the object
X.B Thermometer
Xand name it
X.B Mercury .
X.IP \(em
X.I "Save your state" .
X(Pretend that every item in this list ends with
X"\fISave Your State\fR".)
X.IP \(em
XMove
X.B Mercury
Xso it doesn't overlap any object and resize it
Xto make it a bit bigger.
XThen add the following three items,
Xpositioning them tastefully in the template:
X.RS
X.IP \(em
XA button
X.B named
Xand
X.B labeled
X.I C ,
Xfor close .
X.IP \(em
XAn item of
X.B Type
X.I Slider ,
X.B named
X.I DegF ,
X.B labeled
X.I "Deg F" ,
Xrunning from a
X.B Min
Xof
X.I 32
Xto a
X.B Max
Xof
X.I 212
Xwith a
X.B "Display Length"
Xof
X.I 180 .
X(A good practice is to give the item a name
Xwhich is identical to its label with all the spaces removed.)
XNote that you click on an item in the
X.B Type
Xlist to change an item's type into something other than a button.
X.IP \(em
XAn item of
X.B Type
X.I Slider ,
X.B named
X.I DegC ,
X.B labeled
X.I "Deg C" ,
Xrunning from a
X.B Min
Xof
X.I 0
Xto a
X.B Max
Xof
X.I 100
Xwith a
X.B "Display Length"
Xof
X.I 180 .
X.RE
X.IP \(em
XShrink-wrap the template
X.B Mercury
Xusing
X.B "Window\(rhFit\ Window"
Xfrom the template's border menu.
X.IP \(em
XResize the object
X.B Thermometer
Xso it's large enough to hold the new template.
X.IP \(em
XAdd the template
X.B Mercury
Xto the object
X.B Thermometer
Xas a pane.
X(Hint:
Xlook for a
X.B Pane\(rh
Xmenu item in
X.B Thermometer 's
Xborder menu.)
X.IP \(em
XClick left on the slider bars in the pane
X(in the
X.I pane,
Xnot in the
X.I template);
Xnote that they respond and alter their values.
X.RE
X.PP
XThe bars' values,
Xas well as the values of all other items,
Xare saved in the state file;
Xso if you set
X.B "Deg C"
Xto 27 degrees and exit
X.B hype
Xnormally, then the next time you run
X.B hype
Xwith this state file, the value in
X.B "Deg C"
Xwill be 27 degrees.
XAlso note that clicking on the bars in the \fItemplate\fR
Xhas no effect;
Xthose values may only be changed by altering the item's
X\fBDefault\fR value through its info box.
X.PP
XWe now have a system of two objects,
Xeach of which has a pane and some items.
XThe only item that does anything besides change its value
Xis the button in the root object.
XNow we'll add some behavior to the
X.B C
Xbutton in
X.B Thermometer :
Xwe'll program the button to close its owning object,
X.B Thermometer .
X.RS
X.IP \(em
XGive the
X.B C
Xbutton this script (hint: look in the template contents menu):
X.RS
X.DS
X\fBmouseUp:
X{
X close("."); # "." refers to the current object
X}.
X.DE
X.RE
X(Everything after a "#" in a script is a comment.)
X.IP \(em
XClick left on
X.B C
X(in the \fIpane\fR, not the \fItemplate\fR) and observe that
X.B Thermometer
Xcloses.
X.IP \(em
XReopen it by using the button in the root object.
X.RE
X.PP
XItem-driven support for opening and closing objects
X(navigation)
Xis important if we want to spare the final user
Xthe effort of using
X.B hype 's
Xprogramming menus.
X(By the way, have you remembered to
X.I "save your state" ?)
X.PP
XThe last and most complicated piece of programming
Xis to synchronize the thermometers so that whenever
Xwe change one,
Xthe other changes to reflect the equivalent temperature.
XThat is,
Xif we click
X.B "Deg F"
Xto 70,
X.B "Deg C"
Xshould change itself to show 21.
XWe will do this in a slightly roundabout way
Xin which we allow entities in
X.B Thermometer
Xto communicate only through message-passing;
Xwe will not let any entity access another entity's value directly.
X.PP
XThe scheme is this:
XWhenever either of the slider bars receives a
X.B mouseUp
Xmessage,
Xit will read its own value,
Xconvert that to centigrade (if needed),
Xand send the message
X.B degreesC
Xfollowed by the current centigrade temperature as a parameter
Xto
X.B Thermometer ,
Xthe owning object.
X.B Thermometer
Xwill intercept the new temperature message,
X.B degreesC ,
Xand will send message
X.B changeTo
Xfollowed by the new temperature,
Xto every item it owns.
XThe message will be ignored by
X.B C ,
Xthe button,
Xand it will be used by the thermometer bars
Xto set a new value.
X(See the figure
X.B "Message-passing in the Tutorial"
Xnear the end of the tutorial.)
XAs you will see in the scripts,
Xwe are able to do this without having to program
Xany entity's name into any other entity;
Xall we have to know is the message-passing convention.
X.KS
X.PP
XFirst we'll add the script for
X.B Thermometer ,
Xthe object.
X.RS
X.IP \(em
XFrom
X.B Thermometer 's
Xobject border menu, select
X.B "Object\(rhObj Script\(rhEdit Script" .
X.IP \(em
XInsert this script:
X.RS
X.DS
X# Everything between a "#" and the end of the line is a comment.
X# You don't have to type comments into the script.
X# param() returns the received message's parameters.
X# self() returns the current entity's name, sometimes
X# called the "current context" in hyplish.
X# The funny looking stuff on the line starting with
X# pane = ...
X# is an alternate syntax for describing the members of
X# the set of entities owned by another entity,
X# where "$$" is hype's string concatenation operator.
X# See Hype: A Programmer's Guide for much more on all of this.
X\fBdegreesC:
X{
X newtemp = param(); # Comments can go here too.
X for(i = 0; i < numpanes(self()); i++) {
X pane = self() $$ "!" $$ i;
X for(j = 0; j < numitems(pane); j++) {
X item = getnthitem(pane, j);
X send("changeTo", item, newtemp);
X }
X }
X}.\fR
X.DE
X.RE
X.RE
X.LP
XThis script loops over all of the items of all of the panes
Xin this object.
XIt sends the same message to each,
Xwithout worrying about whether each particular item
Xwill respond to the message.
X.KE
X.KS
X.PP
XThe script for each of the slider bars has two message handlers
Xin it.
XOne must respond to the
X.B mouseUp
Xmessage that is sent by
X.B hype
Xitself on a left mouse button event.
XThe second handler must respond to the
X.B changeTo
Xmessage that comes from
X.B Thermometer
Xwhenever a new temperature is registered.
X.RS
X.IP \(em
XGive
X.B "Deg F"
Xthis script (hint: look in
X.B Mercury 's
Xtemplate contents menu.):
X.RS
X.DS
X\fBmouseUp:
X{
X value = getitemval(self());
X centigrade = 5.0 * ( value - 32 ) / 9.0;
X send("degreesC", ".", centigrade);
X}.
XchangeTo:
X{
X fahrenheit = (9.0 * param() / 5.0) + 32;
X setitemval(self(), fahrenheit);
X}.\fR
X.DE
X.RE
X.IP \(em
Xand give
X.B "Deg C"
Xthis script:
X.RS
X.DS
X\fBmouseUp:
X{
X value = getitemval(self());
X send("degreesC", ".", value);
X}.
XchangeTo:
X{
X setitemval(self(), param());
X}.\fR
X.DE
X.RE
X.IP \(em
XYou should now be able to click left on either of the slider bars in
X.B Thermometer
Xand have the change reflected in the other bar.
XIf the slider you
X.I "didn't"
Xclick on
X.I "doesn't"
Xchange,
Xcheck your typing
X.I very
Xcarefully in all the scripts you've created.
XAlso, don't forget to
X.I "save your state"
Xonce it works.
XYou may also
X.B "Quit Template"
Xfrom
X.B Mercury 's
Xborder menu now (if you're scripts are working).
X.RE
X.KE
X.SH
XSome Things to Note
X.PP
XBoth slider bars currently have the same length.
XThere is no reason that this has to be so.
XTry changing
X.B "Deg C"
Xso that its length is 100.
XNote that after you change the item's info,
Xthe template changes immediately.
XTo make the pane reflect the new length,
Xcause the entire object to refresh by clicking
Xleft on the object's border.
X.PP
XCurrently, error handling is very poor.
XTry deliberately omitting the final period in a script
Xor mistyping part of a script
Xso you can see what
X.B hype
Xwill (or will not) do.
X.PP
XYou may shrink-wrap an object around its panes by using
X.B "Window\(rhFit Window"
Xfrom an object's border menu.
XWe didn't mention it before so that you would be able to clearly
Xdistinguish between the object border and the pane border.
SHAR_EOF
if test 7807 -ne "`wc -c < 'usemessages'`"
then
echo shar: error transmitting "'usemessages'" '(should have been 7807 characters)'
fi
fi # end of overwriting check
echo shar: done with directory "'Tutorial'"
cd ..
if test ! -d 'archives'
then
echo shar: creating directory "'archives'"
mkdir 'archives'
fi
echo shar: entering directory "'archives'"
cd 'archives'
if test ! -d 'container'
then
echo shar: creating directory "'container'"
mkdir 'container'
fi
echo shar: entering directory "'container'"
cd 'container'
echo shar: extracting "'Makefile'" '(157 characters)'
if test -f 'Makefile'
then
echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^ X//' << \SHAR_EOF > 'Makefile'
XCFLAGS = -g
Xcontainer.a: container.o
X ar rcv container.a container.o
X ranlib container.a
X
Xctest: ctest.o
X cc -o ctest ctest.o ../mfile/mfile.a container.a
X
SHAR_EOF
if test 157 -ne "`wc -c < 'Makefile'`"
then
echo shar: error transmitting "'Makefile'" '(should have been 157 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'container.c'" '(4713 characters)'
if test -f 'container.c'
then
echo shar: will not over-write existing file "'container.c'"
else
sed 's/^ X//' << \SHAR_EOF > 'container.c'
X#include "../mfile/mfile.h"
X#include <stdio.h>
X
Xtypedef MFILE *Container;
X
XContainer cnew_con()
X{
X return mfopen();
X}
XContainer cnew_constring(str)
Xchar *str;
X{
X Container temp;
X void cins_cur_chars();
X void crewind();
X temp = cnew_con();
X cins_cur_chars(temp,str,strlen(str));
X crewind(temp);
X return temp;
X}
Xchar *cflatten(cont)
XContainer cont;
X{
X long n;
X char *temp;
X n = clength(cont);
X temp = (char *) malloc(sizeof(char) * n+1);
X crewind(cont);
X mfread(cont,temp,n);
X temp[n] = '\0';
X return temp;
X}
Xvoid cdestroy(cont)
XContainer cont;
X{
X mfclose(cont);
X}
Xvoid ctrunc(cont)
XContainer cont;
X{
X mftrunc(cont);
X}
Xvoid crewind(cont)
XContainer cont;
X{
X mfseek(cont,0,0);
X}
XContainer ccpy_con(old)
XContainer old;
X{
X long size;
X long curspot;
X Container new;
X char *buff,*cget_cur_chars();
X void cins_cur_chars();
X new = cnew_con();
X crewind(old);
X buff = cget_cur_chars(old,clength(old));
X cins_cur_chars(new,buff,clength(old));
X crewind(new);
X return new;
X}
Xlong clength(cont)
XContainer cont;
X{
X return mflength(cont);
X}
X
Xchar *cget_nth_line(cont,n)
XContainer cont;
Xint n;
X{
X char c;
X char *str;
X int m = 0;
X int i;
X mfseek(cont,0,0);
X
X while (n >= 0) {
X m = 0;
X c = mfgetc(cont);
X while ((c != EOF) && (c != '\n')) {
X c = mfgetc(cont);
X m++;
X }
X if (c == EOF) {
X break;
X }
X n--;
X }
X mfseek(cont,-(m+1),1);
X str = (char *) malloc(sizeof(char) * (m + 1));
X for (i = 0; i < m; i++) {
X str[i] = mfgetc(cont);
X }
X str[m] = '\0';
X return str;
X}
Xint cfind_nth_line(cont,n)
XContainer cont;
Xint n;
X{
X char c;
X char *str;
X int m = 0;
X int i;
X
X while (n >= 0) {
X m = 0;
X c = mfgetc(cont);
X while ((c != EOF) && (c != '\n')) {
X c = mfgetc(cont);
X m++;
X }
X if (c == EOF) {
X break;
X }
X n--;
X }
X mfseek(cont,-(m+1),1);
X return m;
X}
X
Xint cfind_nth_item(cont,n)
XContainer cont;
Xint n;
X{
X char c;
X char *str;
X int m = 0;
X int i;
X
X while (n >= 0) {
X m = 0;
X c = mfgetc(cont);
X while ((c != EOF) && (c != ',')) {
X c = mfgetc(cont);
X m++;
X }
X if (c == EOF) {
X mfseek(cont,-m,1);
X return m;
X break;
X }
X n--;
X }
X if (n == 0) {
X return 0;
X }
X mfseek(cont,-(m+1),1);
X return m;
X}
X
X#define WHITE_SPACE(x) ((c == ' ') || (c == '\n') || (c == '\t'))
X
Xint cfind_nth_word(cont,n)
XContainer cont;
Xint n;
X{
X char c;
X char *str;
X int m = 0;
X int i;
X
X while (n >= 0) {
X m = 0;
X c = mfgetc(cont);
X while (WHITE_SPACE(c)) {
X c = mfgetc(cont);
X }
X while (!WHITE_SPACE(c)) {
X if (c == EOF) {
X if (n != 0) {
X return NULL;
X }
X mfseek(cont,-(m),1);
X return m;
X break;
X }
X
X c = mfgetc(cont);
X m++;
X }
X n--;
X }
X mfseek(cont,-(m+1),1);
X return m;
X}
X
Xchar *cget_nth_word(cont,n)
XContainer cont;
Xint n;
X{
X int length;
X char *temp;
X crewind(cont);
X length = cfind_nth_word(cont,n);
X temp = (char *) malloc(sizeof(char) * (length + 1));
X mfread(cont,temp,length);
X temp[length] = '\0';
X return temp;
X}
Xchar *cget_nth_item(cont,n)
Xint n;
XContainer cont;
X{
X int length;
X char *temp;
X length = cfind_nth_item(cont,n);
X temp = (char *) malloc(sizeof(char) * (length + 1));
X mfread(cont,temp,length);
X temp[length] = '\0';
X return temp;
X}
Xchar *cget_cur_chars(cont,length)
XContainer cont;
Xint length;
X{
X char *temp;
X temp = (char *) malloc(sizeof(char) * (length + 1));
X mfread(cont,temp,length);
X return temp;
X}
Xint cget_numwords(cont)
XContainer cont;
X{
X int len;
X char c;
X int n;
X char *str;
X int m = 0;
X int i;
X c = 'a';
X mfseek(cont,0,0);
X n = 0;
X while (c != EOF) {
X m = 0;
X c = mfgetc(cont);
X while (WHITE_SPACE(c)) {
X c = mfgetc(cont);
X }
X while (!WHITE_SPACE(c)) {
X if (c == EOF)
X break;
X c = mfgetc(cont);
X m++;
X }
X n++;
X }
X if (m == 0) {
X return n - 1;
X } else {
X return n;
X }
X}
Xint cget_numlines(cont)
XContainer cont;
X{
X char c,l;
X int n;
X char *str;
X mfseek(cont,0,0);
X n = 0;
X c = '!';
X l = '\n';
X while (c != EOF) {
X l = c;
X c = mfgetc(cont);
X if (c == '\n') {
X n++;
X }
X }
X if (l == '\n') {
X return n;
X }
X return n+1;
X}
Xint cget_numitems(cont)
XContainer cont;
X{
X char c,l;
X int n;
X char *str;
X mfseek(cont,0,0);
X n = 0;
X c = '!';
X l = ',';
X while (c != EOF) {
X l = c;
X c = mfgetc(cont);
X if (c == ',') {
X n++;
X }
X }
X if (l == ',') {
X return n;
X }
X return n+1;
X}
X
Xvoid cdel_cur_chars(cont,n)
XContainer cont;
Xint n;
X{
X mfdelete(cont,n);
X}
X
Xvoid cins_cur_chars(cont,ptr,n)
XContainer cont;
Xchar *ptr;
Xint n;
X{
X mfinsert(cont,ptr,n);
X}
SHAR_EOF
if test 4713 -ne "`wc -c < 'container.c'`"
then
echo shar: error transmitting "'container.c'" '(should have been 4713 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'container.h'" '(728 characters)'
if test -f 'container.h'
then
echo shar: will not over-write existing file "'container.h'"
else
sed 's/^ X//' << \SHAR_EOF > 'container.h'
X
X
X
Xtypedef void *Container;
X
XContainer cnew_con();
XContainer ccpy_con();
XContainer cnew_constring();
Xchar *cflatten();
X
Xvoid cdestroy();
Xchar *cget_nth_line();
Xchar *cget_nth_word();
Xchar *cget_nth_char();
Xchar *cget_nth_item();
X
Xvoid crewind();
Xint cfind_nth_line();
Xint cfind_nth_word();
Xint cfind_nth_char();
Xint cfind_nth_item();
X
Xchar *cget_cur_chars();
Xvoid cdel_cur_chars();
Xvoid cins_cur_chars();
X
Xvoid cdel_nth_line();
Xvoid cdel_nth_word();
Xvoid cdel_nth_char();
Xvoid cdel_nth_item();
X
Xvoid cins_nth_line();
Xvoid cins_nth_word();
Xvoid cins_nth_char();
Xvoid cins_nth_item();
X
Xcseek();
Xcread();
Xcwrite();
Xvoid ctrunc();
SHAR_EOF
if test 728 -ne "`wc -c < 'container.h'`"
then
echo shar: error transmitting "'container.h'" '(should have been 728 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'ctest.c'" '(573 characters)'
if test -f 'ctest.c'
then
echo shar: will not over-write existing file "'ctest.c'"
else
sed 's/^ X//' << \SHAR_EOF > 'ctest.c'
X#include "container.h"
X#include <stdio.h>
X
Xmain ()
X{
X char buff[1000];
X int i;
X Container cont;
X cont = cnew_con();
X for(i = 0; i < 1000; i++ ) {
X buff[i] = getchar();
X }
X
X mfwrite(cont,buff,1000);
X for (i = 0; i < 10; i++) {
X crewind(cont);
X fprintf(stdout,"%s\n",cget_nth_line(cont,i));
X crewind(cont);
X fprintf(stdout,"%s\n",cget_cur_chars(cont,cfind_nth_line(cont,i)));
X crewind(cont);
X cfind_nth_line(cont,4);
X cins_cur_chars(cont,"holy lamb\n",10);
X crewind(cont);
X fprintf(stdout,"%s\n",cget_cur_chars(cont,cfind_nth_word(cont,0)));
X }
X}
SHAR_EOF
if test 573 -ne "`wc -c < 'ctest.c'`"
then
echo shar: error transmitting "'ctest.c'" '(should have been 573 characters)'
fi
fi # end of overwriting check
echo shar: done with directory "'container'"
cd ..
if test ! -d 'hash'
then
echo shar: creating directory "'hash'"
mkdir 'hash'
fi
echo shar: entering directory "'hash'"
cd 'hash'
echo shar: extracting "'Makefile'" '(170 characters)'
if test -f 'Makefile'
then
echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^ X//' << \SHAR_EOF > 'Makefile'
XCFLAGS = -g
X
X.SUFFIXES: .f .c .o .ln
X
X.c.ln:
X csh -c "lint -xu -i $<"
X
X
X
Xhash.a: hash.o shash.o
X ar rcv hash.a hash.o shash.o
X ranlib hash.a
X
Xwc:
X wc *.c *.h Makefile
X
SHAR_EOF
if test 170 -ne "`wc -c < 'Makefile'`"
then
echo shar: error transmitting "'Makefile'" '(should have been 170 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'hash.c'" '(2978 characters)'
if test -f 'hash.c'
then
echo shar: will not over-write existing file "'hash.c'"
else
sed 's/^ X//' << \SHAR_EOF > 'hash.c'
X/* hash.c -- hype requires many a fine young hash table so that it can have */
X/* roughly constant time lookups for most of it's stuff. This file is an */
X/* attempt at a general hash table maintenance module. */
X
X
X#include "../../src/util.h"
X
Xtypedef struct hnode {
X struct hnode *next;
X void *key;
X char *ptr;
X} Hnode,*HnodePtr;
X
Xtypedef struct hash {
X int size;
X HnodePtr *entry;
X} HashT,*HashTPtr;
X
XHashTPtr make_hash()
X{
X HashTPtr temp;
X temp = (HashTPtr) malloc(sizeof(HashT) * 1);
X temp->entry = NULL;
X temp->size = 0;
X return temp;
X}
Xvoid unmake_hnode_list(ptr)
XHnodePtr ptr;
X{
X if (ptr != NULL) {
X unmake_hnode_list(ptr->next);
X free(ptr);
X }
X}
Xvoid unmake_hash(hash)
XHashTPtr hash;
X{
X int i;
X for (i = 0; i < hash->size; i++) {
X unmake_hnode_list(hash->entry[i]);
X }
X free(hash->entry);
X free(hash);
X}
X
XHnodePtr make_hnode()
X{
X HnodePtr temp;
X temp = (HnodePtr) malloc(sizeof(Hnode) * 1);
X temp->key = 0;
X temp->next = NULL;
X temp->ptr = NULL;
X return temp;
X}
Xvoid init_hash( size, hash)
Xint size;
XHashTPtr hash;
X{
X int i;
X hash->size = size;
X hash->entry = (HnodePtr *) malloc(sizeof(HnodePtr) * size);
X for ( i = 0; i < size; i++) {
X hash->entry[i] = NULL;
X }
X}
X
Xint hashval( x, size)
Xint x;
Xint size;
X{
X int f;
X f = x & 0x000f;
X f *= ((x & 0x0f00) >> 16);
X f += ((x & 0x00f0) >> 8);
X f += ((x & 0xf000) >> 24) * 3;
X return abs(f) % size;
X}
X
Xdelete_from_hash(key, hash)
Xvoid *key;
XHashTPtr hash;
X{
X int fval;
X HnodePtr temp,cur;
X fval = hashval(key,hash->size);
X cur = hash->entry[fval];
X if (cur == NULL) {
X mywarning("hash.c: tried to delete non-existent element from hash table\n");
X }
X if (cur->key == key) {
X hash->entry[fval] = cur->next;
X free(cur);
X return;
X }
X while ((cur->next != NULL) && ((cur->next->key != key))) {
X cur = cur->next;
X }
X if (cur->next == NULL) {
X return;
X/* mywarning("hash.c: element to delete not found\n"); */
X } else {
X temp = cur->next;
X cur->next = cur->next->next;
X free(temp);
X }
X}
X
Xchar *hlookup(key,hash)
XHashTPtr hash;
Xvoid *key;
X{
X int fval;
X HnodePtr cur;
X fval = hashval(key,hash->size);
X cur = hash->entry[fval];
X if (cur == NULL) {
X return NULL;
X }
X if (cur->key == key) {
X return cur->ptr;
X }
X while (cur != NULL) {
X if (cur->key == key) {
X return cur->ptr;
X } else {
X cur = cur->next;
X }
X }
X return NULL;
X}
Xadd_to_hash(key, hash, ptr)
Xvoid *key;
Xchar *ptr;
XHashTPtr hash;
X{
X HnodePtr temp,cur;
X int fval;
X if (hlookup(key,hash) != NULL) {
X mywarning("duplicate hash key attempted\n");
X return NULL;
X }
X
X temp = make_hnode();
X temp->key = key;
X temp->next = NULL;
X temp->ptr = ptr;
X fval = hashval(key,hash->size);
X cur = hash->entry[fval];
X
X if (cur == NULL) {
X hash->entry[fval] = temp;
X } else {
X temp->next = hash->entry[fval];
X hash->entry[fval] = temp;
X }
X}
SHAR_EOF
if test 2978 -ne "`wc -c < 'hash.c'`"
then
echo shar: error transmitting "'hash.c'" '(should have been 2978 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'hash.h'" '(288 characters)'
if test -f 'hash.h'
then
echo shar: will not over-write existing file "'hash.h'"
else
sed 's/^ X//' << \SHAR_EOF > 'hash.h'
X/* hash.h -- this file is the header file for a hopefully general hash */
X/* table module. */
X
Xtypedef void *HashTPtr;
X
XHashTPtr make_hash();
X
Xvoid unmake_hash();
X
Xvoid init_hash();
X
Xvoid add_to_hash();
X
Xvoid delete_from_hash();
X
Xvoid *hlookup();
SHAR_EOF
if test 288 -ne "`wc -c < 'hash.h'`"
then
echo shar: error transmitting "'hash.h'" '(should have been 288 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'shash.c'" '(3885 characters)'
if test -f 'shash.c'
then
echo shar: will not over-write existing file "'shash.c'"
else
sed 's/^ X//' << \SHAR_EOF > 'shash.c'
X/* hash.c -- hype requires many a fine young hash table so that it can have */
X/* roughly constant time lookups for most of it's stuff. This file is an */
X/* attempt at a general hash table maintenance module. */
X
X
X#include "../../src/util.h"
X
Xtypedef struct shnode {
X struct shnode *next;
X char *key;
X void *id;
X} SHnode,*SHnodePtr;
X
Xtypedef struct shash {
X int size;
X SHnodePtr *entry;
X} SHashT,*SHashTPtr;
X
Xvoid *slookup();
X
XSHashTPtr smake_hash()
X{
X SHashTPtr temp;
X temp = (SHashTPtr) malloc(sizeof(SHashT) * 1);
X temp->entry = NULL;
X temp->size = 0;
X return temp;
X}
XSHnodePtr smake_hnode()
X{
X SHnodePtr temp;
X temp = (SHnodePtr) malloc(sizeof(SHnode) * 1);
X temp->key = "";
X temp->next = NULL;
X temp->id = 0;
X return temp;
X}
X
Xchar *shash_get_nth(hash,n)
XSHashTPtr hash;
Xint n;
X{
X SHnodePtr s;
X int i = 0;
X int j = 0;
X s = hash->entry[j];
X while(s == NULL) {
X j++;
X if (j >= hash->size) {
X return NULL;
X }
X s = hash->entry[j];
X }
X while (1) {
X if (i == n)
X return s->key;
X i++;
X s = s->next;
X while(s == NULL) {
X j++;
X if (j >= hash->size) {
X return NULL;
X }
X s = hash->entry[j];
X }
X }
X}
Xvoid Sinit_hash( size, hash)
Xint size;
XSHashTPtr hash;
X{
X int i;
X hash->size = size;
X hash->entry = (SHnodePtr *) malloc(sizeof(SHnodePtr) * size);
X for (i = 0; i < size; i++) {
X hash->entry[i] = NULL;
X }
X}
X
Xvoid sunmake_hnode_list(ptr)
XSHnodePtr ptr;
X{
X if (ptr != NULL) {
X sunmake_hnode_list(ptr->next);
X free(ptr->key);
X free(ptr);
X }
X}
Xvoid sunmake_hash(hash)
XSHashTPtr hash;
X{
X int i;
X for (i = 0; i < hash->size; i++) {
X sunmake_hnode_list(hash->entry[i]);
X }
X free(hash->entry);
X free(hash);
X}
Xint shashval( x, size)
Xchar *x;
Xint size;
X{
X int l,n,i;
X l = strlen(x);
X n = l;
X if( l - 1 > 0) {
X n = n * x[l-1];
X }
X if (l - 4 > 0) {
X n = n * x[l-1];
X }
X for (i = 0;i < l;i++) {
X n += x[i];
X }
X n = n % size;
X return n;
X}
X
Xint sadd_to_hash(key, hash, id)
Xchar *key;
XSHashTPtr hash;
Xvoid *id;
X{
X SHnodePtr temp,cur;
X int fval;
X/* if (slookup(key,hash) != NULL) {
X mywarning("duplicate hash key attempted\n");
X return NULL;
X }
X*/
X if (strlen(key) == 0) {
X mywarning("Major Error: Zero hash key attempted\n");
X return 0;
X }
X temp = smake_hnode();
X temp->key = mystrcpy(key);
X temp->id = id;
X temp->next = NULL;
X
X fval = shashval(temp->key,hash->size);
X cur = hash->entry[fval];
X if (cur == NULL) {
X hash->entry[fval] = temp;
X } else {
X temp->next = hash->entry[fval];
X hash->entry[fval] = temp;
X }
X}
Xint sdelete_from_hash(key, hash, id)
Xchar *key;
XSHashTPtr hash;
Xvoid *id;
X{
X int fval;
X SHnodePtr temp,cur;
X if (strlen(key) == 0) {
X return 0;
X }
X fval = shashval(key,hash->size);
X
X cur = hash->entry[fval];
X if (cur == NULL) {
X mywarning("hash.c: tried to delete non-existent element from hash table\n");
X }
X if (!strcmp(cur->key,key) && (id == cur->id)) {
X hash->entry[fval] = cur->next;
X free(cur->key);
X free(cur);
X return;
X }
X while ((cur->next != NULL) &&
X (strcmp(cur->next->key,key) || (id != cur->next->id ))) {
X cur = cur->next;
X }
X if (cur->next == NULL) {
X mywarning("hash.c: tried to delete non-existent element from hash table\n");
X } else {
X temp = cur->next;
X cur->next = cur->next->next;
X free(temp->key);
X free(temp);
X }
X}
X
Xvoid *slookup(key,hash)
XSHashTPtr hash;
Xchar *key;
X{
X int fval;
X SHnodePtr cur;
X if (strlen(key) == 0) {
X return NULL;
X }
X fval = shashval(key,hash->size);
X cur = hash->entry[fval];
X if (cur == NULL) {
X return NULL;
X }
X if (strcmp(cur->key,key) == 0) {
X return cur->id;
X }
X while (cur != NULL) {
X if (strcmp(cur->key,key) == 0) {
X return cur->id;
X } else {
X cur = cur->next;
X }
X }
X return NULL;
X}
SHAR_EOF
if test 3885 -ne "`wc -c < 'shash.c'`"
then
echo shar: error transmitting "'shash.c'" '(should have been 3885 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'shash.h'" '(244 characters)'
if test -f 'shash.h'
then
echo shar: will not over-write existing file "'shash.h'"
else
sed 's/^ X//' << \SHAR_EOF > 'shash.h'
X/* hash.h -- this file is the header file for a hopefully general hash */
X/* table module. */
X
Xtypedef void *SHashTPtr;
X
XSHashTPtr smake_hash();
X
Xvoid sunmake_hash();
Xvoid sinit_hash();
X
Xint sadd_to_hash();
X
Xint sdelete_from_hash();
X
SHAR_EOF
if test 244 -ne "`wc -c < 'shash.h'`"
then
echo shar: error transmitting "'shash.h'" '(should have been 244 characters)'
fi
fi # end of overwriting check
echo shar: done with directory "'hash'"
cd ..
if test ! -d 'mfile'
then
echo shar: creating directory "'mfile'"
mkdir 'mfile'
fi
echo shar: entering directory "'mfile'"
cd 'mfile'
echo shar: extracting "'Makefile'" '(165 characters)'
if test -f 'Makefile'
then
echo shar: will not over-write existing file "'Makefile'"
else
sed 's/^ X//' << \SHAR_EOF > 'Makefile'
XCFLAGS = -g
X
Xmfile.a: mfile.o
X ar rcv mfile.a mfile.o
X ranlib mfile.a
X
Xmftest: mftest.o mfile.o mfile.h
X cc -o mftest mftest.o mfile.o
X
Xmftest.o: mftest.c mfile.h
X
X
SHAR_EOF
if test 165 -ne "`wc -c < 'Makefile'`"
then
echo shar: error transmitting "'Makefile'" '(should have been 165 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'mfile.c'" '(5680 characters)'
if test -f 'mfile.c'
then
echo shar: will not over-write existing file "'mfile.c'"
else
sed 's/^ X//' << \SHAR_EOF > 'mfile.c'
X#include <stdio.h>
X#include "../../src/util.h"
X#define MAGIC 327
X#define BUFFSIZE 32
X#define CHECK_MAGIC(x) if (x->magic != MAGIC) { \
X char *y; \
X y = (char *) 57; \
X fprintf(stderr,"Bad magic number to mfile.\n"); \
X fprintf(stderr,"%s\n",y); \
X}
X
Xtypedef struct blk {
X char contents[BUFFSIZE];
X struct blk *next;
X} Block,*BlockPtr;
X
Xtypedef struct mfile {
X int magic;
X long length;
X long curr;
X BlockPtr firstbloc;
X BlockPtr curbloc;
X BlockPtr lastbloc;
X} MFILE;
X
X
XBlockPtr new_bloc()
X{
X BlockPtr temp;
X temp = (BlockPtr) malloc(sizeof(Block) * 1);
X if (temp == NULL) {
X fprintf(stderr,"Out of memory for memory file.\n");
X }
X temp->next = NULL;
X return temp;
X}
X
XMFILE *mfopen()
X{
X MFILE *temp;
X temp = (MFILE *) malloc(sizeof(MFILE) * 1);
X if (temp == NULL) {
X fprintf(stderr,"Out of memory for memory file.\n");
X }
X temp->length = 0;
X temp->magic = MAGIC;
X temp->curr = 0;
X temp->firstbloc = NULL;
X temp->curbloc= NULL;
X temp->lastbloc= NULL;
X return temp;
X}
Xlong mflength(file)
XMFILE *file;
X{
X CHECK_MAGIC(file);
X return file->length;
X}
Xstatic void dealloc_blocs(bloc)
XBlockPtr bloc;
X{
X if (bloc == NULL) {
X return;
X } else {
X dealloc_blocs(bloc->next);
X free(bloc);
X }
X}
Xvoid mfclose(file)
XMFILE *file;
X{
X CHECK_MAGIC(file);
X dealloc_blocs(file->firstbloc);
X free(file);
X}
X
Xint mfgetc(file)
XMFILE *file;
X{
X int c;
X CHECK_MAGIC(file);
X if (file->curr == file->length) {
X return EOF;
X }
X c = file->curbloc->contents[file->curr % BUFFSIZE];
X file->curr++;
X if (file->curr % BUFFSIZE == 0) {
X file->curbloc = file->curbloc->next;
X }
X return c;
X}
Xint mfungetc(file)
XMFILE *file;
X{
X mfseek(file,-1,1);
X}
Xint mfputc(file,c)
XMFILE *file;
Xchar c;
X{
X CHECK_MAGIC(file);
X if (file->lastbloc == NULL) {
X file->firstbloc = new_bloc();
X file->lastbloc = file->firstbloc;
X file->curbloc = file->firstbloc;
X }
X if (file->curbloc == NULL) {
X file->lastbloc->next = new_bloc();
X file->lastbloc = file->lastbloc->next;
X file->curbloc = file->lastbloc;
X }
X file->curbloc->contents[file->curr % BUFFSIZE] = (char) c;
X file->curr++;
X if ((file->curr % BUFFSIZE) == 0) {
X file->curbloc = file->curbloc->next;
X }
X if (file->curr > file->length) {
X file->length = file->curr;
X }
X return c;
X}
Xint mfinsert(file,ptr,bytes)
XMFILE *file;
Xchar *ptr;
Xint bytes;
X{
X char *temp;
X long buffsize;
X long curspot;
X CHECK_MAGIC(file);
X curspot = mfseek(file,0,1);
X buffsize = mfseek(file,0,2) - curspot;
X temp = (char *) malloc(sizeof(char) * buffsize);
X mfseek(file,curspot,0);
X mfread(file,temp,buffsize);
X mfseek(file,curspot,0);
X mfwrite(file,ptr,bytes);
X mfwrite(file,temp,buffsize);
X free(temp);
X return bytes;
X}
Xvoid mftrunc(file)
XMFILE *file;
X{
X CHECK_MAGIC(file);
X if (file->curbloc == NULL) {
X return;
X }
X dealloc_blocs(file->curbloc->next);
X file->curbloc->next = NULL;
X file->lastbloc = file->curbloc;
X file->length = file->curr;
X}
Xint mfdelete(file,bytes)
XMFILE *file;
Xint bytes;
X{
X char *temp;
X long buffsize;
X long curspot;
X CHECK_MAGIC(file);
X curspot = mfseek(file,0,1);
X buffsize = mfseek(file,0,2) - curspot - bytes;
X temp = (char *) malloc(sizeof(char) * buffsize);
X mfseek(file,curspot+bytes,0);
X mfread(file,temp,buffsize);
X mfseek(file,curspot,0);
X mfwrite(file,temp,buffsize);
X mfseek(file,curspot+buffsize,0);
X mftrunc(file);
X return bytes;
X}
Xint mfwrite(file,ptr,bytes)
XMFILE *file;
Xchar *ptr;
Xint bytes;
X{
X int written;
X CHECK_MAGIC(file);
X written = 0;
X if (bytes <= 0) {
X return 0;
X }
X if (file->lastbloc == NULL) {
X file->firstbloc = new_bloc();
X file->lastbloc = file->firstbloc;
X file->curbloc = file->firstbloc;
X file->curbloc->contents[file->curr++] = ptr[written++];
X }
X while (written != bytes) {
X if (file->curbloc == NULL) {
X file->lastbloc->next = new_bloc();
X file->lastbloc = file->lastbloc->next;
X file->curbloc = file->lastbloc;
X }
X file->curbloc->contents[file->curr % BUFFSIZE] = ptr[written++];
X file->curr++;
X if (file->curr % BUFFSIZE == 0) {
X file->curbloc = file->curbloc->next;
X }
X }
X if (file->length < file->curr) {
X file->length = file->curr;
X }
X return written;
X}
X
Xint mfread(file,ptr,bytes)
XMFILE *file;
Xchar *ptr;
Xint bytes;
X{
X int read = 0;
X CHECK_MAGIC(file);
X if (bytes <= 0) {
X return read;
X }
X while (read != bytes) {
X if ((file->curbloc == NULL) || (file->curr == file->length)){
X return read;
X }
X ptr[read++] = file->curbloc->contents[file->curr % BUFFSIZE];
X file->curr++;
X if ((file->curr % BUFFSIZE) == 0) {
X file->curbloc = file->curbloc->next;
X }
X }
X return read;
X}
X
X
Xlong mfseek(file,offset,origin)
XMFILE *file;
Xlong offset;
Xint origin;
X{
X long newval;
X int i;
X CHECK_MAGIC(file);
X switch (origin) {
X case 0:
X file->curr = offset;
X break;
X case 1:
X file->curr = file->curr + offset;
X break;
X case 2:
X file->curr = file->length + offset;
X break;
X }
X if (file->curr < 0) {
X file->curr = 0;
X }
X file->curbloc = file->firstbloc;
X if (file->lastbloc == NULL) {
X file->firstbloc = new_bloc();
X file->lastbloc = file->firstbloc;
X file->curbloc = file->firstbloc;
X }
X for (i = 0; i < (file->curr / BUFFSIZE); i++) {
X if (file->curbloc == NULL) {
X file->lastbloc->next = new_bloc();
X file->curbloc = file->lastbloc->next;
X file->lastbloc = file->lastbloc->next;
X }
X file->curbloc = file->curbloc->next;
X }
X if (file->curr > file->length) {
X file->length = file->curr;
X }
X return file->curr;
X}
SHAR_EOF
if test 5680 -ne "`wc -c < 'mfile.c'`"
then
echo shar: error transmitting "'mfile.c'" '(should have been 5680 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'mfile.h'" '(72 characters)'
if test -f 'mfile.h'
then
echo shar: will not over-write existing file "'mfile.h'"
else
sed 's/^ X//' << \SHAR_EOF > 'mfile.h'
X
X
X
Xtypedef void *MFILE;
X
X
XMFILE *mfopen();
Xint mfwrite();
Xint mfread();
SHAR_EOF
if test 72 -ne "`wc -c < 'mfile.h'`"
then
echo shar: error transmitting "'mfile.h'" '(should have been 72 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'mftest.c'" '(804 characters)'
if test -f 'mftest.c'
then
echo shar: will not over-write existing file "'mftest.c'"
else
sed 's/^ X//' << \SHAR_EOF > 'mftest.c'
X#include <stdio.h>
X#include "mfile.h"
X
Xmain()
X{
X int i,j;
X char c;
X MFILE *mf;
X FILE *fd;
X char bigbuf[6000];
X fd = fopen("mfile.c","r");
X for (i = 0; i < 1; i++) {
X lseek(fd,0,0);
X mf = mfopen();
X j = 0;
X while ((c = getc(fd)) != EOF) {
X bigbuf[j++] = c;
X mfputc(mf,c);
X }
X mfseek(mf,0,0);
X mfbogus(mf);
X mfseek(mf,5000,0);
X mfbogus(mf);
X mfseek(mf,-5000,2);
X mfwrite(mf,bigbuf,5000);
X mfbogus(mf);
X mfseek(mf,0,0);
X mfbogus(mf);
X mfread(mf,bigbuf,5000);
X mfbogus(mf);
X mfseek(mf,0,0);
X mfdelete(mf,4000);
X mfseek(mf,0,0);
X mfbogus(mf);
X bigbuf[1] = '\0';
X/* j = mfread(mf,bigbuf,10);*/
X bigbuf[0] = mfgetc(mf);
X while (bigbuf[0] != EOF ) {
X fprintf(stdout,"%s",bigbuf);
X bigbuf[0] = mfgetc(mf);
X }
X mfclose(mf);
X }
X}
SHAR_EOF
if test 804 -ne "`wc -c < 'mftest.c'`"
then
echo shar: error transmitting "'mftest.c'" '(should have been 804 characters)'
fi
fi # end of overwriting check
echo shar: done with directory "'mfile'"
cd ..
echo shar: done with directory "'archives'"
cd ..
# End of shell archive
exit 0
More information about the Comp.sources.sun
mailing list