„Amiga Machine Language (Chapter 7)” változatai közötti eltérés
Innen: amigaspirit.hu - pegasos.hu Wiki
Ugrás a navigációhozUgrás a kereséshez
(intial import as separate page) |
(Nincs különbség)
|
A lap jelenlegi, 2009. május 25., 13:36-kori változata
Chapter 7.
----------
7.Working With Intuition.
-------------------------
Now that you've learned so much about machine language,lets look
at the special features of the Amiga.Lets look at the operating
system Intuition that is in charge of windows,screens,the mouse
and lots of other things.Beforetaking a look at these beautiful
features,theres some bad news.
First,though,lets here the good news.Since Intuition has so many
functions,it allows you to be very creative in programming your
ideas.The disadvantage is that the flexibility means that you have
to use a lot of parameters,and that makes for a lot of tedious
work.
However,this is no grounds for panic.Once you've built up the
necessary routines,the programming and experimentation becomes
increasingly interesting.Before you try out new program variations
you should save your source code to disk,because Intuition gets
fairly upset about bad parameters and often responds by crashing
the system.
Now lets get to work.To start working with Intuition,you need the
Intuition library.You can load it with the OpenLibrary function
from the EXEC library.Heres the subroutine that takes care of
initialization.
openlib =-408
execbase = 4
run:
bsr openint ;load intuition library
...
openint: ;*initialize and open system
move.l execbase,a6 ;exec base address
lea intname,a1 ;name of intuition library
jsr openlib(a6) ;open intuition
move.l d0,intbase ;save intuition base address
rts
intname: dc.b "intuition.library",0
align
intbase: dc.l 0 ;base address of intuition
When your program is finished,you need to close the screens,the
window and the library.To do this,use the CloseLibrary function
from the EXEC library.It has an offset of -414.
Heres the subroutine:
closelibrary =-414
...
closeint: ;*close intuition
move.l execbase,a6 ;exec base address in A6
move.l intbase,a1 ;intuition base address in A1
jsr closelibrary(a6) ;close intuition
rts ;done
Now that you've got that taken care of,you can finally start
working with Intuition.
7.1.Open Screen.
----------------
Intuition is a graphics operating system.For this reason,you'll be
working with the screen.Its even more interesting to work with
several screens at the same time.However,you only have one monitor
on the Amiga.
You can open as many screens as you like (at least,as long as
theres some memory available).You can open a window,display menus
and do I/O's there.The individual screens are fully independant.
You can work with all of them simultaneously on the monitor.
You can move individual screens forward and back to your hearts
content.You can also press the left <Amiga> key and then an "m"to
return to the workbench screen after getting into the different
screens.
You want to begin programming Intuition by setting up a screen.You
have already loaded the Intuition library,so you can use the Open-
Screen function.
Wait a minute!What should the screen look like,where should it go,
and what form should it have?You need to look at the options for
the form of the screen you have available.
The input to the screen is in the form of a table that has 13
entries.Lets take a look at the parameters that you need for our
screen.
You'll start the table with the label "screen_defs"which must be
at an even address:
align
screen_defs: ;The screen table begins here
The first bit of information that the screen needs is the position
and size.Lets have it start in the upper left corner and fill the
entire screen.You'll use the positions X=0 and Y=0,the width 320
and the height 200.This means that your screen is the maximum
size.
x_pos: dc.w 0 ;X-Position
y_pos: dc.w 0 ;Y-Position
width: dc.w 320 ;width
height: dc.w 200 ;height
Next you need to decide which colors should be displayed.That
depends on the number of bitplanes,on the depth.Lets choose two.
That means you have 2^2 (4) colours available.Lets choose two,
since four colours is usually plenty.
depth: dc.w 2 ;number of bitplanes
Next you need to choose the colour of the title line and the
function symbols.Give the number of the colour register:
detail_pen: dc.b 0 ;colour of text,etc...
Now for the colour of the text background:
block_pen dc.b 1 ;background colour
Make sure that these two inputs fit in a byte.The colours are
normally the following (if the standard values have'nt been
changed).You'll notice that the number of colours depends on the
number of bit maps.
Pen Colour
---------------------------------------------------------
0 Background (blue)
1 White
for two bit planes
2 Black
3 Red
for three bit planes
4 Blue
5 Violet
6 Turquoise
7 White
for four bit planes
8 Black
9 Red
10 Green
11 Brown
12 Blue
13 Blue
14 Green
15 Green
The next word contains the bits that describe the appearance of
the screen.The bits are:
Bit Value Name Meaning
---------------------------------------------------------------
1 2 GENLOCK_VIDEO
2 4 INTERLACE Puts the screen in Interlace
mode.The resolution and thus the
maximum screen size are doubled.
6 $40 PFBA
7 $80 EXTRA_HALFBRITE
8 $100 GENLOCL_AUDIO
10 $400 DBLPF Divides the screen into a border
and character area.
11 $800 HOLDNMODIFY Turns on Hold-and-Modify mode.
13 $2000 VP_HIDE
14 $4000 SPRITES Allows sprites to be used.
15 $8000 MODE_640 Turns on the highest resolution
graphics for the screen(640x400).
Choose the value two (normal) for your example screen:
view_modes: dc.w 2 ;representation mode
The following word is constructed in such away that each bit as
its own meaning.Use this to set what sort of screen it is.Choose
15 so the screen is a "Custom screen",which allows you all of the
options.
screen_type: dc.w 15 ;screen type:custom screen
Next theres a pointer to the character set to be used for all
output to the screen.If you don't want to install your own
character set,just put a zero here,and the standard character set
is used.
font: dc.l 0 ;character set:standard
Next theres a pointer to the text thats used as the name of the
screen.The text ends with a zero,just like window names must.
title: dc.l name ;pointer to title text
Next comes a long word that defines the gadgets.These gadgets
represent the functions,like "Bring forward",that can be accessed
via a mouse click in the screen.The long word in this table is a
pointer to a list which specifies the gadgets.These aren't the
system gadgets.However,you're only using system gadgets here,so
put a zero here.
gadgets: dc.l 0 ;no gadgets
Finally theres a long word that you only need if you want to use
the special bitmap just for your screen.Since this isn't the case,
just put a zero here.
bitmap: dc.l 0 ;no bitmap
Thats it for the list entries that you need to define the screen.
You still need the text for the name of the screen.Enter the
following:
sname: dc.b 'Our Screen',0 ;screen title
Heres a quick overview of the list:
align
screen_defs: ;*The screen ta
x_pos: dc.w 0 ;X-position
y_pos: dc.w 0 ;Y-position
width: dc.w 320 ;width
height: dc.w 200 ;height
depth: dc.w 2 ;number of bitplanes
detail_pen: dc.b 0 ;colour of the text,etc...
block_pen: dc.b 1 ;background colour
view_modes: dc.w 2 ;representation mode
screen_type: dc.w 15 ;screen type:custom screen
font: dc.l 0 ;character set:standard
title: dc.l sname ;pointer to title text
gadgets: dc.l 0 ;no gadgets
bitmap: dc.l 0 ;no bit map
sname: dc.b 'Our Screen',0 ;screen title
Once you've decided on the parameters,its very easy to open the
screen.You need Intuitions OpenScreen function.Its offset is -198
and it only needs one parameter,the address of the parameter
table.The program fragment looks like this:
openscreen =-198
bsr openint ;open intuition
bsr scropen ;open screen
...
scropen: ;*open screen
move.l intbase,a6 ;intuition base address in A6
lea screen_defs,a0 ;pointer to table
jsr openscreen(a6) ;and open
move.l d0,screenhd ;save screen handle
rts ;return to main program
...
screen_defs: ;table info follows
Now the Amigas Workbench screen is covered by your screen.Now you
can do what you want with it until the program is done.Afterwards,
the screen must be closed again,so that you can see the Workbench
screen again.
Use the CloseScreen function (offset -66) to do this.The only
parameter it needs is the pointer to the screen structure you got
back from the OpenScreen function.
closescreen =-66
...
scrclose: ;* close screen
move.l intbase,a6 ;intuition base address in A6
move.l screenhd,a0 ;screen handle in A0
jsr closescreen(a6) ;clos screen
rts ;done
The long word that OpenScreen returned to you is a pointer to a
screen structure that contains all the needed data about the
screen.Besides the data which was given,there is a pointer in the
screen area for individual bit planes,etc...
The form of this structure is fairly complicated and contains some
data that you can't use.Several of the parameters are interesting,
however.Heres a selection of usable parameters:
No Name Function
------------------------------------------------------------------
0 (NextScreen.L) Pointer to next screen.
4 (FirstWindow) Pointer to first window structure
8 (LeftEdge.W)
$A (TopEdge.W) Position of screen
$C (Width.W) Width
$E (Height.W) Height
$10 (MouseY.W)
$12 (MouseX.W) Mouse position in the screen
$14 (Flags.W) Screen flags
$16 (Title.L) Pointer to title text
$1A (DefaultTitle) Pointer to normal title
$28 (Font.L) Pointer to character set
$C0 (Plane0.L) Pointer to bitplane 0
$C4 (Plane1.L) Pointer to bitplane 1
$C8 (Plane2.L) Pointer to bitplane 2
$CC (Plane3.L) Pointer to bitplane 3
An example of an application for the plane pointer is writing and
using your own character routine.Next you want to move the address
of the plane into an address register as follows:
move.l screenhd,a5 ;screen pointer in A5
move.l $c0(a5),a5 ;bitplane 0-pointer in A5
If you want to try this,do the following:
move.l screenhd,a5 ;screen pointer in A5
move.l $c0(a5),a5 ;bitplane 0-pointer in A5
move #$20,d0 ;Counter D0=$20
lop1:
move d0,(a5) ;write counter bits in picture
add.l #80,a5 ;address+80,next line
dbra d0,lop1 ;continue until D0 < 0
This program draws a white,square pattern that corresponds to the
bit pattern for the numbers $20 to 0.This isn't a particularly
useful program,but it shows how easy it is to write from a machine
language program directly to the screen.If you change the offset
in the second line to $C4,the pattern is read.
You can move the entire screen with the normal technique of moving
the mouse pointer into the upper border and moving it up and down
with the left mouse key depressed.You can do the same with a
program.
Lets move the screen without the mouse.Use the joystick for
demonstration purposes.Put the joystick in port two.As you saw in
the chapter on the hardware register,you can read memory location
$DFF00C to find information about the joystick.You can find the
direction the screen should be moved here.
Moving the screen requires another Intuition function.You use the
MoveScreen function which as an offset of -162 and needs three
parameters to do this.The parameters are:
In A0 the pointer to the screen structure that you got back in
D0 when you opened the screen.(You saved it in "screenhd")
In D1 the desired movement in the Y-direction,the vertical
direction.
In D0 the horizontal movement in the X-direction.The varient
doesn't work so you can only move the screen vertically.
Insert the following lines in your program:
MoveScreen =-162
...
scrmove: ;*move screen D0 to the right
;and D1 down
move.l intbase,a6 ;intuition base address in A6
move.l screenhd,a0 ;screen handle in A0
clr.l d0 ;no horizontal movement
jsr movescreen(a6) ;move screen
rts ;done
Now your looking at a complete program that goes through the
following steps:
1. Opens the Intuition library
2. Opens the screen
3. Moves the screen in the direction specified by the joystick in
port two
4. Closes the screen when the fire button is hit
5. Closes the Intuition library
6. Ends
Here is the complete program including the subroutines,so you'll
have it all in one spot:
;** Demo program to open and move a screen **
movescreen =-162
openscreen =-198
closescreen =-66
closelibrary =-414
openlib =-408 ;open library
execbase = 4 ;exec base address
joy2 =$dff00c ;joystick 2 data
fire =$bfe001 ;firebutton 2:bit 7
run:
bsr openint ;open intuition
bsr scropen ;open screen
move joy2,d6 ;save joystick info
loop:
tst.b fire ;test fire button
bpl ende ;pressed down:done
move joy2,d0 ;basic info in D0
sub d6,d0 ;subtract new data
cmp #$0100,d0 ;up?
bne noup ;no
move.l #-1,d1 ;dy=-1 direction y
bsr scrmove ;move up
bra loop
noup:
cmp #$0001,d0 ;down?
bne loop ;no
move.l #1,d1 ;dy=1
bsr scrmove ;move down
bra loop
ende:
bsr scrclose ;close screen
bsr closeint ;close intuition
rts ;done!
openint: ;*initialize and open system
move.l execbase,a6 ;exec base address
lea intname,a1 ;name of intuition library
jsr openlib(a6) ;open intuition
move.l d0,intbase ;save intuition base address
rts
closeint: ;*close intuition
move.l execbase,a6 ;exec base address in A6
move.l intbase,a1 ;intuition base address in A1
jsr closelibrary(a6) ;close intuition
rts ;done
scropen: ;*open screen
move.l intbase,a6 ;intuition base address in A6
lea screen_defs,a0 ;pointer to table
jsr openscreen(a6) ;open
move.l d0,screenhd ;save screen handle
rts ;return to main program
scrclose: ;*close screen
move.l intbase,a6 ;intuition base address in A6
move.l screenhd,a0 ;screen handle in A0
jsr closescreen(a6) ;close screen
rts ;done
scrmove: ;move screen D0 right/D1 down
move.l intbase,a6 ;intuition base address in A6
move.l screenhd,a0 ;screen handle in A0
clr.l d0 ;no horizontal movement
jsr movescreen(a6) ;and move
rts ;done
align
screen_defs: ;*screen table begins here
x_pos: dc.w 0 ;X-position
y_pos: dc.w 0 ;Y-position
width: dc.w 320 ;width
height: dc.w 200 ;height
depth: dc.w 2 ;number of bitplanes
detail_pen: dc.b 1 ;Text colour=white
block_pen: dc.b 3 ;background colour=red
view_modes: dc.w 2 ;representation mode
screen_type dc.w 15 ;screen type:custom screen
font: dc.l 0 ;standard character set
title: dc.l sname ;pointer to title text
gadgets: dc.l 0 ;no gadgets
bitmap: dc.l 0 ;no bit map
intbase: dc.l 0 ;base address of intuition
screenhd: dc.l 0 ;screen handle
intname: dc.b 'intuition.library',0
align
sname: dc.b 'Our Screen',0 ;Screen title
align
end
From this example,you can see how easy scrolling actually is.
Another easy thing to do is to use the DisplayBeep function.It as
an offset -96;the only parameter it needs is the screen pointer
that you stored in the "screenhd"memory block.This function covers
the screen with an orange colour for a short while.The screen is
not changed.The beep function can be used as follows:
DisplayBeep: =-96
...
move.l intbase,a6 ;intuition base address in A6
move.l screenhd,a0 ;screen pointer in A0
jsr displaybeep(a6) ;light up screen
If you put a zero instead of a screen pointer in A0,the whole
screen blinks.
Good,now you have your own screen that you can move up and down.
What good is it if you can't put anything on it?Lets open a window
on the screen!
7.2.Open Window.
----------------
As you saw in the chapter on program initialization,its easy to
open a window with the DOS library.You can't use this method on
your own screen however.You need to use another method that can
open any window on any screen.
Intuition has a function called OpenWindow which handles this sort
of work.It has an offset of -204 and needs only one parameter,a
pointer to a window definition table.This pointer goes in register
A0.
This table is very similar to the one used to define the screen.
The first four values specify the X-and Y-positions,the width,and
the height of the window to be opened.Heres an example:
align
window_defs:
dc.w 10 ;x-position
dc.w 20 ;y-position
dc.w 300 ;width
dc.w 150 ;height
Next come two bytes that define the colour of the letters on the
background:
dc.b 1 ;white letter colour
dc.b 3 ;on a red background
The next long word contains the IDCMP flags in its bits.The bits
determine the circumstances under which Intuition sends a message
to the program.The bits have the following meanings:
Bit Value Name Meaning
-----------------------------------------------------------------
0 $000001 SIZEVERIFY
1 $000002 NEWSIZE Window size changed
2 $000004 REFRESHWINDOW
3 $000008 MOUSEBUTTONS Mouse key hit
4 $000010 MOUSEMOVE Mouse moved
5 $000020 GADGETDOWN A special gadget chosen
6 $000040 GADGETUP Same as above
7 $000080 REQSET
8 $000100 MENUPICK A menu item chosen
9 $000200 CLOSEWINDOW A window closed
10 $000400 RAWKEY A key pressed
11 $000800 REQVERIFY
12 $001000 REQCLEAR
13 $002000 MENUVERIFY
14 $004000 NEWPREFS Preferences modified
15 $008000 DISKINSERTED A disk put in
16 $010000 DISKREMOVED A disk taken out
17 $020000 WBENCHMESSAGE
18 $040000 ACTIVEWINDOW A window activated
19 $080000 INACTIVEWINDOW A window deactivated
20 $100000 DELTAMOVE Report relative mouse movement
If you want your first window to respond only by clicking on the
close symbol,write the following:
dc.l $200 ;IDCMP flags:CLOSEWINDOW
Next comes a long word whose bits determine the windows type.You
can use this to construct a window to your exact specifications.
This is quite different from windows opened with the DOS function.
The bits mean:
Bit Value Name Meaning
------------------------------------------------------------------
0 $0000001 WINDOWSIZING Window size is changeable
1 $0000002 WINDOWDRAG Window is moveable
2 $0000004 WINDOWDEPTH Window covering is posible
3 $0000008 WINDOWCLOSE Window close symbol
4 $0000010 SIZEBRIGHT
5 $0000020 SIZEBOTTOM
6 $0000040 SIMPLE_REFRESH New drawing manuel
7 $0000080 SUPER_BITMAP Save the windows contents
8 $0000100 BACKDROP Move window back
9 $0000200 REPORTMOUSE Report mouse co-ordinates
10 $0000400 GIMMEZEROZERO
11 $0000800 BORDERLESS Window without border
12 $0001000 ACTIVATE Window active
13 $0002000 WINDOWACTIVATE
14 $0004000 INREQUEST
15 $0008000 MENUSTATE
16 $0010000 RMBTRAP Right mouse key:no menu
17 $0020000 NOCAREREFRESH No refresh message
24 $1000000 WINDOWREFRESH
25 $2000000 WBENCHWINDOW
To refresh is to rebuild the window contents when necessary,for
instance when the windows size is changed.If none of the refresh
bits are set,you're in Smart-Refresh-Mode.In this case,Intuition
takes care of refreshing the window.This is the easiest method.
If you choose the value $100F as the type for your example window,
the window is active once its opened,and it has all the system
gadgets:
dc.l $100F ;ACTIVATE and all gadgets
The next long word in the list allows you to use your own gadgets
in the window.This long word is a pointer to the structure of a
your gadget.Since you don't want this,just put a zero here.
dc.l 0 ;first gadget:no gadgets of our own
The next long word is a pointer to a graphics structure so you can
design your own symbol for checking menu points.Put a zero here.
You'll use the standard sign:
dc.l windowname ;pointer to window name
The next long word is a pointer to the screen structure that you
got back after calling the OpenScreen function.The easiest way to
do this is to save the pointer to this location in the buffer:
screenhd: dc.l 0 ;screen pointer
The next long word is a pointer to a bit map if you want one of
your own for the window.Since you don't want one,put a zero here.
dc.l 0 ;no bit map of our own
Next come four values that set the maximum and minimum width and
height of the window:
dc.w 150 ;smallest width
dc.w 50 ;smallest height
dc.w 320 ;maximum width
dc.w 200 ;maximum height
The last value in the list is the screen type of the screen the
window is located in.Put a 15 here.You're using our screen as a
custom screen:
dc.w 15 ;screen type:custom screen
Heres a quick overview of the whole list:
align
window_prefs:
dc.w 10 ;X-position
dc.w 20 ;Y-position
dc.w 300 ;width
dc.w 150 ;height
dc.b 1 ;white print colour
dc.b 3 ;on red background
dc.l $200 ;IDCMP flags:CLOSEWINDOW
dc.l $100f ;ACTIVATE and all gadgets
dc.l 0 ;first gadget:no gadgets of
;our own
dc.l 0 ;checkmark:standard
dc.l windowname ;pointer to window name
screenhd: dc.l 0 ;screen pointer
dc.l 0 ;no bitmap of our own
dc.w 150 ;smallest width
dc.w 50 ;smallest height
dc.w 320 ;maximum width
dc.w 200 ;maximum height
dc.w 15 ;screen type:custom screen
;and here comes the window name:
windowname: dc.b 'Our Window',0
align
Insert these lines in the program you listed above.Here are two
subroutines for opening and closing the window:
openwindow =-204
closewindow =-72
...
windopen:
move.l intbase,a6 ;intuition base address in A6
lea windowdef,a0 ;pointer to window definition
jsr openwindow(a6) ;open window
move.l d0,windowhd ;save window handle
rts
windclose:
move.l intbase,a6 ;intuition base address in A6
move.l windowhd,a0 ;window handle
jsr closewindow(a6) ;close window
rts
...
windowhd: dc.l 0 ;window handle
Now you can insert a "bsr windowopen"after the "bsr scropen"and a
"bsr windclose"before the "bsr scrclose"command.Once you've
started the program,move the window around in the screen.You'll
find that you can't move the window out of the screen with the
mouse.
The window in the example has the close gadget in the upper left
corner.Normally if you click it,the window is closed.Try clicking
it.You'll find that nothing happens.
The display of this and all other gadgets,as well as other events
must be programmed in,since Intuition doesn't know which action
causes which event.We'll take a look at how to handle this in the
next chapter.
7.3.Requesters.
---------------
If you only have one disk drive,you've certainly seen the Amiga
message,"Please insert xxx in unit 0",a lot.This window is another
that has two fields for clicking.This sort of message with a
choice of options is called a requester.
You want to take a look at how to program a requester.First,you
need a window for the requester to appear in.You opened a window
of this sort in the example program.
To display a requester,use the Intuition function AutoRequest
(offset -348).It takes care of drawing and managing the requester.
This function needs the following parameters:
In A0 The pointer to the window structure that you put in
"windowhd".
In A1 A pointer to the text structure that should stand over the
choice buttons.
In A2 Same as above for the text of the left button.
In A3 Same as above for the right button.
In D0 The IDCMP flag which lets you know what event should go
with the clicking of the left button.
In D1 Same as above for the right button.
In D2 The width of the whole requester.
In D3 The height of the requester.
Insert the following lines in your program:
autorequest =-348
...
request:
move.l windowhd,a0 ;pointer to window structure
lea btext,a1
lea ltext,a2 ;pointer to text structure
lea rtext,a3
move.l #0,d0 ;left activates by clicking
move.l #0,d1 ;right activates by clicking
move.l #180,d2 ;width and
move.l #80,d3 ;height of requester
move.l intbase,a6 ;intuition base address
jsr autorequest(a6) ;display requester
rts
The flags passed in D0 and D1 offer some interesting posibilites.
The system messages that tells you to enter a particular disk are
overlooked when the DISKINSERTED flag is similar.Putting a disk in
brings about the same responce as clicking the "Retry"button.
Whats new is the use of a text structure.Use three of them.Text
structures are lists that contain entries for the text that you
need.
These lists begin with two bytes that are used to define the
colour.The first byte is the colour of the text.The second is for
the background colour.Here this doesn't have any meaning.
btext:
dc.b 2 ;black text colour
dc.b 0 ;background colour
The next byte specifies the character mode.A zero means that the
text is output normally.A four means the text is output inverted.
dc.b 0 ;normal text representation
The next entries are words.For this reason the addresses must be
even,so you need to either insert another byte or use the "align"
pseudo-op.The following words are the X-and Y-position of the text
relative to the upper left corner of the requester.
dc.w 10 ;X-position
dc.w 5 ;Y-position relative to upper
;left corner
Next,theres a pointer to the character set that is used.Put a zero
here to use the standard set.
dc.l 0 ;standard character set
Next you need to give the address of the text that should be
output.This text must be closed with a null byte.
dc.l text ;pointer to text
You need a long word at the end of the list that is either a
pointer to another text or a zero if no more text is needed.
dc.l 0 ;no more text
Here are the three text structures that you need for the example:
btext: ;text structure for the title
dc.b 0,1 ;colour
dc.b 0 ;mode
align
dc.w 10,10 ;text position
dc.l 0 ;standard font
dc.l bodytxt ;pointer to text
dc.l 0 ;no more text
bodytxt:
dc.b "Requester Text",0
align
ltext: ;text structure of left button
dc.b 0,1 ;colour
dc.b 0 ;mode
align
dc.w 5,3 ;text position
dc.l 0 ;standard font
dc.l lefttext ;pointer to text
dc.l 0 ;no more text
lefttext:
dc.b "left",0
align
rtext:
dc.b 0,1 ;colour
dc.b 0 ;mode
align
dc.w 5,3 ;text position
dc.l 0 ;standard font
dc.l righttext ;pointer to text
dc.l 0 ;no more text
righttext:
dc.b "right",0
align
After calling the requester,D0 contains the information about
which of the buttons were pressed,and in which button the event
took place.If D0 is zero,it was the right button.If it is one,it
was the left button.
7.4.Event Handling.
-------------------
Pretend you've opened a window that as a close symbol,and you want
the program to react to this symbol being clicked.You need a
signal from Intuition that lets you know that an event as taken
place.The signal is called a message.
The IDCMP flag of the window specifies which events should cause
Intuition to send a message.By setting the bits for WINDOWCLOSE,
you can allow a message to be sent when the close symbol is
clicked.
To get the message,you can use the EXEC function GetMsg (offset
-372).It needs the source address of the event as a parameter.Here
the source is the User port (which doesn't have anything to do
with the User port on old Commodore computors).
The User port contains a table which has entrieswhich specify the
events that have taken place and related things like mouse
position and time.
How do you find the User port?Use the pointer to the window
structure that you got back from the OpenWindow function and
stored in the "windowhd"memory block.
This pointer points to the window structure of this window.This
structure consists of a number of entries.Some are copies of the
parameters from our window definition table.We won't cover all the
entries,because most won't be interesting to you.You're more
interested in the pointer to the User port.Its in the window
structure.
You can find this in the long word that begins in the 86th byte of
the structure.You can get this long word with the following lines
of code:
move.l windowhd,a0 ;pointer to structure in A0
move.l 86(a0),a0 ;user port pointer in A0
You can call the GetMsg function with this pointer in A0 by using
the following lines of code in your program:
GetMsg = -372
...
move.l windowhd,a0 ;pointer to structure in A0
move.l 86(a0),a0 ;user port pointer in A0
move.l execbase,a6 ;exec base address in A6
jsr getmsg(a6) ;get message
This function returns a value in the D0 register.This value is a
pointer to another structure,the Intuition Message Structure.If
theres a zero in D0,no event as taken place.
The long word that starts at the 20th byte in this structure
contains the information about which event took place.Evaluating
the information is easy,since the bits of this long word have the
same meaning as the IDCMP flag that you described when you looked
at opening windows.
Put the lines above after "loop"and then insert the following:
move.l d0,a0 ;message pointer in A0
move.l 20(a0),d6 ;save event in D6
tst.l d0 ;did the event take place?
bne end ;yes!
Now you can end this program by clicking the close symbol.This way
you can find out if an event as taken place.You can use D6 to
determine what event took place.In the example,D6 contains the
number $00000200,which means that the close symbol was clicked.
To see if this works with other events,change the $200 IDCMP flag
to $10200 in the window definition table.When you've assembled and
started this version,take the disk out of the drive-the program
terminates.
The IDCMP flags that you've got now cause the clicking of the
close symbol and the taking out of the disk (DISKREMOVED) to be
reported.If you want to find out which of the events took place,
you can look in D6.It has a $200 in it if the window is closed,a
$10000 if the disk was removed.
7.5.Menu Programming.
---------------------
Now lets look at one of Intuitions more interesting capabillities:
menu programming.By using menus,you can make your programs very
user friendly.
There are a lot of ways for you to use menus.You can make menu
points unusable,output sub-menus,choose the type of menu entries
(allow text or pictures to be output),etc..To have lots of options
you need some parameters.
Lets produce a menu with the SetMenuStrip function (offset -264)
of Intuition.The function only needs two parameters,a pointer to
the menu structure of the window to be drawn and a pointer to the
window structure of the window in which the menu is to function.
Each window can have its own menu that is active when the window
is activated.
Heres the subroutine to set up the menu:
SetMenuStrip =-264
...
setmenu: ;* Initialize a menu
move.l intbase,a6 ;intuition base address in A6
move.l windowhd,a0 ;pointer to window structure
lea menu,a1 ;pointer to menu structure
jsr setmenustrip(a6) ;call function
rts
Heres a routine to erase the menu:
ClearMenuStrip =-54
...
clearmenu:
move.l intbase,a6 ;intuition base address in A6
move.l windowhd,a0 ;pointer to window structure
jsr clearmenustrip(a6)
rts
You've already got the pointer to the window structure.Lets look
at the menu structure you need for the menu.You need to build a
structure like this for each menu--for each menu title that
appears when you press the right mouse key.
This structure is a table with the following form:
First there is a long word that points to the menu structure of
the next menu.If the current menu is the last one,a zero goes
here.
align
menu:
dc.l menu1 ;pointer to the next menu
Next come two words which contain tha X- and Y-position of the
menu title:
dc.w 20 ;X-position
dc.w 0 ;Y-position
Next,use two words to store the menu titles width and height in
pixels:
dc.w 50 ;width
dc.w 10 ;height of menu title
The next word contains the flag bit that determines whether the
menu is available or not.An unavailable menu either as grey
entries or they are drawn weakly.If the flag bit,bit 0,is set the
menu is available.Otherwise,it is not.
dc.w 1 ;menu available
Now comes a long word which functions as a pointer to the text
which is used as the menu title.Make sure the length isn't larger
than the width entry allows!Otherwise unpleasent things will
happen.
dc.l menutext ;pointer to title text
Next comes a long word which functions as a pointer to the
structure of the first menu entry of this menu.Each menu entry
needs its own structure.
dc.l menuitem01 ;pointer to the first menu item
The last entries in the table are four words that are reserved for
internal functions.They must be here.
dc.w 0,0,0,0 ;reserved words
Thats the structure of the first menu.This structures first long
word points to the next structure which has the same form.The
pointer is set to zero in the last menu.
You still need the structure of the menu entries.These structure
tables have the following form:
They start with a pointer to the next menu item.This pointer is
set to zero for the last entry.
align
menuitem01:
dc.l menuitem02 ;pointer to next menu item
Next comes the four words:the X- and Y-position,the width and the
height of the box the menu entry goes in.The size becomes obvious
when the item is chosen by having the right mouse key clicked on
it.Then the box becomes visible.As you can see,the next word is
determined in the flags.First lets set the position and size of
the menu point,though:
dc.w 0 ;X-position of entry
dc.w 0 ;Y-position
dc.w 90 ;width in pixels
dc.w 10 ;height in pixels
The position entries are relative to the upper left corner of the
menu that is pulled down.
The following word was described above:it contains flags for
entries to this menu item.There are several interesting variations
possible.The following flag bits are contained in this word:
Bit Value Name Meaning When Set
------------------------------------------------------------------
0 $0001 CHECKIT Point is checked when chosen
1 $0002 ITEMTEXT Text menu item
2 $0004 COMMSEQ Choice can be made with keys as well
3 $0008 MENUTOGGLE Check turned on and off
4 $0010 ITEMENABLED Menu item available
6 $0040 HIGHCOMP Item inverted when chosen
7 $0080 HIGHBOX Iten framed when chosen
8 $0100 CHECKED Item is checked
Heres a description of the bits:
Name Description
------------------------------------------------------------------
CHECKIT If this bit is set,a check or a user-defined
drawing is put in front of the text when the item
is chosen.The text should begin with two blanks.
ITEMTEXT The menu item is a normal text if this bit is set.
Otherwise a drawing is output.
COMMSEQ By setting this bit and entering a character,this
menu point can be chosen by pressing the right
<Amiga> key and the key that was input.The input
character is then displayed in the menu with the
Amiga symbol.There needs to be space available for
this.
MENUTOGGLE If this bit is set and checking is allowed (bit 0),
the second time this point is chosen the check is
erased,the next time it is displayed again,etc...
ITEMENABLED Erasing this bit makes the menu item available.
HIGHCOMP If this bit is set,the box you've defined is
inverted when this menu item is chosen by the mouse
pointer.
HIGHBOX In this mode,the box is framed whin its chosen.
The two previous bits determine the mode of the chosen menu item.
The following combinations are possible:
HIGHIMAGE If both bits are cleared,choosing the bit causes a
self-defined drawing to be output.
HIGHNONE When both bits are set,there isn't any reaction to
choosing this item.
CHECKED This bit can be set by either the program or
Intuition.It lets you know if the menu text has a
check next to it or not.You can use this to find
out if the item was checked by testing but eight.If
its set,the item was checked.You can also use it to
cause the item to be checked.
You're choosing the mode CHECKIT,ITEMTEXT,COMMSEQ,MENUTOGGLE,ITEM-
ENABLED and HIGHBOX for the example:
dc.w $10011111 ;mode flag
Lets get back to the structure of the menu items.After the flag
word,there is a long word whose flag bits determine whether this
menu point can be turn off another one.Set this to zero:
dc.l 0 ;no connection
Now comes the pointer to the structure of the text that should be
displayed.If the ITEMTEXT bit isn't set,this pointer must point to
the structure of the drawing.If nothing should be shown,you can
set this to zero.Use a text in the example and write the
following:
dc.l menu01text ;pointer to menu text structure
The following long word only has a meaning if the HIGHIMAGE flag
is set.Then this long word points to the text or the drawing that
should be displayed when the menu items box is clicked.Otherwise
the long word is ignored,so insert a zero:
dc.l 0 ;no drawing when clicked
The next entry is a byte that is used for input of keyboard
characters,which together with the right <Amiga> key can be used
to choose the menu item.This only works if the COMMSEQ bit is set.
Place a character here:
dc.b 'A' ;choose item using <Amiga>/'A'
Since the next item is a long word,you need an "align"peudo-op
here.Next comes the long word that points to the menu item
structure or a submenu.The submenu is automatically shown when
this menu item is clicked.You can't nest them any deeper,however,
so this long word is ignored for submenus.
If you don't want a submenu to this item,put a zero here:
align
dc.l 0 ;no submenu
The next and final long word is written to by Intuition if you
choose several menu itens.In this case,the menu number of the next
menu item chosen goes here:
dc.l 0 ;preparation
Thats the structure for a menu item.You still need the text
structure for the text of the item.This isn't complicated,but it
makes you get into fine details about the form of the menu.You've
already learned about this text structure when you looked at
requesters,so we'll skip an explanation.
Heres the complete structure of an example menu.You can use two
menus,each with two subpoints.The second menu point of the left
menu has a submenu with two entries.You ought to type this program
in,so that you can experiment with it.You can also use this
example to evaluate the clicked menu item.
;**Complete menu structure foe example menu **
menu:
dc.l menu1 ;no next menu
dc.w 10,30 ;X/Y
dc.w 50,10 ;width/height
dc.w 1 ;menu enabled
dc.l menuname ;menu title
dc.l menuitem01 ;menu entry
menuname:
dc.b "Menu 1",0 ;first menu name
align
menu1:
dc.l 0 ;no further menu
dc.w 80,0 ;see above
dc.w 50,10
dc.w 1
dc.l menuname1
dc.l menuitem11
dc.w 0,0,0,0
menuname1:
dc.b "Menu 2",0 ;second menu name
align
menuitem01: ;first menu item
dc.l menuitem02 ;pointer to next entry
dc.w 0,0 ;X/Y
dc.w 130,12 ;width/height
dc.w $9f ;flags
dc.l 0 ;exclude
dc.l text01 ;pointer to text structure
dc.l 0 ;select fill
dc.b "1" ;command
align
dc.l 0 ;subitem:none
dc.w 0 ;next select:no
text01:
dc.b 0,1 ;colours
dc.b 0 ;mode:overwrite
align
dc.w 5,3 ;X/Y position
dc.l 0 ;standard character set
dc.l text01txt ;pointer to text
dc.l 0 ;no more text
text01txt:
dc.b "Point 0.1",0
align
menuitem02: ;second menu item
dc.l 0
dc.w 0,10
dc.w 130,12
dc.w $57
dc.l 0
dc.l text02
dc.l 0
dc.b "2" ;activate with <Amiga>/'2'
align
dc.l 0
dc.w 0
text02:
dc.b 0,1
dc.b 0
align
dc.w 5,3
dc.l 0
dc.l text02txt
dc.l 0
text02txt:
dc.b "Point 0.2",0
align
menuitem11: ;first menu point of the second menu
dc.l menuitem12 ;pointer to second menu point
dc.w 0,0
dc.w 90,12
dc.w $52
dc.l 0
dc.l text11
dc.l 0
dc.b 0
align
dc.l 0
dc.w 0
text11:
dc.b 0,1
dc.b 0
align
dc.w 5,3
dc.l 0
dc.l text11txt
dc.l 0
text11txt:
dc.b "Point 1.1",0
align
menuitem12: ;second menu item of second menu
dc.l 0 ;no more items
dc.w 0,10
dc.w 90,12
dc.w $92
dc.l 0
dc.l text12
dc.l 0
dc.b 0
align
dc.l submenu0 ;pointer to submenu
dc.w 0
text12:
dc.b 0,1
dc.b 0
align
dc.w 5,3
dc.l 0
dc.l text12txt
dc.l 0
text12txt:
dc.b "Point 1.2",0
align
submenu0: ;first point of submenu
dc.l submenu1 ;pointer to next point
dc.w 80,5
dc.w 90,12
dc.w $52
dc.l 0
dc.l texts0
dc.l 0
dc.b 0
align
dc.l 0
dc.w 0
texts0:
dc.b 0,1
dc.b 0
align
dc.w 5,3
dc.l 0,texts0txt,0
texts0txt:
dc.b "S Point 1",0
align
submenu1: ;submenu,second item
dc.l 0
dc.w 80,15
dc.w 90,12
dc.w $52
dc.l 0
dc.l texts1
dc.l 0
dc.b 0
align
dc.l 0
dc.w 0
texts1:
dc.b 0,1
dc.b 0
align
dc.w 5,3
dc.l 0
dc.l texts1txt
dc.l 0
texts1txt:
dc.b "S Point 2",0
align
The menu items in this example have the following properties as a
result of their flags:
Menu 1;
The first item,"Point 0.1",can be chosen using the right <Amiga>
key and the "1" key.This point alternates between checked and not
checked,which can easily be used to check out the key function.If
the item is checked and you hit both keys,the check disappears and
vice versa.The box at this point is framed when the mouse pointer
clicks on it.
The second item,"Point 0.2",can be chosen using the right <Amiga>
key and the "2"key.This item is checked the first time it is
chosen.However,in contrast to the item above,it can't be erased.
The box of this item is inverted when clicked.
Menu 2;
These two points can't be chosen using keys.The box of the upper
item is inverted when clicked on:the lower one is framed.When you
click the second item,"Point 1.2",a submenu with two entries is
displayed.
Experiment with this structure a little bit.Change some values and
see what happens.As you can see,menu programming isn't as bad as
you thought,and it offers a lot of options (but you'll have to do
lots of typing!).
When you've done experimenting,you'll want to produce your own
program with menus.How does the program find whether a menu item
in a menu has been clicked on?
You already looked at one way to find out the menus state.You can
test the CHECKED bit in the flag word of a menu item.If this is
set,the user clicked on this item with the mouse.
This only works if checking is allowed for the item being tested.
You could allow all the menu items to be checked,but this still
isn't a good solution--it requires testing all the flag bits of
all the menus one after the other.That makes very boring
programming.
You've already learned about finding about events from Intuition.
You've moved the message about which event took place into D6,and
you can look at it to find out what happend.
If you set the eight bit,the MENUPICK bit,of the IDCMP flag long
word in the window definition,the choice of the menu point is
reported.Put the following lines in your loop in the main program.
loop:
move.l execbase,a6 ;exec base address in A6
move.l windowhd,a0 ;window structure pointer
move.l 86(a0),a0 ;user point pointer in A0
jsr getmsg(a6) ;get message
tst,l d0 ;whay happend?
beq loop ;nothing happend
move.l d0,a0 ;message pointer in A0
move.l $14(a0),d6 ;event in D6
If the program makes it out of the loop,an event as taken place.
You have the events flag in the D6 register.You can evaluate the
event using CMP or BTST to find out which flag bits are set.You
can then execute the function corresponding to the set bit.You can
use lines like the following ones:
cmp #$200,d6 ;WINDOWCLOSE?
beq ende ;yes:program end
These lines terminate the program when the window is closed.
If the user chose a menu item,there is a $100 in the D6 register.
You now need to determine which item it was.
You can find this information in a word that comes right after the
long word with the event flags in the message structure.Write:
move $18(a0),d7
You now have the code for the clicked menu item in the D7
register.If the user just pressed the right key and let it go
without choosing a menu item,you'll find a $FFFF here.This word
doesn't contain just one,but three pieces of information:
Which menu was the item chosen from?
Which menu item?
Which submenu?
The information is divided in three bit groups.The division is as
follows:
Bits 0-4 Menu title number
Bits 5-10 Menu item number
Bits 11-15 Submenu item number
The numbering begins with zero-ie the first menu point of the
first menu has the numbers 0 and 0.
To try this out insert the following lines:
move d7,d6 ;move code into D6
lsr #8,d7 ;shift right 11 times
lsr #3,d7 ;submenu item now in D7
clr.l d5
roxr #1,d6 ;bit 0 in X-flag
roxl #1,d5 ;menu number now in D5
and.l #$7f,d6 ;issolate lower bits
cmp #$7f,d6 ;no menu item?
beq loop ;no:continue
lsr #4,d6 ;else menu item in D6
ende
By making a test run with AssemPro,you can easily see if this
works right-just look at the registers after the program is over.
If you,for example,want to write a program with four menus with 10
menu items each,this sort of method is too much work-there are 44
tables.For this reason,lets look at a short program that takes
care of the necessary structure table itself.
The menu structure is built very simply-it doesn't offer submenus
or the option of choosing items via the keyboard.If you want these
extras,you can still use this program,but you'll have to use MOVE
commands to insert the desired flags and pointers.
The input that this program needs is a list of the menu names and
the items in each menu.The addresses of the menu texts go in a
table with the following simple form:
dc.l Menu title 1
dc.l Point1,Point2,Point3,...,0
dc.l Menu title 2
dc.l Point1,Point2,Point3,...,0
dc.l Menu title 3 oder 0
This program is set up in such a way that up to four menus can lie
next to each other (in normal screen resolution),which is often
plenty.The table above ends by putting a zero instead of a pointer
to the nxt menu title.As you can see,its pretty simple.
This program is inserted in your big program right behind the
"setmenu"label.After the "bsr setmenu"command is executed,the menu
structure is built and initialized at the same time.You don't need
to change the rest of the program,it'll be shorter that way.
Heres the program fragment for the complete "setmenu"routine:
setmenu: ;*initialize menu structure
lea mentab,a0 ;pointer to text pointer in A0
lea menu,a1 ;pointer to menu field in A1
move #10,d1 ;horizontal menu position=10
menuloop:
clr.l d2 ;vertical menu position=0
move.l a1,a2 ;save address of pointer
tst.l (a0) ;another menu there?
beq setmenu1 ;no:quit
clr.l (a1)+ ;"no more menus"preperations
move d1,(a1)+ ;set X-position
add.l #70,d1 ;and increment
move.l #50,(a1)+ ;Y-position and width
move.l #$a0001,(a1)+ ;height and flag
move.l (a0)+,(a1)+ ;menu title
lea 12(a1),a3
move.l a3,(a1)+ ;pointer to menu item
clr.l (a1)+ ;reserved words
clr.l (a1)+
itemloop:
tst.l (a0) ;last entry?
beq menuend ;yes:menu done
lea 54(a1),a3
move.l a3,(a1)+ ;pointer to next item
move.l d2,(a1)+ ;X- and Y-positions
add #10,d2 ;Y-position+10
move.l #$5a000a,(A1)+ ;WIDTH/HEIGHT
move #$52,(a1)+ ;flag:normal
clr.l (a1)+ ;no connection
lea 16(a1),a3
move.l a3,(a1)+ ;text structure pointer
clr.l (a1)+ ;no fill structure
clr.l (a1)+ ;no command,no submenu
clr.l (a1)+ ;and no continuation
move #$1,(a1)+ ;set text structure:colour
clr.l (a1)+ ;mode 0
move.l #$50003,(a1)+ ;X- and Y-position
clr.l (a1)+ ;standard character set
move.l (a0)+,(a1)+ ;text pointer
clr.l (a1)+ ;no continuation
bra itemloop ;next item...
menuend: ;eventual transfer to next menu
clr.l -54(a1) ;erase pointer to next item
tst.l (a0)+ ;increment table pointer
tst.l (a0) ;another menu there?
beq setmenu1 ;no:done
move.l a1,(a2) ;pointer to next menu
bra menuloop ;and continue
setmenu1: ;*initialize menu (like before)
move.l intbase,a6 ;intuition base address in A6
move,l windowhd,a0 ;window structure in A0
lea menu,a1 ;pointer to menu structure
jsr setmenustrip(a6)
rts
You need three things yet for this program:the memory to be used
for the structure,the table of text pointers and the text.Heres an
example:
mentab:
dc.l menu1 ;first menu title
dc.l mp11,mp12,mp13 ;menu items
dc.l 0 ;end of menu 1
dc.l menu2 ;second menu title
dc.l mp21,mp22,mp23 ;menu items
dc.l 0 ;end of menu 2
dc,l 0 ;you're out of menus!
;** Menu Text **
menu1: dc.b "Menu 1",0
mp11: dc.b "Point11",0
mp12: dc.b "Point12",0
mp13: dc.b "Point13",0
menu2: dc.b "Menu 2",0
mp21: dc.b "Point21",0
mp22: dc.b "Point22",0
mp23: dc.b "Point23",0
align
;** Storage space for menu structure **
menu: blk.w 500
Make sure that the memory area reserved for the menu structure is
big enough and change the entry "blk.w 500"to the calculated
value.
If you use this program,and want to build some special features
into the menu (for instance key commands),you can make entries in
the menu structure table while the program is running.You can find
the word (or byte or long word) that interests you in the table as
follows:
For example,to find the keyboard command byte of the second entry
in the first menu,calculate as follows:
Address = Start_address+Menu*30+(entry-1)*54+26
which in the example comes to:
Address = menu+30+54+26
= menu+110
The 26 is the distance from the beginning of the MenuItem
structure to the desired byte,the command byte.In this way,you can
calculate the addresses and use MOVE commands to modify the menu
to fit your wishes.By the way,in the example above,the correspond-
ing flag bit must be set as well,so that the keyboard command is
recognized.
Now lets get back to the window.Its nice to have a window that you
can change and close,but you really want to be able to output text
in a window!
7.6.Text Output.
----------------
Its very easy to use Intuition's text output function.Use the
PrintIText function (offset -216).It needs four parameters.
In A0 A pointer to the RastPort of the window.You can find this
in the window structure.
In A1 A pointer to the text structure of the text that should
be output.
In D0 The X-position.
In D1 The Y-position of the text in the window.
Its very easy to enter the X- and Y-positions.You've already used
the text structure twice (for requesters and menus).
Whats new is accessing the windows RastPort.The RastPort is a
structure that describes the window.The address is needed by
several Intuition functions.
The pointer to the RastPort starts at the 50th byte in the window
structure.You can access it as follows:
move.l windowhd,a0 ;address of window structure
move.l 50(a0),a0 ;RastPort address in A0
Now you've got the address of the RastPort.Lets write a routine
that prints a text.The X- and Y-positions are in D0 and D1
respectively and the address of the text structure in A1 before
the routine is called:
PrintIText = -216
...
print:
move.l intbase,a6 ;intuition base address in A6
move.l windowhd,a0 ;address of window structure
move.l 50(a0),a0 ;rastport address in A0
jsr printitext(a6) ;call function
rts
You can try out this routine by using the requesters text that is
still in a structure of the program.Write the following lines
before the "loop"label:
lea btext,a1 ;pointer to text structure in A1
move.l #10,d0 ;X-position
move.l #30,d1 ;Y-position of text
bsr print ;output text
Start the program and the text appears in the middle of the window
If this doesn't happen,check the colour of the text in the text
structure.Its probably zero.Just change it to three,and the text
appears in red the next time you start the program.
7.7.Images.
-----------
An image is a drawing that goes in a rectangular field and is
defined bitwise.The disk symbol of the Intuition screen and the
system gadgets in the screen and window borders are examples of
such Images.
The rectangle that the drawing goes in can be arbitrarily large,
but each pixel in the rectangle needs its own bit,so programming
screen-sized Images isn't advisable.You'll stick to an Image that
requires about 32x16 bits-an Image thats about 3x1cm.
You can make all sorts of images as you've seen looking at window
gadgets.There is an Intuition functionthat draws an Image:It is
the DrawImage function (offset -114) and it needs 4 parameters:
In A0 The address of the rastport image is drawn in.You've
already learned how to access this address in the section
on the text function.
In A1 The structure address of the image to be drawn.
In D0 The relative X-position
In D1 The relative Y-position of the drawing.
Lets draw this picture in your window.It justs takes a simple
routine.You just need to put the address of the image structure in
A1 and the position of the image in D0 and D1 before you call it.
DrawImage =-114
...
draw: ;*draw image
move.l intbase,a6 ;intuition base address in A6
move.l windowhd,a0 ;pointer to window structure
move.l 50(a0),a0 ;now,rastport address in A0
jsr drawimage(a6) ;draw image
rts
Now you need the structure of the image.The structure contains
nine entries which have the following meanings:
The first two entries are words which specify the distance in the
X- and Y-direction from the co-ordinates that were given to tell
where the image should be drawn.You'll just put two zeros here:
image:
dc.w 0,0 ;X- and Y-position
Next come two words which specify the width and height of the
image in pixels.Lets draw a 32x13 point image.Enter:
dc.w 32,13 ;width and height of image
The next word in the list specifies the number of planes in the
drawing.If its a simple image that only uses two colours,just
enter a one.For more colours,you'll need a correspondingly bigger
number.When more colurs are worked with,the bit pattern of the
image must have more data.Lets just have one bit plane:
dc.w 1 ;one bitplane:2^1=2 colours
Next comes a long word that points to the data of the image:
dc.l imgdata ;pointer to image data
The next two bytes are very interesting.The first byte,the
PlanePick byte,tells which plane of the window or screen the image
data should be written in.Since you only have one plane,you need
to enter the bit plane of the window.This information is found in
the bits of the byte-bit0 stands for plane 0,bit 1 for plane 1,etc
..You also define the colour of the image with this input.If you
enter a two,every set bit of your image represents a red point.
dc.b 2 ;drawing red:plane 1
The second byte,the PlaneOnOff byte,is an interesting enhancement.
Each bit of the window bit plane corresponds to a whole number
here.The only bytes that are interesting though are the ones that
are cleared in the PlanePick byte.If the bit is set in PlaneOnOff,
evert bit of the image in the corresponding plane is set.Otherwise
they are cleared.To make sure that each bit of the image that
isn't set appears white,enter a one.All the bits of the image that
aren't set,are set in Plane 1 and appear white.
dc.b 1 ;background:white
The last entry of the structure is a lobg word that points to
another image.You don't need this,so set the long word to zero:
dc.l 0 ;no more images
Heres a quick overview of the image structure:
image:
dc.w 0,0 ;X- and Y-positions
dc.w 32,13 ;width and height of image
dc.w 1 ;one bitplane:2^1=2 colours
dc.l imgdata ;pointer to image data
dc.b 2 ;drawing red:plane 1
dc.b 1 ;background:white
dc.l 0 ;no more images
Now lets produce the image data.Each image row uses a word,long
word,or several of these represent the pattern.The set points of
the image correspond to the set bits.This is repeated as often as
the height of the image requires.The data on each line must begin
on a word border,on a even address.
For the example,its easy to decide on the data,since you're going
32 points across-that corresponds to exacty one long word.Its
easiest to program the image using the binary representation of
the data.
Lets use,as an example,an image that represents a switch in "OFF"
mode.This form is chosen for a good reason,so you should type it
in.In the chapter on gadgets thats coming up,we'll show you how to
turn the switch on.Here is the example data for the switch image:
imgdata: ;Data for switch in "OFF" mode
dc.l %00000000000000000000000000000000
dc.l %00000000000000000000111000000000
dc.l %00011101110111000001111100000000
dc.l %00010101000100000001111100000000
dc.l %00010101100110000001111000000000
dc.l %00011101000100000011100000000000
dc.l %00000000000000000111000000000000
dc.l %00000000000000001110000000000000
dc.l %00000000000111111111100000000000
dc.l %00000000001111111111110000000000
dc.l %00000000001111111111110000000000
dc.l %00000000000110000001100000000000
dc.l %00000000000000000000000000000000
Once you've typed in this data,you can experiment with displaying
it on the screen.Enter the following lines before the "loop"label:
move.l image,a1 ;pointer to image structure
move #30,d0 ;X-postion in window
move #50,d1 ;Y-position
bsr draw ;draw image
How do you like the image on the screen?You'll run into this
switch again when we talk about putting the switch in the "ON"
state when discussing gadgets.You need to look at other methods of
drawing in the window first,though.
7.8.Borders.
------------
A border is a collection of lines that are connected.They can be
of any length or at any angle.Intuition lets you draw borders to
do things like put frames around windows and screens.They are used
to put borders around pictures or text,especially for use with
string gadgets.We'll talk about that later,though.
Its easy to draw borders.Just use the Intuition function
DrawBorder (offset -108) which needs four parameters:
In A0 The rastport address of the output medium the lines should
be drawn in.Use your window.
In A1 The address of the border structure.We'll look at the form
of this structure shortly.
In D0 The relative X-co-ordinate which is used with the X- and Y
co-ordinate list to calulate the actual line co-ordinates.
In D1 The relative Y-co-ordinates.Relative,here too,means that
this is relative to the upper left corner of the screen.
Lets write a short routine that is called with three parameters.
The structure address in A1 and the X and Y co-ordinates are in D0
and D1 respectively when the routine is called.The border is drawn
in the window whose structure address is in "windowhd".
DrawBorder =-108
...
borderdraw: ;* draw several lines
move.l inbase,a6 ;intuition base address in A6
move.l windowhd,a0 ;pointer to window structure
move.l 50(a0),a0 ;now rastport address in A0
jsr drawborder(a6) ;draw lines
rts
Now lets look at the border structure.The list needs the eight
following parameters:
First,you need two words for the vertical and horizontal distance
from the co-ordinates given in the function call.To avoid losing
sight of some of the many distance entries,put two zeros here:
border:
dc.w 0 ;horizontal distance
dc.w 0 ;vertical distance
Next come two bytes that determine the colour.Use a red frame:
dc.b 3 ;red frame
dc.b 0 ;background (unused)
As you can see,the background colour isn't used.You have two modes
to choose between for drawing the lines.The following mode
determines the mode that is used.If it is zero,each line is drawn
in the colour chosen,no matter what was done before.This is the
JAM1 mode.The other mode is the XOR mode which ignores both colour
entries.In this mode,all the points that lie under the line have
their colour value inverted.As a result,a white point becomes
black,and a blue one becomes red.That is mode two.Lets use the
JAM1 mode for the example:
dc.b 0 ;mode:JAM1 (2=XOR)
The next entry specifies how many co-ordinate pairs there are in
the list.Since this word must be on an even address,you need to
use the "align"peudo-op first.Then enter the number of pairs.
Remember that you need three points to draw two lines:beginning,
corner and end point.To draw a rectangular frame,you need five
pairs:
dc.b 5 ;5 X,Y pairs used together
The next item is a pointer to the co-ordinate table that contains
a list of points to be connected:
dc.l coord ;pointer to cordinate table
The border structures final entry is a long word that can point to
another border structure.If you don't have any more structures to
be pointed to,just enter a zero here.The pointer is useful for
connecting two independant border structures-for example,to
produce a two coloured frame that really stands out.You don't need
this pointer in the example,though:
dc.l 0 ;no more structures
Thats the border structure.Now lets look at the co-ordinate list.
For the example,it consists of five pairs of numbers which
represent a rectangle.I recommend entering these values,because
you'll use them in example programs further down the line.
coord: ;coordinates for rectangle frame
dc.w -2,-2
dc.w 80,-2
dc.w 80,9
dc.w -2,9
dc.w -2,-2
Heres a quick overview of the border structure:
border:
dc.w 0 ;horizontal distance
dc.w 0 ;vertical distance
dc.b 3 ;red frame
dc.b 0 ;background (unused)
dc.b 0 ;mode:JAM1 (2=XOR)
dc.b 5 ;5 X,Y pairs used together
dc.l coord ;pointer to cordinate table
dc.l 0 ;no more structures
coord: ;coordinates for rectangle frame
dc.w -2,-2
dc.w 80,-2
dc.w 80,9
dc.w -2,9
dc.w -2,-2
Once you've typed this in,you can try the whole thing out.Type the
following lines before the "loop"label in the program:
lea border,a1 ;address of the border structure
move #20,d0 ;X base position
move #80,d1 ;Y base position
bsr drawborder ;draw frame
As you can see,using enough X and Y co-ordinates,you can draw the
Eiffel tower.Thats enough about simple drawings.You want to put
some life into your drawings and text.Lets manipulate them with
the mouse!
7.9.Gadgets.
------------
We already talked a bit about gadgets when you looked at screen
construction.Looking at system gadgets like the window close
symbol,you can activate by clicking and causes a program function
to be executed.
You can make your own gadgets as well.Intuition allows you a lot
of interesting possibilities.
There are four types of gadgets:
Boolean gadgets are used in Yes/No situations.You can click and
activate it (Yes) or deactivate it (No).
String gadgets are used to accept input of text of a specified
length.
Integer gadgets are a special sort of string gadgets which accept
the input of a decimal number.Intuition converts the value into a
long word and sends it to the program.
Proportional gadgets let you choose an analog value with the mouse
You can move these around with the mouse.
7.9.1.Boolean Gadgets.
----------------------
Lets start with the simplest type,the boolean gadget.an example of
this sort of gadget is the close symbol of the window.The only
status it differenciates between are clicked and not clicked.Lets
develop a gadget of this type step by step.The flags and other
parameters are similar for the other gadgets.
Each gadget needs a structure containing fifteen entries.There is
a pointer to this structure in window,screen or requester that the
gadget is to appear in.Theres always a long word available for
this purpose.Up to this point,you've just put a zero there.If
there is an address of a gadget structure there,the gadget or
gadgets are displayed when the window is opened.
A gadget structure as the following entries:
The first long word is a pointer to the next gadget to be
installed.The gadgets are displayed in a row,like pearls on a
string.This pointer is the first gadget in this linked list of
gadgets.If you just want one gadget in your window,put a zero
here:
gadget1:
dc.l 0 ;no more gadgets
The next two words determine the position of the gadget in the
window.There are several ways to determine the position.Use flags
to access the various possibilities.Lets start with a gadget that
stays in one spot:
dc.w 40 ;X and
dc.w 50 ;Y position of the gadget
The next two words determine the size of the gadgets Hit box.This
box isn't the visible size of the gadget (that depends on the
image data).It is the size of the rectangle that Intuition should
watch.If the mouse pointer is moved into this box and the left
button pressed,the gadget is activated.Clicking on parts of the
gadget that are outside this box have no effect!
dc.w 32 ;width and
dc.w 13 ;height of the hit box
Next comes the word whose bits determine the properties of the
gadget.Bits 0 and 1 determine what should happen when this objects
hit box is clicked on.The meanings of the various values of these
bits go as follows:
Bit 0 1 Value Name Meaning
------------------------------------------------------------------
0 0 0 GADGHCOMP The gadget inverted
0 1 1 GADGHBOX The gadget framed
1 0 2 GADGHIMAGE Another image appears
1 1 3 GADGHNONE No reaction
Bit 2 determines whether the gadget should consist of a drawing or
a border.If it is set(Value+4),it is treated as an image;otherwise
its treated like a border.
The next bit determines if the gadget should appear in the upper
or lower border of the frame.If it is set(Value+8).the position is
relative to the lower border;otherwise it is relative to the upper
border.The next bit as the same meaning for the horizontal
position.If set(Value+$10),it is a relative positioning.Otherwise,
it is an absolute positioning.
Notice that when you define a gadget to be relative,you must have
a negative value in the position input in the first word of the
structure.Since the desired position isn't under,but its over this
position!
In this way,you can choose either absolute or relative positioning
of the gadget.An example of a gadget that is positioned absolutely
is the system gadget,close window.An example of a relative gadget
is the symbol for changing the size.
The width and height of the gadgets hit box can also be relative
to the window size.Specify this by using bit 5 for width (Value +
$20)and bit 6 for the height (Value +$40).A set bit mens a
relative size.
Bit 7 (Value+$80)makes the object active as soon as the window is
opened.
Bit 8 (Value+$100)determines whether the gadget can be used or not
If this bit is set,the gadget can't be activated.
For the example,you'll use absolute positioning and size,the
inverted appearance for the activated gadget,and the
representation of the object as an image.That means you must use
the value four:
dc.w 4 ;flags:image,invert
Next comes a word whose bits are used as flags.This flag is called
the Activation Flag.It determines the functions of the gadget.The
bits,their values and meanings follow:
Bit Value Name Meaning
------------------------------------------------------------------
0 1 RELVERIFY Causes the gadget to be activated
only when the left mouse key is let
loose over the gadget.
1 2 GADGIMMEDIATE Lets the gadget be active as soon as
there is a click.
2 4 ENDGADGET Lets you choose to end this choice
and have it disappear if this is a
requester gadget.
3 8 FOLLOWMOUSE Lets the gadget know the mouse
position at regular intervals from
the time it is selected until the
time it is deselected.You can use
this to move the gadget with the
mouse when you want to change the
gadget position.
4 $10 RIGHTBORDER This makes sure thay when borders
are used that the page is adjusted
to the size of the gadget so that it
fits in the border.
5 $20 LEFTBORDER
6 $40 TOPBORDER
7 $80 BOTTOMBORDER
8 $100 TOGGLESELECT Allows the objects state to change
every time it is clicked.If
activated,it becomes deactivated and
vice versa.
9 $200 STRINGCENTRE For a string gadget,these two bits
determine whether the string should
appear centred or right justified.If
neither is set,the string is output
left justified.
10 $400 STRINGRIGHT
11 $800 LONGINT Turns a string gadget into a Integer
gadget (explanation later).
12 $1000 ALTKEYMAP Causes another ketboard placement to
be in effect for string gadget input
Thats it for the activation flags.Lets choose the TOGGLESELECT and
GADGETIMMEDIATED flags for example:
dc.w $102 ;activation
The next word of the gadget structure determines the gadget type.
Heres the meaning of the individual bits:
Bit Value Name Meaning(report what circumstances)
----------------------------------------------------------------
0 1 BOOLGADGET This is a boolean gadget
1 2 GADGET002
2 4 STRGADGET String order Integer gadget
0+1 3 PROPGADGET Proportional gadget
System gadgets:
4 $10 SIZING Size changing gadget
5 $20 WDRAGGING Moving gadget for window
4+5 $30 SDRAGGING Same for screen
6 $40 WUPFRONT Gadget to move window forward
6+4 $50 SUPFRONT Gadget to move screen forward
6+5 $60 WDOWNBACK Move window back
6+5+4 $70 SDOWNBACK Move screen back
7 $80 CLOSE Window close gadget
Type definitions:
12 $1000 REQGADGET Requester gadget
13 $2000 GZZGADGET Border gadget in GIMMEZEROZERO
window
14 $4000 SCRGADGET Screen gadget when set
15 $8000 SYSGADGET System gadget when set
You want to use a simple boolean gadget for your example,so enter:
dc.w 1 ;gadget type:boolean
Next comes a pointer to the gadget structure.The first pointer
contains the address of the image or border structure which should
be used to represent the gadget.If no representation is needed,put
a zero here.You want to represent the gadget as an image,so put a
pointer to the image structure that you produced in the chapter
about images:
dc.l image ;gadget image
The next pointer is only used if the GADGHIMAGE flag in the flag
word of the structure is set.This is a pointer to another
structure that should be put on the screen when the object is
activated.If a border structure is used for the gadget represent-
ation,this must be a border structure as well.You won't use a
second image,so put a zero here:
dc.l 0 ;no new gadget displayed
The next pointer is to the text structure that should be output by
the gadget.If no text is needed,just put a zero here.You want to
use some text,however:
dc.l ggtext ;gadget text
Now comes a long word that determines which gadgets are
deactivated when this is activated.This function still doesn't
work right so put a zero here:
dc.l 0 ;no exclude
You'll set the next pointer to zero as well,because it is only
used for String and Proportional gadgets.For these gadgets,this is
a special structure to describe the characteristics of the gadget.
Its called SpecialInfo.
dc.l 0 ;no SpecialInfo
The next word contains the Gadget Identification (ID) number:
dc.w 1 ;gadget ID
Finally there is a long word that doesn't have any function,so put
a zero here:
dc.l 0 ;user data (ignore)
Thats it.Heres a quick overview of the gadget structure:
gadget1:
dc.l 0 ;no more gadgets
dc.w 40 ;X and
dc.w 50 ;Y position of gadget
dc.w 32 ;width and
dc.w 13 ;height of hit box
dc.w 4 ;flags:image,invert
dc.w $102 ;activation flags
dc.w 1 ;gadget type:boolean
dc.l image ;gadget image
dc.l 0 ;no new gadget displayed
dc.l ggtext ;gadget text
dc.l 0 ;no exclude
dc.l 0 ;no SpecialInfo
dc.w 1 ;gadget ID
dc.l 0 ;user data (ignore)
You've already prepared a structure that you can use for this
image.Now you need the text that appears under the gadget.
Since the gadget looks like a switch,label it "switch".The text
structure looks like this:
ggtext:
dc.b 1,0 ;colours
dc.b 1 ;mode
align
dc.w -8,14 ;X and Y position
dc.l 0 ;standard font
dc.l swtext ;pointer to text
dc.l 0 ;no more text
swtext:
dc.b "switch",0
align
Once you've typed this in,save it,assemble it and start again.You
can click the switch and cause it to be inverted.Click it again,
and it appears normal.
Now you can experriment with the structure.If you change the flag
from four to five,you can cause the gadget to be framed when it is
activated.Set the RELVERIFY bit(bit0:+1)in the Activation Flag
word.Then you can move the mouse pointer onto the object and press
the button.It is activated.Keep the mouse button pressed down and
move the mouse.Once you leave the hit box,the activation disapears
This way,you can avoid accidently activating a gadget.
Now you want to display the switch in an on state.This is easy.All
you need to do is produce another image structure,one for the on
state.You put this pointer in the long word right after the
pointer to the normal image structure.You can change the flag word
to six which causes a second image to be displayed when the gadget
is activated.
Here is the image structure for the switch in the one state.
image2:
dc.w 0,0 ;no offset
dc.w 32,13 ;32x13 pixels
dc.w 1 ;mode 1
dc.l imgdata2 ;pointer to the data
dc.b 2,1 ;same colours as before
dc.l 0 ;nothing else
imgdata2: ;data for switch in the On state
dc.l %00000000000000000000000000000000
dc.l %00000000011100000000000000000000
dc.l %00000000111110000011101001000000
dc.l %00000000111110000010101101000000
dc.l %00000000011110000010101011000000
dc.l %00000000000111000011101001000000
dc.l %00000000000011100000000000000000
dc.l %00000000000001110000000000000000
dc.l %00000000000111111111100000000000
dc.l %00000000001111111111110000000000
dc.l %00000000001111111111110000000000
dc.l %00000000000110000001100000000000
dc.l %00000000000000000000000000000000
Now the state of the object can be determined by looking at the
picture.If the gadget is activated,the switch is on.If not,the
switch is off.
Thats it for boolean gadgets.You can learn about the things you
did'nt touch with some experimentation.You want to get to the
string gadgets that also do some interesting things.
7.9.2.String Gadgets.
---------------------
Lets pretend you want a program to load data from the disk.To get
the user to enter the filename,you need to output text telling the
user to enter the name.Then you need to call an input routine to
evaluate the keyboard input.
Its easier and more elegant to use a String gadget.This function
allows for easy input and/or editingof short text.You have the
option of having the text framed.The Undo function can be used by
pressing the right <Amiga> key and a "Q",and the old contents of
the gadget,the old text are restored.
You can also vary the size of the text and the input field.If the
text is longer than the input field is wide,the text is moved back
and forth through the visible area when you move the cursor keys
or the normal input to the border.
You can also restrict input to just digits.This makes it posible
to accept numeric input.Intuition even converts the digit string
into a binary number.This saves the machine language programmer
some work.A specialized String gadget of this sort is called a
Integer gadget.
The structure is similar to the Boolean gadgets structure.There
are only two major differences:
The type word of the structure must be a four to declare that this
is a String gadget (STRGADGET).
The pointer to the SpecialInfo structure is needed.Put a pointer
to the StringInfo structure that you are going to design later
here.
The width and height entries in the gadget structure have a
different meaning than they had previously.They do declare the
area in which you can bring the mouse pointer to activate the
String gadget.However,it is also used for representation of text.
These values determine the size of the box in which the text is
output.You should surround the box with a border using the Border
function,so that the user can see where it is.
If the text is longer than the box,only a portion of it is seen on
the screen.You can move through the area by entering text or using
the left/right cursor keys to move through the box.The characters
that are entered are inserted at the cursor position,so the rest
of the text is shifted by one character when you are on the right
edge of the input area.The following functions can be used for
editing this text:
Cursor key left/right
Moves the cursor over the text thats already on hand.Moves
the text through the Container.
Cursor keys with <Shift>
Puts the cursor on the beginning or the end of the text.
Deletes the character under the cursor.
<Backspace>
Deletes the character to the left of the cursor.
<Return>
Ends text input.
<Amiga>right+"Q"
This is the Undo function.It replaces the text with the
original contents.
The StringInfo structure only has a few entries:
First theres a pointer to the memory area that is used to store
the text that is input.The memory buffer must be big enough to
handle all the text entered.
strinfo:
dc.l strpuffer ;pointer to text buffer
Next comes the pointer to the Undo buffer.This pointer and this
buffer are only needed if you want the Undo function.If you do,you
must have a buffer that is at least as big as your text buffer.
Every time the string gadget function is called,the text buffers
contents are copied into this buffer.To get the old contents back,
just press the right <Amiga>key and the "Q"key.The contents of the
Undo buffer are copied back to the text buffer.If you use several
string gadgets in a program,you can use the same Undo buffer for
all of them,since only one string gadget is used at one time.
dc.l undo ;pointer to undo buffer
The following word contains the cursor position in the text.You
should set this word to zero,so that the user can see the
beginning of the text when the string gadget appears.
dc.w 0 ;cursor position
The next word contains the maximum number of characters that can
be input.If you type one more than this number of characters,the
screen blinks,to show that you can't enter a longer input string.
The number of characters and the reserved space for the input
field don't have to agree,since text can be scrolled by typing.
dc.w 10 ;maximum # of characters
The following word tells at which character of text in the buffer,
the output to the box should begin.You should put a zero here,so
that the user can see the beginning of the text.
dc.w 0 ;output text from this character
The next five words are used by Intuition,so you don't have to
initialize them.Just put zeros here.The words contain the
following information:
dc.w 0 ;character position in undo buffer
dc.w 0 ;number of chars in text buffer
dc.w 0 ;number of chars visible in box
dc.w 0 ;horizontal box offset
dc.w 0 ;vertical box offset
The next two long words are initialized by Intuition as well:
dc.l 0 ;pointer to rastport
dc.l 0 ;long word with value of the input
; ;(for integer gadgets)
The final entry is a pointer to the keyboard table that is used if
the ALTKEYMAP flag of the gadget is set.
dc.l 0 ;standard keyboard table
Heres a quick overview of the StringInfo structure:
strinfo:
dc.l strpuffer ;pointer to text buffer
dc.l undo ;pointer to undo buffer
dc.w 0 ;cursor position
dc.w 10 ;maximum # of characters
dc.w 0 ;output text from this character
dc.w 0 ;character position in undo buffer
dc.w 0 ;number of chars in text buffer
dc.w 0 ;number of chars visible in box
dc.w 0 ;horizontal box offset
dc.w 0 ;vertical box offset
dc.l 0 ;pointer to rastport
dc.l 0 ;long word with value of input
; ;(for integer gadgets)
dc.l 0 ;standard keyboard table
Here are the text and undo buffers:
strpuffer:
dc.b "Hello!",0,0,0
undo:
dc.l 0,0,0,0
align
Once you've entered these lines,you can either alter the old
gadget structure or build a new one.We'd recommend building
another gadget structure so that you can have the switch and use
it later.Change the first pointer in the old structure from zero
to "gadget1"and insert this new structure.Here is an example
strucure for the string gadget.It as the following entries:
gadget1: ;*structure for string gadget
dc.l 0 ;no more gadgets
dc.w 20,80 ;position
dc.w 80,10 ;width and height of box
dc.w 0 ;flags:normal
dc.w 2 ;activation($802 for long int)
dc.w 4 ;type:string gadget
dc.l border ;pointer to border
dc.l 0 ;no drawing selected
dc.l 0 ;no text
dc.l 0 ;no exclude
dc.l strinfo ;pointer to stringinfo structure
dc.w 2 ;gadget ID
dc.l 0 ;no user data
border: ;*border for box frame
dc.w 0,0 ;no offset
dc.b 3,3 ;red colour
dc.b 0 ;mode:JAM1
dc.b 5 ;5 X,Y pairs
dc.l coord ;pointer to coordinates table
dc.l 0 ;no more structures
coord: ;*coordinates for frame
dc.w -2,-2 ;start in upper left corner
dc.w 80,-2 ;upper right
dc.w 80,9 ;lower right
dc.w -2,9 ;lower left
dc.w -2,-2 ;back to beginning
This data causes a red rectangle,the border,to appear around the
"Hello!"text.You can change the text by clicking in the field and
editing once the cursor appears.If you type something wrong,you
can use the undo function(the right <Amiga> key and the Q key),to
get "Hello!"back.
Once you've done some typing and deactivated the gadget by
pressing <Return> or by clicking outside the field (cursors
disapear),you can terminate the program.
Change the activation flag to $802 and the "strbuffer"to "dc.l
0,0,0,0",assemble,and then start the program.You can type in the
string gadget once it has been activated,but you can only enter
digits.The screen blinks if you enter letters.
Enter a number,and then end the program after deactivating the
gadget.If you look at the stringinfo structure you can look at the
value of the number you input(in hex)in the eight long word.
After looking at boolean,text and numeric input to gadgets,lets
look at Proportional gadgets which allow the user to enter analog
values by moving a symbol.
7.9.3.Proportional Gadgets.
---------------------------
You've seen the advantages of slider devices over knobs that you
turn,maybe on a hifi,maybe on a toaster,but certainly someplace.
Its easier to tell the state the item is in with a slider,
especially if several such devices are next to each other(for
example graphic equalizers).You can represent sliders on the
Amigas screen and work with them with the mouse.This offers a nice
way to represent information graphically in your programs.
You can do this with gadgets.Using Proportional gadgets,you can
put a symbol in a frame and move horzontally and/or vertically.The
size of the frame and the slider can be variable size,so that the
frame size is relative to the screen size so when the window
changes size,it will also.The slider can be set up so that its
size in the grows or shrinks.
These are best seen via example and experimentation.(The
posibilities mentioned do not form a complete list by any stretch
of the imagination.)You want to set up a simple Proportional
gadget that can be moved horizontally.
You need a gadget structure that as the same form as others.To
show the differences,heres a complete example structure for your
gadget.You can connect this gadget to the other one,by changing
the first long word in the last structure to "dc.l gadget2".
gadget2: ;*structure for Proportional gadget
dc.l 0 ;no more gadgets
dc.w 150,30 ;position
dc.w 100,10 ;width and height of frame
dc.w 4 ;flags:GADGIMAGE
dc.w 2 ;activation:GADGIMMEDIATE
dc.w 3 ;type:proportional gadget
dc.l mover ;pointer to slider data
dc.l 0 ;no select structure
dc.l 0 ;no text
dc.l 0 ;no exclude
dc.l propinfo ;pointer to propinfo structure
dc.w 3 ;gadget ID
dc.l 0 ;no user data
You see two special features.Use an image structure for the mover
and put a pointer to another structure in the spot for the Special
Info pointer.
First,lets look at the "mover"structure,the sliders image
structure.Heres an example of this structure:
mover: ;*structure for slider image
dc.w 0,0 ;no offset
dc.w 16,7 ;16x7 pixels big
dc.w 1 ;one bit plane
dc.l moverdata ;pointer to image data
dc.b 1,0 ;colour:white
dc.l 0 ;don't continue
moverdata: ;*image data for mover
dc.w %0111111111111110
dc.w %0101111111111010
dc.w %0101011111101010
dc.w %0101010110101010
dc.w %0101011111101010
dc.w %0101111111111010
dc.w %0111111111111110
Up till now,there was'nt anything new.Now lets look at the
PropInfo structure that describes the properties of the
Proportional gadget.
The structure starts with a flag word that contains the following
bits:
Bits Value Name Meaning
-----------------------------------------------------------------
0 1 AUTOKNOB Mover is set up automatically
1 2 FREEHORIZ Allows horizontal movement
2 4 FREEVERT Allows vertical movement
3 8 PROPBORDERLESS Turns off automatic framing
8 $100 KNOBHIT Set when the mover is touched
You can set the first four bits to get the representation that you
want.Bit 8 is set by Intuition when the mover is clicked with the
mouse pointer.
Bit 0,AUTOKNOB,allos for the simplest sort of Proportional gadget.
If this bit is set,no move data are used for the mover image.
Instead,a white mover is generated that is adjusted to the size of
the box and the values to be represented.When you use this slider
to represent the displayed lines in a long text of a program,the
displayed lines are a percentage of the total text.The
relationship between the total number of lines and the lines shown
is represented by an AUTOKNOB as the relationship between the
frame and the slider.The bigger the percentage,the bigger the
slider is.You don't want to work with this though,even though it
is simple and interesting,because a simple white button isn't
particularly attractive.If you experiment with it,make sure that
the pointer to the image data points to a four word long buffer
that Intuition can use to store values.The buffer is of the
following form:
buffer:
dc.w 0 ;X position of the slider in the box
dc.w 0 ;Y position in the box
dc.w 0 ;width of slider
dc.w 0 ;height of slider
Leys look at the PropInfo structure.Since you're not using
AUTOKNOB and wish to allow horizontal movement only,put two in as
a flag:
propinfo:
dc.w 2 ;flags:FREEHORIZ
In the next two words of the structure,the horizontal (HorizPot)
and vertical (VertPot) position of sliders are stored.A value of
zero means left or upper,while the value $FFFF means right or
lower.The value that results from movement is in this range.You
set these values to zero at the start of the program.After moving
the mouse,there is different values here.
dc.w 0,0 ;X and Y position of the slider
Next come two words which determine the size of the AUTOKNOB or
the step size of the slider(this determines how far the slider
moves when you click in the box next to the slider).These words
are called HorizBody (horizontal movement) and VertBody (vertical
movement).
dc.w $ffff/16 ;horizontal step size:1/16
dc.w 0 ;no vertical movement
;The next six words are initialized by Intuition.
dc.w 0 ;box width
dc.w 0 ;box height
dc.w 0 ;absolute step size horizontal
dc.w 0 ;and vertical
dc.w 0 ;left border of box
dc.w 0 ;upper border of box
Thats it.Heres a quick overview of the PropInfo structure:
prpoinfo:
dc.w 2 ;flags:FREEHORIZ
dc.w 0,0 ;X and Y position of slider
dc.w $ffff/16 ;horizontal step size:1/16
dc.w 0 ;no vertical movement
dc.w 0 ;box width
dc.w 0 ;box height
dc.w 0 ;absolute step size horizontal
dc.w 0 ;and vertical
dc.w 0 ;left border of box
dc.w 0 ;upper border of box
Once you've typed this in,you can start the program and try it
out.
You can also try vertical movement by setting the flag word equal
to six,the vertical step size to $FFFF/10,and the height of the
gadget to 80,for the example.To try out the AUTOKNOBs,change the
flag value to seven.
7.10.Example Program.
---------------------
Here is a complete example program using what you have learned in
this chapter:
;7_Intuition.asm
;** Demo-Program for working with Intuition **
movescreen =-162
openscreen =-198
closescreen =-66
openwindow =-204
closewindow =-72
autorequest =-348
setmenustrip =-264
clearmenustrip=-54
printitext =-216
drawimage =-144
drawborder =-108
displaybeep =-96
closelibrary =-414
openlib =-408
execbase = 4
getmsg =-372
joy2 =$dff0c
fire =$bfe001
;!!!when > 500kb !!!
;org $40000
;load $40000
; or use AssemPro to place in CHIP RAM
;!!!!!!!!!!!!!!!!!!!!!!!
run:
bsr openint
bsr scropen
bsr windopen
bsr setmenu
bsr print
lea border,a1
move #22,d0
move #30,d1
bsr borderdraw
bsr draw
bsr request
loop:
move.l execbase,a6
move.l windowhd,a0
move.l 86(a0),a0 ;user port
jsr getmsg(a6)
tst.l d0
beq loop ;no event
move.l d0,a0
move.l $16(a0),msg ;event:LO=item,HI=Event
move.l msg,d6 ;to test
move.l d6,d7
lsr #8,d7
lsr #3,d7 ;sub menu point in D7
clr.l d5
roxr #1,d6
roxl #1,d5 ;menu number in D5
and.l #$7f,d6
cmp #$7f,d6 ;no menu point?
beq loop ;no:continue
lsr #4,d6 ;menu point in D6
cmp #1,d6 ;point 2?
bne no1
move,l intbase,a6
move.l screenhd,a0
jsr displaybeep(a6)
no1:
cmp #0,d6
bne loop
ende:
bsr clearmenu
bsr windclose
bsr scrclose
bsr closeint
rts
openint:
move.l execbase,a6
lea intname,a1
jsr openlib(a6)
move.l d0,intbase
rts
closeint:
move.l execbase,a6
move.l intbase,a1
jsr closelibrary(a6)
rts
scropen:
move.l inbase,a6
lea screen_defs,a0
jsr openscreen(a6)
move.l d0,screenhd
scrclose:
move.l inbase,a6
move.l screenhd,a0
jsr closescreen(a6)
rts
scrmove:
move.l intbase,a6
move,l screenhd,a0
jsr movescreen(a6)
rts
windopen:
move.l intbase,a6
lea windowdef,a0
jsr openwindow(a6)
move.l d0,windowhd
rts
windclose:
move.l intbase,a6
move.l windowhd,a0
jsr closewindow(a6)
rts
request:
move.l windowhd,a0
lea btext,a1
lea ltext,a2
lea rtext,a3
move.l #0,d0
move.l #0,d1
move.l #180,d2
move.l #80,d3
move.l intbase,a6
jsr autorequest(a6)
rts
setmenu:
lea mentab,a0 ;pointer to text pointer in A0
lea menu,a1 ;pointer to menu field in A1
move #10,d1 ;menu position = 10
menuloop:
clr.l d2 ;menu point-Y=0
move.l a1,a2 ;save pointer
tst.l (a0)
beq setmenu1 ;end
clr.l (a1)+
move d1,(a1)+
add.l #70,d1
move.l #50,(a1)+
move.l #$a0001,(a1)+
move.l (a0)+,(a1)+ ;menu title
lea 12(a1),a3
move.l a3,(a1)+ ;menu point
clr.l (a1)+
clr.l (a1)+
itemloop:
tst.l (a0) ;last one?
beq menuend ;yes
lea 54(a1),a3
move.l a3,(a1)+ ;pointer to next point
move.l d2,(a1)+ ;X/Y
add #10,d2
move.l #$5a000a,(a1)+ ;width/height
move #$52,(a1)+
clr.l (a1)+
lea 16(a1),a3
move.l a3,(a1)+ ;text structor-pointer
clr.l (a1)+
clr.l (a1)+
clr.l (a1)+
move #$1,(a1)+ ;text-structor set
clr (a1)+
move.l #$50003,(a1)+
clr.l (a1)+
move.l (a0)+,(a1)+ ;text pointer
clr.l (a1)+
bra itemloop ;next point...
menuend:
clr.l -54(a1)
tst.l (a0)+
tst.l (a0) ;still in menu?
beq setmenu1 ;no:ready
move.l a1,(a2) ;pointer to next menu
bra menuloop ;and continue
setmenu1:
move.l intbase,a6
move.l windowhd,a0
lea menu,a1
jsr setmenustrip(a6)
rts
clearmenu:
move.l intbase,a6
move.l windowhd,a0
jsr clearmenustrip(a6)
rts
print:
move.l intbase,a6
move.l windowhd,a0
move.l 50(a0),a0
lea ggtext,a1
move.l #30,d0 ;X
move.l #16,d1 ;Y
jsr printitext(a6)
rts
draw:
move.l intbase,a6
move.l windowhd,a0
move.l 50(a0),a0
lea image,a1
move.l #200,d0
move.l #100,d1
jsr drawimage(a6)
rts
borderdraw:
move.l intbase,a6
move.l windowhd,a0
move.l 50(a0),a0
jsr drawborder(a6)
rts
screen_defs:
dc.w 0,0
dc.w 640,200
dc.w 4
dc.b 0
dc.b 1
dc.w $800
dc.w 15
dc.l 0
dc.l tite1
dc.l 0
dc.l 0
windowdef:
dc.w 10,20
dc.w 300,150
dc.b 0,1
dc.l $300
dc.l $100f
dc.l gadget
dc.l 0
dc.l windname
screenhd:
dc.l 0
dc.l 0
dc.w 200,40,600,200
dc.w $f
btext:
dc.b 3,3
dc.b 0
align
dc.w 10,10
dc.l 0
dc.l bodytxt
dc.l 0
bodytxt:dc.b "Requester-Text",0
align
ltext:
dc.b 3,1
dc.b 0
align dc.w 5,3
dc.l 0
dc.l lefttext
dc.l 0
lefttext: dc.b "left",0
align
rtext:
dc.b 0,1
dc.b 0
align dc.w 5,3
dc.l 0
dc.l righttext
dc.l 0
righttext: dc.b "right",0
align
tite1: dc.b "User Screen",0
windname: dc.b "Window-Title",0
align windowhd: dc.l 0
intbase:dc.l 0
intname:dc.b "intuition.library",0
align msg:dc.l 0
mentab:
dc.l menu1
dc.l mp11,np12,mp13,mp14,mp15,mp16,mp17,mp18,mp19,0
dc.l menu2
dc.l mp21,mp22,mp23,0
dc.l menu3
dc.l mp31,mp32,0
dc.l menu4,mp41,0
dc.l 0
menu1: dc.b "Menu 1",0
mp11: dc.b "Point 11",0
mp12: dc.b "Point 12",0
mp13: dc.b "Point 13",0
mp14: dc.b "Point 14",0
mp15: dc.b "Point 15",0
mp16: dc.b "Point 16",0
mp17: dc.b "Point 17",0
mp18: dc.b "Point 18",0
mp19: dc.b "Point 19",0
menu2: dc.b "Menu 2",0
mp21: dc.b "End!",0
mp22: dc.b "Beep",0
mp23: dc.b "Point 23",0
menu3: dc.b "Menu 3",0
mp31: dc.b "Point 31",0
mp32: dc.b "Point 32",0
menu4: dc.b "Menu 4",0
mp41: dc.b "Point 41",0
align
gadget:
dc.l gadget1
dc.w 20,80,80,10
dc.w 0
dc.w $2 ;activation,$802 for longint
dc.w 4
dc.l border
dc.l 0
dc.l 0
dc.l 0
dc.l strinfo
dc.w 2
dc.l 0
border:
dc.w 0,0
dc.b 1,0,0
dc.d 5 ;XY-pair
dc.l koord
dc.l 0
koord:
dc.w -2,-2,80,-2,80,9,-2,9,-2,-2
strinfo:
dc.l strpuffer
dc.l undo
dc.w 0 ;cursor position
dc.w 10 ;max.char
dc.w 0
dc.w 0,0,0,0,0
dc.l 0,0,0
strpuffer:
dc.b "Hello!",0,0,0
undo: dc.l 0,0,0
align
gadget1:
dc.l gadget2 ;more gadget
dc.w 40,50,32,13
dc.w $6 ;flags:invert
dc.w $103 ;activate
dc.w 1 ;gadget type
dc.l image ;gadget image
dc.l image2 ;select gadget
dc.l ggtext ;gadget text
dc.l 0 ;no exclude
dc.l 0 ;special info
dc.w 1 ;ID
dc.l 0 ;user data
ggtext:
dc.b 1,0,1
align
dc.w -8,14
dc.l 0
dc.l swtext
dc,l 0
swtext:
dc.b "Switch",0
align
image:
dc.w 0,0
dc.w 32,13
dc.w 1
dc.l imgdata
dc.b 2,1
dc.l 0
image2:
dc.w 0,0
dc.w 32,13
dc.w 1
dc.l imgdata2
dc.b 2,1
dc.l 0
imgdata:
dc.l 0
dc.l %00000000011100000000000000000000
dc.l %00000000111110000011101001000000
dc.l %00000000111110000010101101000000
dc.l %00000000011110000010101011000000
dc.l %00000000000111000011101001000000
dc.l %00000000000011100000000000000000
dc.l %00000000000001110000000000000000
dc.l %00000000000111111111100000000000
dc.l %00000000001111111111110000000000
dc.l %00000000001111111111110000000000
dc.l %00000000000110000001100000000000
dc.l 0
imgdata2:
dc.l 0
dc.l %00000000000000000000111000000000
dc.l %00011101110111000001111100000000
dc.l %00010101000100000001111100000000
dc.l %00010101100110000001111000000000
dc.l %00011101000100000011100000000000
dc.l %00000000000000000111000000000000
dc.l %00000000000000001110000000000000
dc.l %00000000000111111111100000000000
dc.l %00000000001111111111110000000000
dc.l %00000000001111111111110000000000
dc.l %00000000000110000001100000000000
dc.l 0
gadget2:
dc.l 0
dc.w 150,30,100,50
dc.w 5
dc.w 2
dc.w 3 ;prop.gadet
dc.l mover ;border
dc.l 0,0,0
dc.l specinfo
dc.w 3
dc.l 0
specinfo:
dc.w 6 ;flags:free horiz
dc.w 0,0
dc.w $ffff/10,$ffff/5
dc.w 0,0,0,0,0,0
mover:
dc.w 0,0,16,7
dc.w 1
dc.l moverdata
dc.b 1,0
dc.l 0
moverdata:
dc.w %0111111111111110
dc.w %0101111111111010
dc.w %0101011111101010
dc.w %0101010110101010
dc.w %0101011111101010
dc.w %0101111111111010
dc.w %0111111111111110
menu:blk.w 500
end