home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
dirs
/
rexxintuition_463.lzh
/
RexxIntuition
/
RexxIntuition.doc
< prev
next >
Wrap
Text File
|
1991-03-09
|
67KB
|
1,403 lines
THE RX_INTUI.LIBRARY DOC
------------------------
1. Copyright and Release Information
2. What's the rx_intui.library?
3. GetScreen()
4. GetWindow()
5. EndWindow()
6. EndScreen()
7. AddMenu()
8. AddItem()
9. AddSub()
10. SetMenu()
11. FreeMenu()
12. Text()
13. Erase()
14. SetDraw()
15. OpFont(), SetFont(), ClsFont()
16. AddGadg()
17. WaitMsg()
18. ModIDCMP()
19. SetTime()
20. ModGadg()
21. GInfo()
22. OnOffGadg()
23. MoveView()
24. Peek() and Poke()
25. RedrawWind()
26. FBox()
27. Line()
28. Pixel()
29. Input()
30. MsgOne() and MsgThree()
31. Title()
32. IFFLoad() and IFFSave()
33. Color()
34. Print()
35. FileIO Section (dissidents File Requester)
A. Demo scripts
B. Rexx Error Returns
C. Final Notes
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
1) Copyright and Release Information
The rx_intui.library and its support files (including this document) are
copyright 1990 by Jeff Glatt of dissidents software. This library and its files
may be freely distributed as long as this copyright notice is intact. Further-
more, if you use this tool, you must never say anything bad about Jeff Glatt,
even if your experimentations with the library result in any aggravation and
provoke pronouncements of extremely naughty words.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
2) What's the rx_intui.library? (Or when is this guy gonna do something with
video? Isn't that why everyone bought an Amiga?)
The rx_intui.library is an ARexx function library. It allows an ARexx macro
script to open screens/windows, and attach gadgets, menus, and open requesters
in those windows. Furthermore, it allows an ARexx macro to interact with
Intuition (ie do an "IDCMP loop"), thus interacting with a user in a familiar,
and friendly windowed environment. In essense, it allows a programmer to write
a Rexx macro with access to the Amiga's intuition library that other languages
offer, but which Bill Hawes' ARexx server does not include.
There are a few other things that this library can do, but those are its
main features.
The library cannot be used without Bill Hawes' ARexx package (available
from several distributors).
Since this is a Rexx function library, any ARexx macro script has automatic
access to the library's functions once the library is added to ARexx. (This can
be accomplished using the dissidents FuncLib program. Copy "rx_intui.library"
to your LIBS: drawer. Consult FuncLib.doc for use of that program.)
FuncLib rx_intui.library 0 -30 0
This library requires the dissidents FileIO (requester.library) library.
This is readily obtained on Fred Fish PD disks, or directly from dissidents.
Otherwise, it should be included on this disk in the FileIO drawer. Copy it to
LIBS:
For certain other functions, this library requires other dissidents libs,
but only for those particular functions (as noted).
There are many example scripts included, and a section of this document
describes them.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
3) GetScreen()
To open a custom screen, you use this function:
screen = GetScreen(title,mode,left,top,width,height,depth)
title - the text displayed in the screen's titlebar (default = NONE)
mode - the screen's ViewModes (default = HIRES) as follows:
LORES = 0, HIRES = 32768, LACE = 4, HAM = 2048, HALFBRITE = 128
DUALPF = 1024, GENLOCK VIDEO = 2, SPRITES = 16384, PFBA = 64
Simply add up the ones that you want.
left - the upper left x position (default = 0)
top - the upper left y position (default = 0)
width - the width of the screen in pixels (default = Gfx's Normal Columns)
height - the height of the screen in pixels (default = Gfx's Normal Rows)
depth - the number of bitplanes (ie colors) (default = 3, ie 8 colors)
If you don't specify an argument, (ie just the comma without any value),
then you'll get a default value. For example, here I open a HIRES 16 color
screen with a title of "My Screen". Note that the default width and height will
be set by the lib, and takes into account PAL as well as Interlace (if I
specify LACE mode).
screen = GetScreen('My Screen',,,,,,4)
This returns the address of the custom screen (which will be passed to other
lib functions), or '' if the screen didn't open.
For all other lib functions that require the screen address to be passed,
if '', then that function will do nothing or ignore this argument. This insures
that if your screen doesn't open, you can't accidentally perform operations on
a null pointer (ie all lib functions are always "safe" to call).
The lib will clip the screen's width and height no larger than the Normal
Columns and Rows set by the graphics library.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
4) GetWindow()
To open a window, you use this function:
window = GetWindow(title,screen,left,top,width,height,extra,IDCMP,windFlags)
title - the text to appear in the window titlebar
screen - the screen upon which to open this window (default = WorkBench)
left - the upper left x position (default = 0)
top - the upper left y position (default = 0)
width - the width of the window in pixels (default = screen's width)
height - the height of the window in pixels (default = screen's height)
extra - these are the extra IDCMP flags for the window as follows:
CONVERT_RAW = 8 RAWKEY are converted to special COOKED KEY events
NO_SLEEP = 16 If no msgs at window, returns instead of sleeps
GIMME_UP = 32 Let's you hear about UP mousebutton events
NO_COLLECT = 64 Reports each MOUSEMOVE instead of collecting them
GIMME_MOVE = 128 Allows you to hear about MOUSEMOVE events
Simply add up the ones that you want. (default = none)
IDCMP - the classes of Intuition messages which you want to receive
SIZEVERIFY = 1, NEWSIZE = 2, REFRESHWINDOW = 4, MOUSEBUTTONS = 8
MOUSEMOVE = 16, GADGETDOWN = 32, GADGETUP = 64, REQSET = 128
MENUPICK = 256, CLOSEWINDOW = 512, RAWKEY = 1024, REQVERIFY = 2048,
REQCLEAR = 4096, MENUVERIFY = 8192, NEWPREFS = 16384, DISKINSERTED
= 32768, DISKREMOVED = 65536, WBMESSAGE = 131072, ACTIVEWINDOW =
262144, INACTIVEWINDOW = 524288, DELTAMOVE = 1048576, TIMEOUT =
4194304 (TIMEOUT allows the WaitMsg routine to return after a
certain amount of time without user activity.)
Simply add up the ones that you want. (default = MOUSEBUTTONS,
GADGETDOWN, GADGETUP, MENUPICK, CLOSEWINDOW, and if you add a
proportional gadget MOUSEMOVE).
windFlags - the window flags as follows:
SIZE = 1, DRAG = 2, DEPTH = 4, CLOSE = 8, SIZEBRIGHT = 16, SIZE-
BOTTOM = 32, SIMPLE_REFRESH = 64, SUPER_BITMAP = 128, OTHER_REF =
192, BACKDROP = 256, REPORTMOUSE = 512, GIMMEZERO = 1024, BORDER-
LESS = 2048, ACTIVATE = 4096, RMBTRAP = 65536, NOCARE_REF = 131072,
SMART_REFRESH = 0
Simply add up the ones that you want. (default = SMART_REFRESH,
SIZE, DRAG, DEPTH, CLOSE, ACTIVATE, REPORTMOUSE)
If you don't specify a parameter, then you'll get the default value. For
example, here I open a window with no title on WorkBench. The lib will open
the screen to full Workbench width and height (taking PAL into account).
I get the default IDCMP and system gadgets.
window = GetWindow(,,,,,,,,,)
This returns the address of the window (which will be passed to other
lib functions), or '' if no window opened. If passed a screen of '', then it
opens on WorkBench.
For all other lib functions that require the window address to be passed,
if '', then that function will do nothing.
Note that when opening on WorkBench, this library expects the system font
to be an 8 by 8 pixel font. If you open a window on a custom screen, the user's
Preferences font setting no longer has to be set to an 8 by 8 font.
The lib will automatically clip the window's width and height to no larger
than the screen upon which it is opened.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
5) EndWindow()
To close an opened window, simply call
err = EndWindow(window)
where window is the address returned by GetWindow(). This automatically
frees all menus and gadgets that you attached to the window. If window = '',
then this does nothing.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
6) EndScreen()
To close an opened screen, simply call
err = EndScreen(screen)
where screen is the address returned by GetScreen(). You should first close
all windows open on the screen. If screen = '', then this does nothing.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
7) AddMenu()
To add a menu to an opened window, use this
menu = AddMenu(window,text,leftedge,width)
window - the window address as returned by GetWindow()
text - the name of the menu (placed in the titlebar)
leftedge - how many pixels from the left window border to place the menu
width - the width of the menu (in pixels)
This will add a new menu to the window, so that you can start adding menu
items to it. The first menu attached to the window will be menu #0. The second
menu added will be #1, etc.
You should make the width as big as the width of the largest item name to be
added to the menu, or the menu name itself (whichever is bigger). To calculate
the width of an item or menu name, add 8 pixels for each character in the name.
For example, if your menu name is "Project", the width would be 7 chars * 8 =
15 pixels wide. If you don't specify the width or leftedge, the library sets
the width to the menu's name, and places it after the last added menu (ie
automatically places the menu in a sensible position).
For example, here I add a menu called "Blort" and let the lib position it:
menu0 = AddMenu(window,'Blort',,)
This returns the address of the added menu. If it can't be added, '' is
returned. This does nothing if window is ''.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
8) AddItem()
item = AddItem(menu,text,flags,exclude,IDCMP,commseq,window)
This adds an item to a menu. The first item added is Item #0. The second
item added is #1, etc. The lib automatically positions the item in the menu.
You can add several items to a menu.
menu - the menu that the item is added to, as returned by AddMenu()
text - the item's name
flags - the item's flags are as follows:
CHECKIT = 1 (Put a checkmark before the item when it's selected)
CHECKED = 256 (Put the checkmark there now)
TOGGLECHECK = 8 (Each time its selected, toggle the checkmark)
COMMSEQ = 4 (Allow a Right Amiga key combo to select the item)
HIGHBOX = 128 (Highlight by boxing the item)
HIGHNONE = 192 (Don't highlight the item)
Simply add up the ones you want. (default = none of the above)
exclude - a mask of the other items to exclude when this one is selected
(default = no exclude)
IDCMP - Extra flags that specify how the item effects IDCMP:
ISSUE CLOSE = 128 (This item sends a CLOSEWINDOW message when
selected)
OK = 1 (CLOSEWINDOW state is OK as opposed to CANCEL)
commseq - the character to use in conjunction with the right Amiga key
(default = no commseq). Note that you should also set the COMMSEQ
flag as well.
window - the window in which the menu was added, as returned by GetWindow()
This returns the address of the added item so that you can add subitems to
it. If it can't be added, '' is returned. If the menu or window = '', then this
does nothing.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
9) AddSub()
sub = AddSub(item,text,flags,exclude,IDCMP,commseq,window)
This adds a subitem to an item. The first sub added is Sub #0. The second
sub added is #1, etc. The lib automatically positions the subitem by its item.
You can add several subitems to an item. The args are the same as AddItem()
except that you pass the item to which to add the Sub, as returned by AddItem.
This returns the address of the added subitem. If it can't be added, '' is
returned. If the item or window = '', then this does nothing.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
10) SetMenu()
oldMenu = SetMenu(window,newMenu)
window - the window to set the new menu strip in
newMenu - the address of menu #0 of the strip to be installed (if '' or no
arg, then a new strip is not installed)
A menu strip is a series of menus that you added to the window.
This removes any menu strip that is presently installed in the window, and
returns the address of its menu #0. Note that the old menu strip is not freed.
If no previous strip was installed, it returns ''.
If you want to make several different menu "strips" for a window, and swap
them at different times, use this function. The technique is to make menus
using AddMenu(), AddItem(), and AddSub(). Save the address of the first menu
(#0) installed. This is also the address of your strip since all the menus
added together are linked to each other in the order that they were added.
Now, call
oldMenu = SetMenu(window,,)
This clears out the window's strip so that you can now make a new strip of
menus. Save the address of this new strip's menu #0. Now, when you want to
swap strips, pass the address of the strip to install via SetMenu. Later, you
will need to free the strips.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
11) FreeMenu()
menu = FreeMenu(window)
When you EndWindow(), the menu strip that is presently attached to the
window is automatically freed (so you don't have to use this function if you're
using only 1 menu strip.) On the other hand, any other strips that you made
which are not currently attached, must be eventually freed using FreeMenu().
Pass the address of menu #0 of the strip to free (ie the address of the strip).
Technique: FreeMenu the current menu, then SetMenu/FreeMenu for every other
menu strip that you created. Then, you can close the window.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
12) Text()
err = Text(text,window,x,y)
This prints the passed text to the window at position (x,y).
text - the text to print
window - the window in which to print
x - x position in pixels
y - y position in pixels
Uses the current penA color for the text, and the penB color for the back-
ground behind the text, and the current drawmode. If window = '', it does
nothing. If text = '' or no arg, then it just moves the pen position to (x,y).
If x or y = '' or no arg, then that position is not changed. (Note that no
args for both x and y allows you to print text from where you last left off.)
The standard text font height is 8 pixels (for Topaz 8).
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
13) Erase()
err = Erase(charLength,window,x,y)
This erases an area of the current text height at position (x,y). charLength
is the number of characters to erase. The other args are as in Text().
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
14) SetDraw()
err = SetDraw(window,PenA,PenB,DrawMode)
window - in which to set the pens and mode
PenA - the color # used for the text or line drawing (generally)
PenB - the color # used for the background behind the text or line
DrawMode - determines how the pens are used:
JAM1 = 0 (Use only PenA), JAM2 = 1 (Use both pens), COMPLEMENT =
2 (Use complementary color #s), INVERSVID = 4 (reverse the pens)
You should set the pens and drawmode before you start calling Text() or
Erase() (unless you want the defaults of JAM1, PenA = 3, and PenB = 0). You
change text/drawing colors and modes using this function.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
15) OpFont(), SetFont(), ClsFont()
FontPtr=OpFont(style,size,fontname)
style - 0=NORMAL, 1=BOLD, 2=ITALICS, 4=UNDERLINE
size - the font height (i.e. 8 pixels)
fontname - name of the font to open (i.e. garnet.font)
Opens the passed font of the specified name, size, and style. Returns the
FontPtr or '' if error. If size = '', defaults to 8. If style = '', defaults
to NORMAL. You must open a font before you can SetFont(). This does not change
the window's current font or style. Note that you can combine styles. For
example, if you want BOLD and ITALICS, specify style = 1+2. If the fontname
is omitted, this returns the Topaz 8 default FontPtr (for use with SetFont).
You should NEVER ClsFont() on the default Topaz 8!
err=SetFont(window,style,FontPtr)
window - in which to set the font
style - 0=NORMAL, 1=BOLD, 2=ITALICS, 4=UNDERLINE
FontPtr - as returned from OpFont()
Sets the passed FontPtr as the current. If FontPtr = '', doesn't change the
font. Also sets the passed style. If style = '', defaults to NORMAL. By passing
only the style, you can change styles without changing the font.
FontPtr=ClsFont(window,FontPtr)
Closes the passed font and returns a NULL string. You should reassign the
return to the same variable as passed so that multiple ClsFonts are safe.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
16) AddGadg()
gadg=AddGadg(window,type,text,left,top,width,height,activation,ID,IDCMP,extra)
This adds a gadget to the opened window at the specified position. You can
add Proportional, String, or Boolean gadgets. Proportional gadgets are laid on
their side (along the x axis) with a knob that moves left or right and a con-
tainer of the size specified by width and height. String and Boolean gadgets
have a border around them of the size specified by width and height (in pixels).
Gadgets are placed at a position of pixel offsets from the top and left of
the window's upper left corner (left = 0, top = 0). The passed text is printed
to the left of the prop and string gadgets (so be sure to calculate the text
width using Number of characters * 8, and add this to your desired left posi-
tion.) For Bool gadgets, the text is printed (and centered) inside the gadget
border (so be sure to make the gadget width as big as the text width).
window - in which to place the gadget (If '', then this does nothing)
type - BOOL = 1, PROP = 3, STRING = 4
text - string associated with the gadget. If no arg, then no gadg text
left - # of pixels over from the left window border
top - # of pixels down from the top of window
width - the width of the gadget. For Bools, make this at least as big
as your text width (ie Number of characters * 8). For Props or
strings, any size will do (however long you want the gadg to be)
height - The height of the gadget. This should be at least 12 pixels
activation - What intuition sends when the user selects, uses, and de-
selects the gadget:
RELVERIFY = 1 (Send a message when the user is done using it)
IMMEDIATE = 2 (Send a message when user first starts using it)
ENDGADGET = 4 (Send a REQCLEAR IDCMPspec when done)
RIGHTBORD = 16 (Place the gadg inside the window right border)
LEFTBORD = 32 (Place the gadg inside the window left border)
TOPBORD = 64 (Gadg in top border, title bar)
BOTTOMBORD = 128 (in bottom border)
TOGGLE = 256 (Each time user selects, toggle its ON/OFF state)
STRCENTER = 512 (String Gadg - cursor stays in center of gadg)
STRRIGHT = 1024 (String Gadg - cursor stays at right of gadg)
Simply add up the ones you want
ID - A number from 0 to 999 which you want associated with this
gadget. Each gadget should have a unique ID number.
IDCMP - Extra flags that specify how the gadget effects IDCMP:
ISSUE_CLOSE = 128 (This gadget sends a CLOSEWINDOW message when
selected or released depending upon RELVERIFY
and IMMEDIATE. String gadgs only send on RELVERIFY)
OK = 1 (CLOSEWINDOW state is OK as opposed to CANCEL)
AUTOSELECT = 2 For a string gadget, when the user hits RETURN,
the next string gadget in the window is automatic-
ally selected. You must specify RELVERIFY for this
to work. Add the string gadgets in the order that
you would like them to be selected, and set the
AUTOSELECT of each string gadget that is to be
autoselected. A string gadget without this flag
set cannot be autoselected, nor auto select any
other gadgets in the window.
PRINTPROP = 4 For a prop gadget, prints the value of the
knob position as the user moves it. The value is
printed to the left of the gadget, so you should
leave 48 pixels space between gadgets along the
x axis. For this to work properly, you should
specify RELVERIFY and IMMEDIATE for the activation.
Also, the window's extraIDCMP should NOT be
NO_COLLECT or GIMME_MOVE.
extra - For a string gadget, this is the number of maximum chars, MAX-
CHARS that you want the user to be able to type in (limit =
65525).
For a prop, this is the number of possible pot values, RANGE,
that you would like returned. For example, if you want only 4
different values returned (ie 0, 1 ,2, or 3), then pass a 4.
The largest # of values you can receive is 65,535 (0 to 65,535
range). Note that a range of 1 (or 0), makes a knob that fills
the entire prop (and cannot be moved).
For a Bool, this is the initial selected state (1=On, 0=Off).
The gadget border and text is rendered using the current PenA, PenB, and
DrawMode, so you should set these values as desired before you add gadgets.
Note that the border for Prop gadgets is set by Intuition, and so you have
control over only the text color with props.
Note: Adding a prop gadget with the PRINTPROP flag set may cause the
window's DrawMode, FontPtr, and Style to be changed. The font is changed to
Topaz 8 NORMAL and Drawmode = JAM2.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
17) WaitMsg()
IDCMPspec=WaitMsg(window)
This routine is the main function which drives your IDCMP loop. It gets
the next intuition message that has arrived at your window, and puts the info
into a form that your rexx script can deal with. If there is no message at the
window, then your Rexx script is put to sleep until one arrives. The returned
IDCMPspec is a Rexx Argstring which consists of 4 fields. You can use the
standard Rexx command PARSE to place the 4 fields into separate variables.
Note that you only receive messages for those IDCMP flags you set when you
GetWindow() or ModIDCMP(). The first field of the IDCMPspec is the class. This
tells you what type of message was received. For example, if you accept the
default window IDCMP when you GetWindow() and you add some menus, when the
user selects some menu item (or subitem), you'll receive an IDCMPspec whose
first field is the value 2 for MENUPICK. If the user were to click the right
mouse (SELECT) button, the returned IDCMPspec's class would be 3 for MOUSE-
BUTTON. The other 3 fields of the IDCMPspec have different meanings depending
upon what the class is. Here is a chart detailing what the fields are for all
IDCMP flags (events):
A ---- means that this field has no meaning.
flag CLASS FIELD #2 FIELD #3 FIELD #4
CLOSEWINDOW 0 state: 0=CANCEL,1=OK ---- ----
GADGET 1 ID number 0=DOWN (SELECT) For PROPs, this is the current step # of the knob
1=UP (RELEASE) For STRINGS, this is the entered text
For BOOLS, this is the On/Off state (On=1, Off=0)
MENUPICK 2 MENU # ITEM # SUBITEM # (if there is one)
MOUSEBUTTON 3 Left DOWN=0 x pixel position y pixel position
Left UP=1
Right (Menu) DOWN=2
Right UP=3
Note that in order to receive Menu buttons, you must specify RMBTRAP window flags.
To receive any UP button event, you must set GIMME_UP of the extraIDCMP flags
for the window.
MOUSEMOVE 4 x pixel position y pixel position ----
If DELTAMOVE, then x and y are a (signed) delta offset from the last position.
Note that in order to receive MOUSEMOVE, you must specify GIMME_MOVE of the
extraIDCMP flags for the window. Also, NO_COLLECT will effect whether you
receive moves while the user is moving the mouse, or whether you just receive
notice of his final position (where he stops moving the mouse). NO_COLLECT
is VERY intensive with Rexx and should only be used when you want the user
to do something like freehand drawing with the mouse.
RAWKEY 5 If RAW, this is Code. If RAW, this ----
If COOKED, this is an the qualifier.
extended ascii char. If COOKED, this is
the modifier.
Note that to get the extended ascii char (ie COOKED KEYS), you must set
CONVERT_RAW of the extraIDCMP flags for the window. This translates a
RAWKEY press into a single ascii character. For all keys except the cursor,
function, and help keys, the ascii character is whatever the system keymap
returns, and the modifier = 0. So if the user holds the shift key and
presses the f key, 'F' is the char and modifier = 0. Alt keys may return
special chars. For the Function, cursor, and help keys, the values returned
are as follows:
Functions F1 to F10 = 0 to 9
Up cursor = 10
Down cursor = 11
Right cursor = 12
Left cursor = 13
Help = 14
Furthermore, the modifier for these keys will be:
no ALT and no SHIFT = 1
SHIFT = 2
ALT = 4
Note that CONVERT_RAW ignores key releases.
REQ 6 If REQSET, -1 ---- ----
If REQVERIFY, 0
If REQCLEAR, 1
SIZE 7 If SIZEVERIFY, -1 ---- ----
If NEWSIZE, 0
If REFRESHWINDOW, 1
DISK 8 If INSERTED, 0 ---- ----
IF REMOVED, 1
ACTIVE 9 If ACTIVEWINDOW, 0 ---- ----
If INACTIVE, 1
TIMEOUT 10 ---- ---- ----
MENUVERIFY 11 ---- ---- ----
NEWPREFS 12 ---- ---- ----
WBMSG 13 ---- ---- ----
Here's the way I envision that you'll implement your IDCMP loop in Rexx
(ie receive and interprete events from intuition). You'll open a window and
setup some way for the user to close the window (ie a system CLOSEGADGET, one
of your gadgets set to ISSUE_CLOSE, or a menu item set to ISSUE_CLOSE). You'll
initially set a variable (in this example called class) to 1. Then, you'll
enter a big loop where you WaitMsg(), and process all received IDCMPspecs
until you receive a class of 0 (CLOSEWINDOW). This will knock you out of the
loop, and allow your program to terminate. Furthermore, you can examine the
2nd field of the CLOSEWINDOW (its state), to determine whether the user wants
to do one thing (OK), or something else (CANCEL). The system CLOSEGADGET always
returns CANCEL state, but you can set your own menu items or gadgets to return
either OK or CANCEL state. Here's an example script:
/* An example of using the dissidents rx_intui.library */
/* Open a window on WB with default IDCMP, windowFlags, etc. */
wind=GetWindow('My Window',,,,,,,,)
/* Here's our IDCMP loop. We just print all returned specs until we get */
/* CLOSEWINDOW class (0). Start out class = 1 before we get into the loop. */
class = 1
DO WHILE class > 0
/* Get the next event or go to sleep waiting for one */
spec=WaitMsg(wind)
/* Show what was returned. Could be right MOUSEBUTTON (down) or CLOSEWINDOW */
SAY spec
/* divide the spec into 4 separate variables */
PARSE var spec class part1 part2 part3
/* Here we would examine the class and do other things depending on it */
END
/* Close the window, thus freeing any resources for it. */
/* Note that if no window opened, this does nothing. */
err=EndWindow(wind)
The TIMEOUT event allows the WaitMsg routine to return after a certain amount
of time without user activity. You can set the TIMEOUT value from 0 to 255
ticks. There are approximately 10 ticks per second but this depends upon system
activity. So, a timeout value of 20 allows the WaitMsg() routine to wait about
2 seconds for any user activity before it returns with a TIMEOUT IDCMPspec.
Note that you must set the TIMEOUT flag for your window IDCMP. Also, note that
every time that you call WaitMsg(), the TIMEOUT is restarted. To disable or
enable TIMEOUT, use SetTime(). This feature is useful if you want to have your
IDCMP loop do something automatically on a regular basis. If not for TIMEOUT,
when you called WaitMsg() and there were no messages from the user, WaitMsg()
would put your macro to sleep until the user intervened. This way you can
always return from WaitMsg() on a regular basis. There is only one problem with
this scheme. The TIMEOUT only works if the window is active. If the user were
to select some other window, then WaitMsg() really will go to sleep if no user
activity. You could let the user take advantage of this as a way for him to
completely halt your entire Rexx script at will. Or, you could ask to receive
ACTIVEWINDOW and INACTIVEWINDOW. There is another flag (of the window's
extraIDCMP) called NO_SLEEP. This flag allows WaitMsg() to never sleep. Instead,
WaitMsg() returns a TIMEOUT event (if there is no user activity in that
window). The net result is a busy wait loop on the Amiga, but if you wanted
some process to continually grind away, even when the user activates another
window, you should set NO_SLEEP when you receive an INACTIVEWINDOW IDCMPspec.
Later, when you receive an ACTIVEWINDOW IDCMPspec, you'll know that the user
selected the window again, and you can clear NO_SLEEP (via ModIDCMP). Note that
a TIMEOUT value of 0 really means 256 (ie 25.6 seconds which is the longest
automatic timeout possible). With NO_SLEEP set, the TIMEOUT amount of 0 means
to return immediately. Otherwise, there is a Delay before the return. Normally,
you'll want some sort of delay to prevent the program from hogging CPU.
Note: If the user selects a prop gadget with the PRINTPROP flag set, this
may cause the window's PenA, PenB, DrawMode, FontPtr, and Style to be changed.
You may need to restore these as desired when you detect such a prop in use.
The font is changed to Topaz 8 NORMAL, Drawmode = JAM2, and pens are set to
the gadget's.
If window = '', then this just returns CLOSEWINDOW with a CANCEL state.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
18) ModIDCMP()
err=ModIDCMP(window,extra,IDCMP,windFlags)
This is used to change the IDCMP and window flags of an open window. You
can change the extraIDCMP and IDCMP flags as described in GetWindow(). For
the windFlags, the only values that can be changed are RMBTRAP or NOCARE-
REFRESH (ie to turn RMBTRAP on and NOCAREREFRESH off, windFlags = 65536, to
turn it off as well as NOCAREREFRESH, windFlags = 0).
Note: Modifying a prop gadget with the PRINTPROP flag set may cause the
window's PenA, PenB, DrawMode, FontPtr, and Style to be changed.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
19) SetTime()
err=SetTime(window,timeout)
This is used to set the timeout value in ticks (where each tick is about
1/10 of a second). If you pass a specific timeout value, then timeout is
enabled. If you pass no timeout arg (ie an empty comma), then timeout is
disabled.
For example, this sets a timeout of 1 second, enabling the feature:
err=SetTime(window,10)
This disables the timeout feature completely:
err=SetTime(window,)
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
20) ModGadg()
gadg=ModGadg(window,gadg,text,activation,extra,init,ID,IDCMP,PenA,PenB,DrawMd)
This is used to modify a gadget in a window. You can change the following
parameters:
text - the text associated with the gadget. The new string cannot be
longer than the original string used when the gadget was made
(via AddGadg), or it will be truncated to that length. If you
pass no arg for this, then it is not changed.
activation - same as AddGadg(). If no arg, then it is not changed.
extra - same as AddGadg(). If no arg, then it is not changed.
Note that for a string gadget, the number of chars cannot be
larger than the original value when the gadget was made. If so,
the value is unchanged.
THE NEXT 3 VALUES DO NOT APPLY TO THE BORDER OF A PROP GADGET.
PenA - the new PenA value for the text and border. If no arg, it is
unchanged.
PenB - the new PenB value for the text and border. If no arg, it is
unchanged.
DrawMd - the new draw mode value for the text and border. If no arg, it
is unchanged.
init - For a string gadget, this is the text to set inside the gadget.
If the text is longer than the gadget's maximum chars, it will
be truncated.
For a prop gadget, this is the step # upon which to set the
knob. For our preceding example, we set a RANGE of 4. Now, we
pass a value of 0, 1, 2, or 3. 0 would set the knob all the way
to the left, 3 would set it all the way to the right. The lib
does no error checking that your step # is one of the allowable
ranges, so a "wrap-around" effect may occur if you don't check.
For a Bool, this is ignored.
ID - same as AddGadg(). If no arg, then it is not changed.
IDCMP - same as AddGadg(). If no arg, then it is not changed.
Note that when you first AddGadg(), you should make sure that your text,
(and for a STRING gadget, the MAXCHARS), is as large as any string that you
intend to pass to ModGadg() so that no truncation will occur.
If window or gadg = '', this does nothing.
Note: This routine may change the current PenA, PenB, and DrawMode if you
update a PROP gadget's knob position with the PRINTPROP flag set.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
21) GInfo()
value=GInfo(window,ID)
This gets some info about the gadget with the passed ID. If the gadget
with that ID is a Prop, this returns the step # that the knob is on. For a
Bool, this returns its state (1=On,0=Off). For a string, this returns the
text in the gadget. If window = '', or no gadget is found with the passed
ID, this returns a null string.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
22) OnOffGadg()
gadg=OnOffGadg(window,gadg,operation)
This is used to turn a gadget On or Off, or to remove it altogether. If
removed, it is freed. If passed a null window or gadg ptr, this does nothing.
window - the address of the window that the gadg is in
gadg - the address of the gadg to affect (as returned by AddGadg)
operation - 0 for remove it, 1 for ON, 2 for OFF
Note that this returns the address of the gadget if you are turning it ON
or OFF, but it returns a NULL ptr if you remove the gadget. You should always
assign the return to the same variable name as the passed gadget. This will
insure that multiple calls to remove a certain gadget will be "safe".
If window or gadg = '', this does nothing.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
23) MoveView()
err=MoveView(window,operation,data1,data2)
This is used to move or size a window (or a window's screen). It is also
used to beep (ie flash) the screen, or to activate a window. If window is null,
this does nothing. No error checking is performed on the dx and dy values!
operation is 0=WindowToFront,1=ScreenToFront,2=WindowToBack,3=ScreenToBack,
4=ActivateWindow,5=DisplayBeep,6=SizeWindow,7=MoveScreen,
8=MoveWindow
data1 and data2 are dx,dy if operation = MoveWindow, MoveScreen, or SizeWindow.
Ignored otherwise.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
24) Peek() and Poke()
value = PEEK(address,offset,size)
value = POKE(value,address,offset,size)
address = structure address to examine or modify
offset = # of bytes to the desired field from the head of the structure
size = 0 if the field is a BYTE size, 1 for WORD, or 2 for LONG
For POKE,
value = the new value to install in that field
These 2 routines let you modify or inspect fields of the structures that the
lib returns. For example, you may wish to get the Window's RastPort address.
This can be done by PEEKing the value at an offset of 50 bytes from the window
address. (The window address is returned by GetWindow). Since the RastPort
field of the window contains an address, it is a LONG. Therefore size = 2.
So here is how we get the RastPort address of a window.
wind=GetWindow('My Window',,,,,,,,)
rastport=PEEK(wind,50,2)
These 2 do nothing if address is a null pointer. Since POKE can modify
memory directly, do not use it unless you know what you're doing. Here are
some other common uses for PEEK.
/* Get window's Screen address. Could be WorkBench's screen */
screen=PEEK(wind,46,2)
/* Get window's ViewPort address. You must first find its screen. */
viewport='' /* assume no viewport */
screen=PEEK(wind,46,2)
IF screen > '' THEN viewport=screen+44
/* Get Screen's ViewModes (as described in GetScreen). Note that this is a WORD size */
modes=PEEK(screen,76,1)
IF modes == 0 THEN SAY 'LoRES mode screen'
/* Get Screen's Width and Height */
width=PEEK(screen,12,1)
height=PEEK(screen,14,1)
/* Get Window's current Gadget strip address */
gstrip=PEEK(wind,62,2)
/* Get Window's current LeftEdge, TopEdge, Width and Height */
leftedge=PEEK(wind,4,1)
top=PEEK(wind,6,1)
width=PEEK(wind,8,1)
height=PEEK(wind,10,1)
/* Get Window's current PenA #, PenB #, and DrawMode. These are BYTEs. You */
/* must first find the window's Rastport. */
rastport=PEEK(wind,50,2)
penA=PEEK(rastport,25,0)
penB=PEEK(rastport,26,0)
drawmode=PEEK(rastport,28,0)
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
25) RedrawWind()
err = RedrawWind(window,flags)
Can be used to redraw the window's gadgets, window frame, and set the
mouse pointer.
Flags: (add up the ones you want)
1 = Draw a regular mouse pointer
2 = Draw a Wait pointer
4 = Redraw window frames
8 = Refresh the Gadgets
16 = Blank the mouse pointer
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
26) FBox()
err=FBox(window,x1,y1,x2,y2)
x1 = upper left x coord (default = inside of left border)
y1 = upper left y coord (default = below title bar)
x2 = lower right x coord (default = inside of right border)
y2 = lower right y coord (default = above bottom border)
This is used to draw a filled box where x1 and y1 are the coordinates of
the upper left corner of the box, and x2 and y2 are the coordinates of the
lower right corner of the box. These values are in pixel offsets from the
upper left corner of the window (where x=0, y=0). This function clips the
values to within the window borders. It also checks that x1 < x2, and y1 < y2,
swapping the coordinates if necessary. If window='', does nothing.
This draws the box using the current PenA and DrawMode for the window.
See SetDraw().
Note that supplying no args makes a box as large as the window. Also, if
you set PenA to the desired background color #, and drawmode to JAM1 or JAM2,
then you can clear the entire window. Note that this can erase the gadgets as
well, so you should RedrawWind().
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
27) Line()
err=Line(window,origX,origY,x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6)
origX = x coord of where to start the line (default = use current x position)
origY = y coord of where to start the line (default = use current y position)
x1 = the x coord of the first point to which to draw
y1 = the y coord of the first point to which to draw
x2 = the x coord of the second point to which to draw
y2 = the y coord of the second point to which to draw
etc
This function draws a series of lines (using the current pens and drawmode).
The start of the line is at origX, origY. Then, the next two args define where
to draw to. Subsequent args define further points to draw lines to. When there
are no more args, the line drawing stops. You can draw up to 6, connected line
segments with each call to this function. Note that you can draw even more
connected line segments by several, subsequent calls to Line(). Don't specify
a new origX or origY (ie just leave an empty comma) and drawing will continue
from the last point. You can draw a single line segment by only giving origX,
origY, x1, and x2. You can draw an unfilled box using this function as well.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
28) Pixel()
penNum=Pixel(window,y,x,operation)
x = the x coord of the point (default = current mouse x)
y = the y coord of the point (default = current mouse y)
operation = 0 for ReadPixel, 1 for WritePixel
This can be used to change the specified pixel to the PenA color (if
operation=1), or to find out the pen number of the specified pixel (operation
=0)
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
29) Input()
response=Input(window,fileio,charLimit,prompt,init)
This is a routine which allows you to get string input from the user via
the window title bar. It is a handy alternative to a string gadget since it
displays the prompt, gets the input, and restores the title bar without alter-
ing your window display. It is ideal for getting string input without needing
room in the window for a string gadget, or opening another window with a string
gadget inside.
The user can cursor about the title bar, inserting, deleting chars, and use
CTRL-x to clear the input.
This returns a NULL string if the user enters no input or presses the ESC
key.
This also filters out any control characters, and uses the system keymap.
window - the window title bar to use
fileio - a fileio (gotten via GetFIO)
charLimit - the number of characters the user can type before auto-return
(ie also the max # of characters that your string will contain)
prompt - the prompt to display
init - any initial input for the user to edit (must be less than
charLimit)
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
30) MsgOne() and MsgThree()
YesNo = MsgThree(window,string1,string2,string3)
YesNo = MsgOne(window,string)
These two are used to present an automessage to the user. MsgOne() only dis-
plays one string and an OK gadget, and always returns 1. MsgThree() allows
up to 3 lines of text, has an OK and NO gadget (returning 1 and 0 respectively)
and centers the 3 lines in the requester. The 2nd or 3rd line can be omitted
by passing null arguments for them.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
31) Title()
err = Title(window,FileIO,string1,string2)
This changes the window title bar to string1 with string2 appended. This
can be used instead of the two autorequester routines. If all you need to do
is post some error message without needing a reaction from the user, this
method frees the user from needing to select some requester's OK or CANCEL to
continue. The original window title is saved so that a subsequent Title() with
no string1 argument can restore the title, even across multiple calls to
changing the title bar. Note that this function will overwrite certain FileIO
fields so that if you use this function, any filename currently in the FileIO
will be disposed of. Also, if you use this FileIO to obtain a filename, the
window's original title can no longer be restored via a NULL string1 arg as so:
err = Title(window,FileIO,)
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
32) IFFLoad() and IFFSave()
These two load an IFF ILBM picture into a window, and save a window's
rastport as an ILBM file, respectively. They both require the dissidents'
ilbm.library to be in your LIBS: drawer. Without this library, a null pointer
is returned.
window=IFFLoad(window,flags,filename)
window - the address of the window to be loaded into, or 0 if you want the
lib to open a window/screen of the proper size for the ILBM. IFFLoad
returns the address of the window (or null pointer if it couldn't
open). You are responsible for closing any window and screen that
the lib opens for you. Use EndWindow() and EndScreen(). Remember, to
get the address of the window's screen, use Peek().
flags - describes how to setup the load as follows:
1 = MOUSEFLAG (set for blank mouse pointer)
2 = SCREENFLAG (set for hide screen title bar)
4 = COLORFLAG (set for "Don't use loaded colorMap. Preserve present map.)
8 = NOSCALE (set for "Don't scale a lower res pic to fill a larger bitmap)
16 = ADJUSTVIEW (do overscan if larger than standard Intuition view)
32 = FORCEPARSE (ignore IFF_DONE and force parsing to continue to end of file)
128 = ANIMFLAG (set if an ANIM file. The lib takes care of this one)
filename - the name of the IFF ILBM file to load
If an error occurs during load (other than the window not opening), an error
requester will appear to alert the user. If you let the library open the window
and screen for you, you must close the these yourself later via EndWindow()
and EndScreen. For example:
/* load a picture called blort in current dir. Let lib open window/screen */
picwind=IFFLoad(0,1+2+16,'blort')
/* Wait for ANY idcmp in this window (i.e. user click) before closing down */
spec=WaitMsg(picwind)
/* Get window's Screen address */
picscr=PEEK(picwind,46,2)
/* Close the window and then the screen */
err=EndWindow(picwind)
err=EndScreen(picscr)
window=IFFSave(window,filename)
This saves a window's contents as an ILBM file. If window is null, this does
nothing. It posts an error requester if the save is not good.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
33) Color()
This brings up the dissidents color requester so that the user can adjust
the screen's colors. This requires the dissidents color.library to be in your
LIBS: drawer. This requester automatically adjusts to the number of colors in
the screen, and has numerous features. See Color.doc for details, or contact
dissidents.
err = Color(screen)
This returns one of the following values:
0 = the user selected OK
1 = the user selected CANCEL
-4 = library in use, another application is displaying it
-3 = passed a null screen address.
-2 = screen has no depth (planes).
-1 = color window can't open (probably out of memory). Buy some more.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
34) Print()
This uses the dissidents prtspool.library (copy to LIBS:) to print text
or graphics. You can dump all or part of a window rastport to the printer,
or print strings (with imbedded printer codes). The printing is spooled so
that your application returns immediately (if memory permits) while the lib
handles the print job. (Your macro could even end before the printing is
complete.) Subsequent printing is queued and handled by the lib if the printer
is in use. The preferences printer settings are used (ie color, printer name,
port, etc). If not enough memory to spool, your macro will halt (with a WAIT
pointer) until printing is complete. The user can abort at that time by press-
ing the RIGHT MOUSE BUTTON while holding the ALT key.
This routine can also be used to abort all current print jobs by setting
the ABORT flag.
err = Print(window, flags, extraCopies, data1, data2, data3, data4)
flags are: (Add up the ones that you desire)
ABORT = 512 (Abort all queued print jobs)
BWFLAG = 256 (For Graphics, when any requesters are presented, make PenA
and PenB B+W temporarily.)
GRAPHICS = 64 (Print Graphics instead of Text)
RAWWRITE = 32 (for Text, don't translate printer codes or characters)
NONEWLINE = 16 (for Text, don't force NEWLINE at end of each Print)
If you want to dump the window rastport, set the GRAPHICS flag. Then data1
and data2 are the coords of the upper left corner of the area to print, and
data3 and data4 are the lower right corner coords (ie x1,y1,x2,y2). See
FBox() for an example of defining coords. The defaults are the same as in
FBox() (so if you don't specify the coords, you get the full rastport).
The BWFLAG is useful if you don't know whether your PenA and PenB are
similiar shades. If they are, any requesters will be indistinguishable
from the background. If you encounter this situation, (especially if you're
loading ILBMs), you should set this flag.
If printing text, don't set GRAPHICS. Then, data1 is the string to print.
The subsequent args are ignored. The lib will force a NEWLINE at the end of
every Print(). If you don't want this, set NONEWLINE. You must then send
your own newline character (16) to flush the output when you desire a new
line. Normally, any imbedded printer escape codes (such as italics on, etc)
will be translated to the proper codes for your printer. If you wish no
translation of characters (ie especially for plotter control), set RAWWRITE.
With RAWWRITE, what you send to Print() is exactly what gets shipped out.
extraCopies is the number of extra copies beyond 1 that you desire. (ie pass
a 0 if you only want the initial dump).
If you want to ABORT current printing, just set the ABORT flag. extraCopies
and data args are not needed.
«««««««««««««««««««««««««««««« FILEIO SECTION »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
35) FileIO Section
Here are the functions that pertain to using the File requester, and auto
requesters. Consult FileIO.doc for a more in-depth discussion of the FileIO
requester which has the ability to be used for filename selection, as well as
displaying a list of your own strings (limit 29 characters). It can do multiple
selections, reports on whether a file exists and whether it is a dir, can do
info suppression, pattern matching, display mounted devices (menu button),
customizable by the user via the 10 function keys, WB pattern matching, etc.
******************************************************************************
fileio = GetFIO()
This returns the address of a FileIO structure which is passed to several
other lib routines. You must get one of these once before using any routine
requiring a FileIO.
******************************************************************************
fileio = EndFIO()
This frees the FileIO structure after you are done using any FileIO
routines. It also frees any list and locks attached to the FileIO.
******************************************************************************
path = FIOWindow(fileIO,title,flags,extension,path,obj-type,tooltypes,screen)
path = FIONW(fileIO,title,flags,extension,path,obj-type,tooltypes,window,x,y)
These present the FileIO requester to the user, allowing him to make his
filename selection, and then returns the entire selected path (ie directory
and filename), or '' if CANCEL was selected (or some error occurred). An Error
could result from the requester being unable to open, or already in use (only
one program can have it open at any given time.)
the args are:
the fileIO address (as returned by GetFIO)
the window title (or '' if none)
the FileIO flag settings (if no arg, these are not changed)
the extension string to match (or '' if none) 14 chars MAX
the initial path (could be a dir or filename). (If no arg, this is not changed)
For SPECIAL_REQ, the string to initially set in the Name String Gadget
the obj-type is the WB object to match where 1 = PROJECT and 2 = TOOL (no arg for ANY)
the tooltypes string is for WB pattern matching (or no arg for none)
the window (or screen if FIOWindow) upon which to open the requester
x,y are the upper left coordinate where the requester is to open (FIONW)
The difference between FIOWindow() and FIONW() is that FIONW() requires you
to have a window open. FIOWindow() opens on the passed screen (if 0, then that
means WorkBench).
Here are the numbers to specify for the FileIO Flags. Simply add up the ones
you want:
1 = NO_CARE_REDRAW (Does not show the list of filenames when first opened)
2 = USE_DEVICE_NAMES (Displays the drives using AmigaDOS device names like DF0)
4 = EXTENSION_MATCH (If you want an extension match. You must specify the string)
8 = DOUBLECLICK_OFF (Double-clicking on a filename doesn't end the requester)
16 = WBENCH_MATCH (Match ObjectType and ToolTypes string)
32 = MATCH_OBJECTTYPE (Don't ignore ObjectType. WBENCH_MATCH must also be set)
64 = MULTIPLE_FILES (Multiple filename selection)
128 = INFO_SUPPRESS (No .info files displayed)
4096 = NO_ALPHA (Don't alphabetize the list of filenames)
8192 = NO_ASSIGNS (Exclude logical assigns for the disk/volume name list)
16384 = SHOW_DISKS (Display disk/volume names instead of filenames)
32768 = SPECIAL_REQ (Use the requester for non-disk use)
Note that if you pass no arg for flags, then the flags settings will remain
the same as the last time that the fileio was used. (The very first time that
the fileio is used, all flags are clear).
The SPECIAL_REQ flag is used to display a requester with a list of your own
strings. You use AddEntry() to create the list of strings. Then, FIONW() or
FIOWindow() return the selected string, or '' if CANCEL is selected (or an
error occurred). Errors could be caused by another program using the FileIO
requester, or the requester was unable to open (low on mem).
For SPECIAL_REQ, replace the path arg with the desired string to be placed
in the Name Gadget. If no arg, then the gadget keeps its previous text.
Note that only the DOUBLECLICK_OFF, NO_ALPHA, and MULTIPLE_FILES flags are
effective in conjunction with SPECIAL_REQ.
Note that if you use one fileIO for both filename and custom reqs, you
should NewEntryList() before calling FIONW(), and you will have to NewEntry-
List() and make the custom list each time before using SPECIAL_REQ. You could
of course GetFIO() two fileIOs and use one for filename and the other for
SPECIAL_REQ.
Also note that this function clears any RMBTRAP of your window, so you
should reset that via ModIDCMP() if desired.
For filename selection, when this routine returns you should check the
FileIO's FILESIZE and the first byte of the FILENAME fields to see whether
the user has chosen a filename, and whether it already exists. This allows
you to protect against overwriting existing files, or trying to load non-
existant files. If the user has chosen a file, then the first byte of FILENAME
is not 0. If the file exists, then FILESIZE (LONG) is not 0; it is the size
of the file.
choose=Peek(fileIO,2,0)
IF choose > 0 THEN SAY 'User selected a file'
IF choose == 0 THEN SAY 'User selected a directory only, or no selection at all'
size=Peek(fileIO,240,2)
IF size == 0 THEN SAY 'This filename does not exist'
IF size > 0 THEN SAY 'This file exists and it is 'size' bytes.'
If you're about to save a file, you would also want to compare the FileIO's
FREEBYTES (which tells how much room is on the chosen disk) against the number
of bytes that you intend to write to the disk. If you're going to overwrite an
existing file, don't forget to add FILESIZE to FREEBYTES before you compare.
/* Let's say that I want to write 30 bytes using the returned filename. */
/* I presented the req to the user and he made his selection. I got the */
/* size, and checked to see if the user made a selection of a file (not dir). */
numOfbytes=30
diskspace=Peek(fileIO,236,2)
diskspace=diskspace+size
IF numOfbytes < diskspace OR numOfbyte == diskspace THEN DO
/* write the data */
END
For SPECIAL_REQ, the FILESIZE field contains the ID number of the string
that the user selected (or the last string selected for MULTIPLE_FILES). This
will be -1 if the string is not one of the ones that you presented in the list
(ie he typed his own string into the Name Gadget).
*********************************************************************
entryNum=AddEntry(fileIO,ID,string)
This adds an entry to a FileIO's list.
args are:
the fileIO address (as returned by GetFIO)
ID is any number you want associated with the string (ie not a string variable)
string is the string to be added and displayed
**************************************************************************
error=NewEntryList(fileIO)
Clears out any previous list in the fileio.
**************************************************************************
error=ClearEntries(fileIO)
Doesn't actually clear the list. It just "de-selects" all previously selected
strings. This is used to clear selections after using MULTIPLE_FILES.
**************************************************************************
error=DeleteEntry(fileIO,string)
Finds the string in the fileio's list, and removes it.
***************************************************************************
string=FirstEntry(fileIO)
Returns a NULL string '' if no more selected strings in the list. Otherwise,
returns the next selected string. Must be used once before calling
NextEntry(). NextEntry() is the same as FirstEntry(), but used for subsequent
calls. These are used to locate all of the selections one at a time after
MULTIPLE_FILES. See the FileIO.doc for details about MULTIPLE_FILES.
**************************************************************************
ID=IsEntryThere(fileIO,string)
Returns -1 if string is not in the list. Otherwise, returns the ID associated
with string.
**************************************************************************
path=GetPath(fileIO,filename)
If filename is not NULL '', then this is copied to the fileio's filename
buffer. Otherwise the filename is left as the user last selected. This
returns the last selected path (ie disk:drawer/filename) spec. Useful for
reconstructing the entire path when retrieving MULTIPLE_FILES. Note that
this doesn't bring up the requester.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
A) Demo scripts
There are several demo scripts to show you how to use various aspects of the
library. Some are rather simple, others more complex.
The first thing that you need to learn is how to open a window. Wind.rexx
does just that on WorkBench (with default IDCMP), then waits for ANY default
user input such as a MOUSEBUTTON or CLOSEWINDOW, and closes the window.
Screen.rexx is almost the same except it opens a screen, and then opens the
window on that screen.
Next, examine the text display functions. Text.rexx shows you how to print
text to a window. TextModes.rexx shows the effects of printing with different
pens and DrawModes, as well as shows how to set bold, italics, and underline
of the current font.
Now, look at the first instance of a minimal IDCMP loop, IDCMP.rexx. This
script just prints out all received events until CLOSEWINDOW. Note how I use
the PARSE command to break up the IDCMPspec into the 4 separate components.
Next, you're ready to look at Menus.rexx which shows you how to setup a menu.
Msg.rexx and Msg3.rexx show how to post some autoRequesters in a window.
Peek.rexx shows how to use Peek().
At this point, you're ready for Gadg.rexx. This script details several
features of the lib's gadget handling. Study this script carefully as it shows
how to setup a PROP, STRING, and BOOL gadget. Also, I start to do some things
inside the IDCMP loop which is where all of your work will be done.
Box.rexx shows how to draw a filled box, and demos a use for this. Line.rexx
demos using the Line() function to draw an unfilled box.
TimeOut.rexx demos the automatic timeout of WaitMsg(). Observe the script
running for several seconds. Note how this feature lets me do something without
intervention from the user.
Keys.rexx shows how to get input from the keyboard. It just prints each key
that you press, including function, cursor, and help keys. Note that I had to
modify the IDCMP of the window since RAWKEY is not one of the defaults. I
could have just specified the IDCMP when I called GetWindow() instead of
passing a null argument then, but I wanted to show you how to use ModIDCMP().
Input.rexx shows how to get a user input string from the window title bar,
which is a handy alternative to throwing up a string gadget just to get a
string, then removing it.
Now, let's look at the file requester. FileIO.rexx opens the file requester
3 times. Once with INFO_SUPPRESS (no .info files displayed), once only dis-
playing files that end in ".library" (by using EXTENSION_MATCH), and the last
time it only displays WorkBench tools (ie programs, not data files, that have
icons.) There are more things that you can do with this requester. Multiple.rexx
demos being able to select multiple filenames. When the requester is open, you
can select several filenames (selecting an already selected name "unselects"
it). This script then uses other functions to print out each one of the selected
files.
Custom.rexx shows how to use the file requester to display a list of strings
for selection by the user.
ILBM.rexx shows how to load an ILBM picture (letting the lib open a window
for it). Of course, you could load into an already open window. This script
also shows how to trap MENU MOUSEBUTTON events (ie Intuition no longer uses
this button to display menus. Now, I receive MENU DOWN and MENU UP MOUSEBUTTON
events.) Actually, I never receive any UP MOUSEBUTTONS because I never set the
GIMME_UP extraIDCMP flag for the window. This script also brings up the color
requester if you press the menu button after the picture is loaded.
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
B) Rexx Error Handling
The Rexx server's function library facilities were obviously not labored
over when the server was written. The handling of error returns from a func-
tion library causes the complete abort of the Rexx macro script (to the best
of my knowledge). If the Rexx function library allowed the macro to allocate
resources (such as this lib allows you to open windows, etc), then there is
no way for your macro to free the resources after Rexx stops it. For this
reason, the lib always returns success to the server, but null pointers when
an error occurs. All lib routines that operate on structures do nothing (ie are
safe) if passed a null pointer. This makes it possible for you to plod on if
an error occurs so that you can later free any resources that were allocated,
but also means that part of your macro may end up doing nothing. If there
wasn't enough memory to even open the window, an entire script could even do
nothing!!! Alas, I decided to forego returning error messages then have you
deal with allocated resources that can't be recovered until a reboot. Now, if
only this aspect of ARexx had been better implemented...
The only error that may result in aborting of the Rexx script is if there is
not enough memory to even return a result to Rexx (or if you have an in-
correctly written script).
«««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
C) Final remarks
Each of the lib's function names begins with 4, unique characters. If you're
writing a Rexx macro that has to be as "tight" as possible, you may call any
lib function using only the first 4 letters. For example,
window=GetW(,,,,,,,,,)
opens a default window on WorkBench. You also can eliminate all extra spaces
(like I did in the above example), and remove comments and blank lines from
the script.
This library is meant to enhance the amiga's ARexx package by Bill Hawes,
allowing scripts to interact with a user in an Intuition environment. As such,
it offers the ability to create a completely interactive Rexx script which can
function as its own application program.
The implementation of these functions reflects my own perception of what
some programmer (i.e. me) is likely to need. The most important considerations
were general functionality, speed, and size. By general functionality, I mean
that it was designed to let you interact with Intuition in a way that makes
it possible to do many typical things, but the esoteric (and fancy) manipula-
tion that other high level languages offer was excluded. Otherwise, the lib
would be much too big and slow, particularly for a SLOW interpreted language
like Rexx. It was written completely in 68000 with "aggressive optimization"
techniques. Consequently, its small size (about 7K) and speed help extend the
Rexx command set without imposing too severe an overhead.
It may be that I implemented something in a manner which better suits my
needs than your own. For this reason, I welcome feedback from anyone experi-
menting with the library. Don't just call when you have a problem. If you have
ideas for additions, you may be able to convince me that it is a viable pro-
ject. Otherwise, I'll assume that this lib suits your needs as well.