PortablE's standard functionality
by Chris Handley Last updated 08-Oct-2012.
All the functionality listed here is intended to be completely portable (i.e. OS independant). However, some of the MODULEs may not be implemented yet for all supported OSes (typically Windows), so they list which OSes are supported.
If you are not sure which modules to use, then please be sure to read chapter 8. What do the different MODULEs do?.
NOTE 1: While methods are shown in the form METHOD method(), this is not valid syntax for PortablE code (although that might change!).
NOTE 2: If you see OWNS as part of a variable's type, you can safely ignore it, because that is what PortablE currently does! However, it is a hint that ownership (i.e. deallocation responsibility) is being handed over. Thus an OWNS parameter shows that the procedure takes ownership, while an OWNS return value shows that the procedure passes ownership to the caller.
This is a list of all the kinds of values that can be used:
These are documented in the original AmigaE manual:
http://cshandley.co.uk/amigaeThis is a list of all expressions that can be used:
storage := expr ++ storage -- storage storage ++ storage --
array[expr] - expr ( expr )
expr !! type expr AND expr expr OR expr expr XOR expr expr SHL expr expr SHR expr expr BUT expr expr = expr expr >= expr expr > expr expr <= expr expr <> expr expr < expr expr + expr expr - expr expr * expr expr / expr
procedure(...) SUPER procedure(...) CALLBACK procedure()
NEW storage NEW object.method(...) object::objectType object.member object.method(...) SUPER self.method(...)
IF expr THEN expr ELSE expr
NOT expr
SIZEOF type
TYPEOF objectType
ADDRESSOF variable
NATIVE {native group} ... ENDNATIVE
EMPTY
Most of these expressions are documented in the original AmigaE manual:
http://cshandley.co.uk/amigaeBut when reading that manual, please beware that:
Note that:
This is a list of all statements that can be used (inside of a procedure). The full version of each statement is given, with optional parts enclosed in [square brackets]. Note that [...] is used to indicate that the previous optional part may be repeated further.
expr statement ; statement IF expr THEN statement [ELSE statement] IF expr statements [ELSE IF expr statements] [ELSE IF expr statements] [...] [ELSE statements] ENDIF END storage [,storage] [,storage] [...] RETURN [ expr [,expr] [,expr] [...] ] FOR storage := expr TO expr [STEP expr] DO statement FOR storage := expr TO expr [STEP expr] statements ENDFOR [IF expr] LOOP statements ENDLOOP REPEAT statements UNTIL expr WHILE expr DO statement WHILE expr statements ENDWHILE [IF expr] SELECT expr [CASE expr ; statements] [CASE expr ; statements] [...] [DEFAULT ; statement] ENDSELECT SELECT constant OF expr [CASE constant [TO constant] [, constant] [...] ; statements] [CASE constant [TO constant] [, constant] [...] ; statements] [...] [DEFAULT ; statements] ENDSELECT
Most of these statements are documented in the original AmigaE manual:
http://cshandley.co.uk/amigaeThis is a list of all the declarations & definitions which can be used (outside of a procedure). Note that [...] is used to indicate that the previous optional part may be repeated further, while [xxx ...] indicates that something comes after xxx but for brevity it is not shown. The | character is used to separate several possible options.
OPT option[=value] [, option[=value]] [...]
MODULE 'name' [, 'name'] [...]
RAISE quadcharacter IF procedure() comparison expression [, ...]
RAISE quadcharacter IF class.method() comparison expression [, ...]
CONST constant = expr [, constant = expr] [...]
ENUM constant [= expr] [, constant [= expr]] [...]
SET constant [, constant] [...]
TYPE type IS type
OBJECT object [OF object]
[PRIVATE|PROTECTED|PUBLIC|member[:type]] [, ...] [...] ENDOBJECT
CLASS object [OF object]
[PRIVATE|PROTECTED|PUBLIC|member[:type]] [, ...] [...] ENDCLASS
STATIC variable IS [list|'immediate string']
DEF variable[:type] [, variable[:type]] [...]
PROC procedure(...) [[NEW] OF class [ORPHAN]] [RETURNS ...] [PROTOTYPE|REPLACEMENT] [IS ...]
[DEF ...] statements [FINALLY statements] ENDPROC [expr [, expr] [...]]
FUNC function(...) [OF function] [IS ...]
[DEF ...] statements [FINALLY statements] ENDPROC [expr [, expr] [...]]
Most of these statements are documented in the original AmigaE manual:
http://cshandley.co.uk/amigaeBut when reading that manual, please beware that:
Note that:
This is a list of all procedures that are built-in to PortablE.
PROC Print( fmtString:ARRAY OF CHAR, arg1=0, ..., arg8=0) PROC PrintL(fmtString:ARRAY OF CHAR, args=NILL:ILIST) PROC PrintFlush()
Print() outputs the formatted string fmtString to stdout, with any additional arguments being used by the relevant soft escape codes (such as '\d'). Output may be buffered, and so may not appear immediately, especially if it does not end in a new line.
PrintL() is the same as Print(), except that it takes it's optional arguments as an ILIST. Can currently handle up to 20 optional items.
PrintFlush() flushes the output buffer, so everything that was Print()ed is shown.
PROC SetStdOut(fileHandle:PTR) RETURNS oldstdout:PTR PROC SetStdIn( fileHandle:PTR) RETURNS oldstdin :PTR PROC Out(fileHandle:PTR, char:CHAR) RETURNS value PROC Inp(fileHandle:PTR) RETURNS char:INT PROC OpenInOut(fileName:ARRAY OF CHAR) RETURNS fileHandle:PTR PROC CloseInOut(fileHandle:PTR)
SetStdOut() & SetStdIn() change the stdout & stdin streams (used by Print()/etc) to the given fileHandle.
Out() writes the supplied character char to the file handle, returning the number of characters actually written - so anything other than 1 is an error. You would typically use the stdout file handle.
Inp() reads & returns one character from the supplied file handle. An error is indicated by returning -1. You would typically use the stdin file handle.
OpenInOut() returns a fileHandle for the given file, which can be used with SetStdOut()/etc.
CloseInOut() closes the fileHandle, so that it can't be used anymore.
PROC StrCmp( first:ARRAY OF CHAR, second:ARRAY OF CHAR, len=ALL, firstOffset=0, secondOffset=0) RETURNS match:BOOL PROC StrCmpNoCase(first:ARRAY OF CHAR, second:ARRAY OF CHAR, len=ALL, firstOffset=0, secondOffset=0) RETURNS match:BOOL PROC StrLen(string:ARRAY OF CHAR) RETURNS length PROC Val(string:ARRAY OF CHAR, addrRead=NILA:ARRAY OF LONG) RETURNS value, read ->addrRead is depreciated PROC InStr( haystack:ARRAY OF CHAR, needle:ARRAY OF CHAR, startPos=0) RETURNS foundPos PROC TrimStr( string:ARRAY OF CHAR) RETURNS string:ARRAY OF CHAR PROC UpperStr(string:ARRAY OF CHAR) RETURNS string:ARRAY OF CHAR PROC LowerStr(string:ARRAY OF CHAR) RETURNS string:ARRAY OF CHAR PROC AstrCopy(destination:ARRAY, source:ARRAY OF CHAR, destSize) PROC OstrCmp( string1:ARRAY OF CHAR, string2:ARRAY OF CHAR, max=ALL, string1Offset=0, string2Offset=0) RETURNS sign:RANGE -1 TO 1 PROC OstrCmpNoCase(string1:ARRAY OF CHAR, string2:ARRAY OF CHAR, max=ALL, string1Offset=0, string2Offset=0) RETURNS sign:RANGE -1 TO 1 PROC QuadToStr(value:QUAD) RETURNS string:ARRAY OF CHAR
StrCmp() compares the first string against the second, and returns TRUE if they matched. len gives how many characters to compare (from the beginning), with the special ALL constant meaning compare everything. firstOffset & secondOffset allow you to specify an offset into the first & second strings respectively (to avoid pointer arithmetic).
StrCmpNoCase() is a case-insensitive version of StrCmp(). This procedure was not present in AmigaE.
StrLen() returns the length of the supplied zero-terminated string. It can be slow for very large strings.
Val() parses the supplied string, and returns the value of the integer number. Leading spaces & tabs are skipped. Hexadecimal & binary numbers are accepted if they are preceeded by $ or % respectively. A - minus sign will make the number negative. read is used to return the number of characters read, but will be 0 to indicate an error if no number could be parsed. addrRead is depreciated, but if it is supplied then the number of characters read is also written to the first item of that array.
InStr() searches the haystack string for an occurance of needle, optionally starting from a startPos position other than 0. It returns the position/offset at which needle was found, or -1 if there was no match.
TrimStr() returns a string pointing to the first non-empty character (not a tab, space, etc) in the supplied string.
UpperStr() modifies the supplied string to be all uppercase. It returns the supplied string for convenience.
LowerStr() modifies the supplied string to be all lowercase. It returns the supplied string for convenience.
AstrCopy() stands for "Array STRing COPY", and copies the contents of the source string into the destination string. destSize gives the maximum number of characters that destination can hold.
OstrCmp() performs an ordered string comparison between string1 & string2. Conceptually you can think of it as returning the Sign() of "string2 - string1". Thus it returns 0 if they are identical, 1 if string2 > string1, and -1 if string2 < string1. max gives how many characters to compare (from the beginning), with the special ALL constant meaning compare everything. string1Offset & string2Offset allow you to specify an offset into string1 & string2 respectively (to avoid pointer arithmetic).
OstrCmpNoCase() is a case-insensitive version of OstrCmp(). This procedure was not present in AmigaE.
QuadToStr() converts a QUAD value into a string, for easy Print()ing. Very useful for printing exception. Beware that it returns the same string each time (but modified to match the QUAD value), so you should copy it if you need to call QuadToStr() again before using the first returned string.
PROC And(a, b) RETURNS value ->depreciated, instead use AND PROC Or(a, b) RETURNS value ->depreciated, instead use OR PROC Xor(a, b) RETURNS value ->depreciated, instead use XOR PROC Shl(a, b) RETURNS value PROC Shr(a, b) RETURNS value PROC Not(a) RETURNS value ->depreciated, instead use NOT
And() returns a bit-wise And of the supplied values. Depreciated in favour of AND.
Or() returns a bit-wise Or of the supplied values. Depreciated in favour of OR.
Xor() returns a bit-wise Exclusive-Or of the supplied values. Depreciated in favour of XOR.
Shl() returns a arithmetically shifted left by b bits. Unlike SHL it accepts negative values for b.
Shr() returns a arithmetically shifted right by b bits. Unlike SHR it accepts negative values for b.
Not(a) returns a bit-wise inversion of the supplied value. Depreciated in favour of NOT.
PROC Mul(a, b) RETURNS value ->depreciated, instead use * PROC Div(a, b) RETURNS value ->depreciated, instead use / PROC Min(a, b) RETURNS value PROC Max(a, b) RETURNS value PROC Odd(a) RETURNS boolean:BOOL PROC Even(a) RETURNS boolean:BOOL PROC Rnd(max) RETURNS num PROC RndQ(seed) RETURNS num PROC Abs(a) RETURNS value PROC Sign(a) RETURNS value:RANGE -1 TO 1 PROC Bounds(num, min, max) RETURNS value PROC FastMod(a, b) RETURNS c PROC Mod(a, b) RETURNS c, d PROC Pow(a, b) RETURNS value
Mul() returns a multiplied by b. Depreciated in favour of *.
Div() returns a divided by b. Depreciated in favour of /.
Min() returns the smaller of the two supplied values.
Max() returns the larger of the two supplied values.
Odd() returns TRUE if the supplied value is odd (not wholly divisible by 2).
Even() returns TRUE if the supplied value is even (wholly divisible by 2).
Rnd() returns a pseudo-random number in the range 0 to max-1. To initialise the internal seed, call Rnd() with a negative number. The returned value may be limited to the range of LONG.
RndQ() returns a pseudo-random number quicker than Rnd() does, but the value covers the range of a whole VALUE (although it may be limited to the range of LONG for some targets). The returned value should be used as the value of seed in the next call.
Abs() returns the absolute (positive) version of the supplied value.
Sign() returns -1 if the supplied value is negative, +1 if it is positive, and 0 if it is 0.
Bounds() returns the number num bounded by the range min to max. It is equivalent to:
IF num < min THEN min ELSE IF num > max THEN max ELSE num
FastMod() divides a by b, returning ONLY the remainder c. It is roughly twice as fast as Mod().
Mod() divides a by b, returning the remainder c & the division result d. Mathematically c is equivalent to "a modulo b", while d is "a / b".
Pow() returns a raised to the power b. This procedure was not present in AmigaE.
PROC Fsin(a:FLOAT) RETURNS float:FLOAT PROC Fcos(a:FLOAT) RETURNS float:FLOAT PROC Ftan(a:FLOAT) RETURNS float:FLOAT PROC Fasin(a:FLOAT) RETURNS float:FLOAT PROC Facos(a:FLOAT) RETURNS float:FLOAT PROC Fatan(a:FLOAT) RETURNS float:FLOAT PROC Fsinh(a:FLOAT) RETURNS float:FLOAT PROC Fcosh(a:FLOAT) RETURNS float:FLOAT PROC Ftanh(a:FLOAT) RETURNS float:FLOAT PROC Fabs( a:FLOAT) RETURNS float:FLOAT PROC Ffloor(a:FLOAT) RETURNS float:FLOAT PROC Fceil( a:FLOAT) RETURNS float:FLOAT PROC Fexp( a:FLOAT) RETURNS float:FLOAT PROC Flog( a:FLOAT) RETURNS float:FLOAT PROC Flog10(a:FLOAT) RETURNS float:FLOAT PROC Fsqrt( a:FLOAT) RETURNS float:FLOAT PROC Fpow( a:FLOAT, b:FLOAT) RETURNS float:FLOAT PROC RealVal(string:ARRAY OF CHAR) RETURNS value:FLOAT, read
Fsin(), Fcos() & Ftan() perform floating-point Sine, Cosine & Tangent in radians.
Fasin(), Facos() & Fatan() perform floating-point Arc Sine, Arc Cosine & Arc Tangent in radians.
Fsinh(), Fcosh() & Ftanh() perform floating-point Hyperbolic Sine, Hyperbolic Cosine & Hyperbolic Tangent in radians.
Fabs() performs a floating-point version of Abs()
Ffloor() & Fceil() calculate the lowest & highest whole-number float of the supplied value.
Fexp() calculates e raised to the supplied power.
Flog() calculates the natural log of the supplied value.
Flog10() calculates the log base 10 of the supplied value.
Fsqrt() calculates the square root of the supplied value.
Fpow() performs a floating-point version of Pow(). Please be warned that the order of the parameters is the opposite of that in AmigaE.
RealVal() performs a floating-point version of Val().
PROC Raise(e:QUAD) ->depreciated, instead use Throw() PROC Throw(e:QUAD, i=NILA:ARRAY OF CHAR) PROC ReThrow() PROC PrintException()
Raise() throws exception e, with exceptionInfo set to NILA. This is depreciated in favour of Throw().
Throw() throws exception e, with exceptionInfo set to i.
ReThrow() throws the last exception again, if the global exception is not 0, otherwise it does nothing. Hardly needed since PortablE automatically does this at the end of every FINALLY section.
PrintException() is an easy way of reporting an exception. If there was no exception then it will do nothing. If you want to customise the output, then you can easily write your own version using Print() & QuadToStr()!
PROC New( size, noClear=FALSE:BOOL) RETURNS mem:ARRAY PROC NewR(size, noClear=FALSE:BOOL) RETURNS mem:ARRAY PROC Dispose(mem:ARRAY) RETURNS NILA
New() allocates & returns a memory block of size bytes. Normally the memory is cleared (zeroed), but if noClear is TRUE then it isn't. If allocation fails then it returns NILA. Note that memory is automatically deallocated at the end of the program.
NewR() is the same as New(), except that if allocation fails it raises the MEM exception.
Dispose() deallocates the provided memory block, which must have been allocated with New() or NewR(). It allows mem to be NILA. It returns NILA for convenience.
PROC FastNew(size, noClear=FALSE:BOOL) RETURNS mem:ARRAY PROC FastDispose(mem:ARRAY, size) RETURNS NILA PROC MemCopy(target:ARRAY, source:ARRAY, sizeInBytes, targetOffsetInBytes=0, sourceOffsetInBytes=0) RETURNS target:ARRAY
FastNew() is like NewR(), except that it is super-fast & does not significantly fragment memory. It does this using an enhanced TLSF algorithm, which allocates memory in larger blocks. On more modern OSes this is unnecessary, and so it simply calls NewR() in thoses cases.
FastDispose() is the Dispose() equivalent for FastNew(), but it needs to know the size of the block being deallocated. Unlike AmigaE, memory is returned to the OS, although only if everything in the "larger block" has been deallocated (otherwise the memory is recycled for the next FastNew() call).
MemCopy() copies sizeInBytes bytes from the source memory block into the target. targetOffsetInBytes & sourceOffsetInBytes allow you to specify an offset into the target & source memory respectively (to avoid pointer arithmetic). It returns the target array for convenience. This procedure was not present in AmigaE, but it provides a portable alternative to the Amiga's CopyMem().
PROC NewArray(sizeInItems, sizeOfItem:INT) RETURNS mem:PTR PROC DisposeArray(array:ARRAY) RETURNS NILA PROC ArrayCopy(target:PTR, source:ARRAY, sizeInItems, sizeOfItem:INT) RETURNS target:ARRAY
NewArray() allocates & returns an array of sizeInItems items & sizeOfItem bytes per item. Although it should return an ARRAY, it currently returns a PTR to force you to use OPT POINTER (since it may not be implementable for Java-like languages).
DisposeArray() deallocates the provided array, which must have been allocated with NewArray(). It returns NILA for convenience.
ArrayCopy() copies sizeInItems items of sizeOfItem bytes per item from the source array into the target array. It returns the target array for convenience. Although target should be an ARRAY, it is currently a PTR to force you to use OPT POINTER (since it may not be implementable for Java-like languages). Therefore you must cast target to a plain ARRAY type, using !!ARRAY , for it to compile.
PROC NewList(maxLen) RETURNS list:LIST PROC DisposeList(list:LIST) RETURNS NILL PROC ListCopy(list: LIST, other:ILIST, len=ALL) RETURNS list:LIST PROC ListAdd( list: LIST, other:ILIST, len=ALL) RETURNS list:LIST PROC ListMax( list: LIST) RETURNS max:VALUE PROC SetList( list: LIST, newLen) PROC ListLen( list:ILIST) RETURNS len:VALUE PROC ListCmp( list:ILIST, other:ILIST, len=ALL) RETURNS match:BOOL PROC ListItem(list:ILIST, index) RETURNS value
NewList() allocates & returns an e-list of maxLen items.
DisposeList() deallocates the provided e-list. It returns NILL for convenience.
ListCopy() replaces the contents of the list with that from the other list. len gives how many items to copy (from the beginning), with the special ALL constant meaning copy everything. It returns the list for convenience.
ListAdd() is similar to ListCopy(), except that the items are appended to the list.
ListMax() returns the maximum allowed length of the list.
SetList() changes the current length of the list to newLen items.
ListLen() returns the current length of the list.
ListCmp() compares the list against the other list, and returns TRUE if they match. len gives how many items to compare (from the beginning), with the special ALL constant meaning compare everything.
ListItem() returns item index from the list.
PROC NewString(maxLen) RETURNS eString:STRING PROC DisposeString(eString:STRING) RETURNS NILS PROC StrCopy( eString:STRING, string:ARRAY OF CHAR, len=ALL, pos=0) RETURNS eString:STRING PROC StrAdd( eString:STRING, string:ARRAY OF CHAR, len=ALL, pos=0) RETURNS eString:STRING PROC StrJoin(s1=NILA:ARRAY OF CHAR, ..., s19=NILA:ARRAY OF CHAR) RETURNS newString:STRING PROC EstrLen( eString:STRING) RETURNS len:VALUE PROC StrMax( eString:STRING) RETURNS max:VALUE PROC RightStr(eString:STRING, eString2:ARRAY OF CHAR, n) RETURNS eString:STRING PROC MidStr( eString:STRING, string:ARRAY OF CHAR, pos, len=ALL) RETURNS eString:STRING PROC SetStr( eString:STRING, newLen) PROC StringF( eString:STRING, fmtString:ARRAY OF CHAR, arg1=0, ..., arg8=0) RETURNS eString:STRING, len PROC StringFL(eString:STRING, fmtString:ARRAY OF CHAR, args=NILL:ILIST) RETURNS eString:STRING, len PROC RealF( eString:STRING, value:FLOAT, decimalPlaces=8) RETURNS eString:STRING PROC ReadStr(fileHandle:PTR, eString:STRING) RETURNS fail:BOOL PROC Link( complex:STRING, tail:OWNS STRING) RETURNS complex:STRING PROC Next( complex:STRING) RETURNS tail:STRING PROC Forward( complex:STRING, num) RETURNS tail:STRING
NewString() allocates & returns an e-string of maxLen items.
DisposeString() deallocates the provided e-string. It returns NILS for convenience.
StrCopy() replaces the contents of the eString with that from the string. len gives how many characters to copy (from the beginning), with the special ALL constant meaning copy everything. pos gives the position of the first character to copy. It returns the eString for convenience.
StrAdd() is similar to StrCopy(), except that the items are appended to the eString.
StrJoin() returns a new e-string which contains all of the supplied strings appended together. If any supplied string is NILA, then it will simply be ignored. This procedure was not present in AmigaE.
EstrLen() returns the current length of the eString. This is much faster than StrLen().
StrMax() returns the maximum allowed length of the eString.
RightStr() fills the eString with the last n characters of eString2. It returns the eString for convenience.
MidStr() replaces the contents of the eString with the given range from the string. pos gives the start position in string (with 0 being the beginning), while len gives how many characters to copy (from the start position), with the special ALL constant meaning copy everything. It returns the eString for convenience.
SetStr() changes the current length of the eString to newLen characters.
StringF() is similar to Print(), except that output now goes to the eString instead of stdout.
StringFL() is the same as StringF(), except that it takes it's optional arguments as an ILIST. Can currently handle up to 20 optional items.
RealF() writes the float value into the eString as an ASCII representation, with decimalPlaces digits after the decimal point. It returns the eString for convenience.
ReadStr() reads a string (ending in ASCII 10) from the fileHandle into the eString. It returns TRUE if an error occured, or an EOF was reached. The only file handle you are likely to use is stdin.
Link() puts the tail e-string into the next field of the complex e-string. It returns the complex e-string for convenience. Note that the complex e-string now owns the tail e-string, and will deallocate it when it is deallocated.
Next() returns the next field of the complex e-string. Next(NILS) safely returns NILS.
Forward() is similar to Next(), except that it goes forward num links instead of 1. You may safely call Forward() with a num that is too large.
PROC CharToUnsigned(char:CHAR) RETURNS value PROC UnsignedToChar(pos) RETURNS char:CHAR
CharToUnsigned() & UnsignedToChar() allow you to convert a CHAR to an unsigned value (typically between 0 & 255) & back again. You need this when comparing a CHAR with an integer value, because CHAR has unknown signedness in PortablE.
PROC BigEndianINT( in:INT ) RETURNS out:INT PROC BigEndianLONG(in:LONG) RETURNS out:LONG PROC BigEndianBIGVALUE(in:BIGVALUE) RETURNS out:BIGVALUE
BigEndianINT(), BigEndianLONG() & BigEndianBIGVALUE() return a value with swapped endianness, when used on a Little Endian processor (like x86), while they do nothing to the value when used on a Big Endian processor (like 68k or PPC). They should be used when reading or writing a value that is stored in Big Endian format.
You are encouraged to use Big Endian format for storing values, partly because they are easily read using a hex editor (since the largest digits are on the left), and partly because this format takes less effort on Big Endian processors (which tend to be less powerful).
Note that these BigEndian...() functions are the equivalent of the depreciated EndianSwap...() functions (which are currently still provided).
PROC LittleEndianINT( in:INT ) RETURNS out:INT PROC LittleEndianLONG(in:LONG) RETURNS out:LONG PROC LittleEndianBIGVALUE(in:BIGVALUE) RETURNS out:BIGVALUE
LittleEndianINT(), LittleEndianLONG() & LittleEndianBIGVALUE() return a value with swapped endianness, when used on a Big Endian processor (like 68k or PPC), while they do nothing to the value when used on a Little Endian processor (like x86). They should be used when reading or writing a value that is stored in Little Endian format.
PROC SwapEndianINT( in:INT ) RETURNS out:INT PROC SwapEndianLONG(in:LONG) RETURNS out:LONG PROC SwapEndianBIGVALUE(in:BIGVALUE) RETURNS out:BIGVALUE
SwapEndianINT(), SwapEndianLONG() & SwapEndianBIGVALUE() always return a value with swapped endianness, whatever processor is used. These functions should not normally be needed, but are provided for completeness.
PROC HaveSameClassTypes(first:CLASSTYPE, second:CLASSTYPE) RETURNS same:BOOL
HaveSameClassTypes() compares the first class type against the second, and returns TRUE if they were the same. For more information please see the "Run Time Type Information (RTTI)" subchapter of the "Object orientation" chapter in PortablE's main manual.
PROC GetBool( ptr:PTR TO BOOL ) RETURNS value:BOOL PROC GetByte( ptr:PTR TO BYTE ) RETURNS value:BYTE PROC GetChar( ptr:PTR TO CHAR ) RETURNS value:CHAR PROC GetInt( ptr:PTR TO INT ) RETURNS value:INT PROC GetLong( ptr:PTR TO LONG ) RETURNS value:LONG PROC GetQuad( ptr:PTR TO QUAD ) RETURNS value:QUAD PROC GetFloat(ptr:PTR TO FLOAT) RETURNS value:FLOAT PROC GetPtr( ptr:PTR TO PTR ) RETURNS value:PTR PROC GetArray(ptr:PTR TO ARRAY) RETURNS value:ARRAY PROC GetValue(ptr:PTR TO VALUE) RETURNS value:VALUE
These procedures peek the given ptr address, and return a value of the requested type.
PROC PutBool( ptr:PTR TO BOOL , value:BOOL ) PROC PutByte( ptr:PTR TO BYTE , value:BYTE ) PROC PutChar( ptr:PTR TO CHAR , value:CHAR ) PROC PutInt( ptr:PTR TO INT , value:INT ) PROC PutLong( ptr:PTR TO LONG , value:LONG ) PROC PutQuad( ptr:PTR TO QUAD , value:QUAD ) PROC PutFloat(ptr:PTR TO FLOAT, value:FLOAT) PROC PutPtr( ptr:PTR TO PTR , value:PTR ) PROC PutArray(ptr:PTR TO ARRAY, value:ARRAY) PROC PutValue(ptr:PTR TO VALUE, value:VALUE)
These procedures poke the provided value into the given ptr address.
PROC CleanUp(returnValue=0) PROC OptMultiThreaded() RETURNS multiThreaded:BOOL PROC FileLength(path:ARRAY OF CHAR) RETURNS size ->depreciated PROC KickVersion(version) ->currently always returns TRUE
CleanUp() exits the program at any point. It was depreciated in AmigaE, but has been reinstated in PortablE by using the exception system. It throws a negative exception value (which are reserved for use by E).
OptMultiThreaded() returns whether the program used OPT MULTITHREADED or not. This can be used to optimise your general-purpose module, such that it avoids worrying about multi-threading unless it has to.
FileLength() returns the length of the given file, but it's use is depreciated because (1) it is unnecessary due to the 'std/cPath' module, and (2) the path it takes is not truely portable.
KickVersion() is supposed to check whether the current Amiga Kickstart version is >= the supplied version, but currently it always returns TRUE. If someone could tell me how to implement this procedure then it would likely be moved to the 'exec' module.
All classes have the following methods:
METHOD InfoClassType() RETURNS typeof:CLASSTYPE METHOD IsSameClassTypeAs(type:CLASSTYPE) RETURNS isSame:BOOL METHOD IsOfClassType(parent:CLASSTYPE) RETURNS isSubtype:BOOL
For more information please see the "Run Time Type Information (RTTI)" subchapter of the "Object orientation" chapter in PortablE's main manual.
Some organisational changes have been made from AmigaE to ensure that PortablE is truely OS independant.
Procedures for Dos, Exec, Graphics & Intuition are no-longer built-in, and must instead be requested using:
MODULE 'dos', 'exec', 'graphics', 'intuition'
This happens automatically when the compatibility mode is enabled.
AmigaE's built-in Graphics helper functions (like Plot() & TextF()) are not available, unless the Amiga 'graphics' module is used, or the compatibility mode is enabled. But they are now depreciated in favour of the 'std/cGfx' module.
AmigaE's built-in Intuition helper functions (like OpenW() & Gadget()) are not available, unless the Amiga 'intuition' module is used, or the compatibility mode is enabled. But they are now depreciated in favour of the 'std/cGui' module.
The arg variable is not available, unless the Amiga 'dos' module is used, or the compatibility mode is enabled. It would be better to use the ShellArgs() procedure from the 'std/pShell' module.
The wbmessage variable is not available, unless the Amiga 'wb' module is used, or the compatibility mode is enabled.
Please see the "Statements, expressions & functions" subchapter of the "Reversible changes from AmigaE" chapter in the main PortablE manual for a list of procedures that have been renamed. Although if you look carefully in this documentation you should be able to find them anyway!
Also note that the exceptioninfo variable has been renamed exceptionInfo, unless the compatibility mode is enabled.
Because the list of MODULEs is quite large, and perhaps it would feel like a lot of effort to read every one until you found the right one, here is a quick explanation of the modules:
Basic stuff:
Commonly needed modules:
More powerful versions of some of the above modules:
Some smaller "sub-modules", if you don't need everything in 'std/cPath':
Obscure or advanced stuff:
This module allows you to call function pointers that are obtained using CALLBACK. It should be considered a hack, which will not be available for target languages like Java, and should be avoided except when porting existing AmigaE code.
Supported OSes: All.
PROC call0empty(func:PTR) PROC call0 (func:PTR) RETURNS value PROC call0many (func:PTR) RETURNS value, ret2, ret3, ret4, ret5 PROC call1empty(func:PTR, p1) PROC call1 (func:PTR, p1) RETURNS value PROC call1many (func:PTR, p1) RETURNS value, ret2, ret3, ret4, ret5 PROC call2empty(func:PTR, p1, p2) PROC call2 (func:PTR, p1, p2) RETURNS value PROC call2many (func:PTR, p1, p2) RETURNS value, ret2, ret3, ret4, ret5 PROC call3empty(func:PTR, p1, p2, p3) PROC call3 (func:PTR, p1, p2, p3) RETURNS value PROC call3many (func:PTR, p1, p2, p3) RETURNS value, ret2, ret3, ret4, ret5 PROC call4empty(func:PTR, p1, p2, p3, p4) PROC call4 (func:PTR, p1, p2, p3, p4) RETURNS value PROC call4many (func:PTR, p1, p2, p3, p4) RETURNS value, ret2, ret3, ret4, ret5 PROC call5empty(func:PTR, p1, p2, p3, p4, p5) PROC call5 (func:PTR, p1, p2, p3, p4, p5) RETURNS value PROC call5many (func:PTR, p1, p2, p3, p4, p5) RETURNS value, ret2, ret3, ret4, ret5 PROC call6empty(func:PTR, p1, p2, p3, p4, p5, p6) PROC call6 (func:PTR, p1, p2, p3, p4, p5, p6) RETURNS value PROC call6many (func:PTR, p1, p2, p3, p4, p5, p6) RETURNS value, ret2, ret3, ret4, ret5
Hopefully it's use is fairly self-explanatory:
This module provides basic functionality that is usually needed for Shell programs.
Supported OSes: All.
CONST SHELL_RET_OK CONST SHELL_RET_WARN CONST SHELL_RET_ERROR CONST SHELL_RET_FAIL
SHELL_RET_OK can be returned by your main() procedure, to indicate your program finished successfully.
SHELL_RET_WARN can be returned by your main() procedure, to indicate a warning.
SHELL_RET_ERROR can be returned by your main() procedure, to indicate an error.
SHELL_RET_FAIL can be returned by your main() procedure, to indicate a failure.
PROC ExecuteCommand(command:ARRAY OF CHAR) RETURNS executed:BOOL PROC ProgramName() RETURNS progName:ARRAY OF CHAR PROC ShellArgs() RETURNS shellArgs:ARRAY OF CHAR PROC CtrlC() RETURNS pressed:BOOL
ExecuteCommand() takes a Shell command, and executes it. It returns TRUE if the command could be found & was executed, but this does not indicate whether the command was successful or not. Currently there is no portable way to determine the return value of a command.
While ExecuteCommand() may be portable (i.e. OS independant), the Shell command provided to it is not. Therefore you will need to check the pe_TargetOS variable with StrCmp() to decide what command should be executed.
ProgramName() returns a string containing the name of the program's executable file.
ShellArgs() returns a string containing the parameters passed to your Shell program. This string may be empty if it was not executed as a Shell command. Beware that the spacing between words may not be exactly preserved, so for example several spaces may become just one.
CtrlC() allows your program to determine whether the user has pressed Ctrl-C or not since the last CtrlC() call.
PROC HighlightOnString() RETURNS on:ARRAY OF CHAR PROC HighlightOffString() RETURNS off:ARRAY OF CHAR
HighlightOnString() returns a string that can be used to start highlighting (or at least mark) a section of Print()ed text.
HighlightOffString() returns a string that can be used to stop highlighting (or at least mark) a section of Print()ed text.
This module provides Amiga-like Shell parameter parsing, but is completely OS independant, and far less error prone than ReadArgs().
Supported OSes: All.
This is how easy it is to use:
DEF file:ARRAY OF CHAR, quiet:BOOL
IF ParseParams('File/A, Quiet/S') = FALSE THEN Raise("QUIT")
file := GetParam(0)
quiet := GetParam(1) <> NILA
The following example programs use it:
Examples/std/Shell/AmigaAttributes.e Examples/std/Shell/BinDif.e Examples/std/Shell/DeleteModuleCache.e Examples/std/Shell/PEGCC.e Examples/std/Shell/RecursiveDir.e Examples/std/Shell/Timer.e
PROC ParseParams(template:ARRAY OF CHAR, shellArgs=NILA:ARRAY OF CHAR, silent=FALSE:BOOL) RETURNS success:BOOL PROC GetParam(index) RETURNS arg:ARRAY OF CHAR PROC NumberOfParams() RETURNS numberOfParams
ParseParams() uses the supplied template to parse the parameters provided to your Shell program. If you supply shellArgs then it will parse that instead.
It returns TRUE when the parameters were parsed without error. It returns FALSE when parameters did not match the template, for which an error will have already been reported to the user, so your program should just quit silently. If TRUE was given to silent then no error will be reported to the user.
GetParam() allows you to retrieve one of the parameters supplied to your program. The value of index specifies which parameter you want, with the first parameter being 0. The retrieved parameter is always returned as a string, even if the parameter only accepts numbers. If no such parameter was supplied, then it returns NILA.
NumberOfParams() returns the number of parameters in the template. It can be used to help emulate ReadArgs() if you wish.
Templates are of the form:
'Parameter1, Parameter2/X, Parameter3=P3/Y'
where P3 is an alternative name for Parameter3, and X & Y are flags. Multiple flags may be used, but each one must have a forward slash before it.
The template flags supported are:
/A = a required parameter /K = the keyword is required /S = the parameter is a switch /N = the parameter is a number /F = the parameter takes the rest of the line
The user's supplied parameters are parsed according to the template. If the user ends their parameters with a question mark, then the template is shown, and the user can enter additional parameters.
Read about AmigaDOS argument passing, which uses ReadArgs(), for a better idea how to use templates.
This module allows you to check the stack at run-time.
Supported OSes: AmigaOS4, AmigaOS3, AROS, MorphOS.
These procedures are not currently supported by the Windows (POSIX) target, but it isn't needed in those cases anyway.
PROC FreeStack() RETURNS bytes PROC StackSize() RETURNS bytes
FreeStack() returns the approximate number of bytes free in the stack.
StackSize() returns the total number of bytes allocated to the stack.
This module provides portable semaphores.
Supported OSes: AmigaOS4, AmigaOS3, AROS, MorphOS.
These procedures are not currently supported by the Windows (POSIX) target, due to MinGW not supporting POSIX semaphores.
PROC NewSemaphore() RETURNS sem:SEMAPHORE PROC DisposeSemaphore(sem:SEMAPHORE) RETURNS nil:SEMAPHORE PROC SemLock(sem:SEMAPHORE) PROC SemUnlock(sem:SEMAPHORE) PROC SemTryLock(sem:SEMAPHORE) RETURNS success:BOOL
NewSemaphore() allocates an e-semaphore.
DisposeSemaphore() deallocates the provided e-semaphore. It returns NIL for convenience.
SemLock() attempts to obtain a lock on the provided sem e-semaphore, and blocks your program until it obtains it.
SemUnlock() unlocks the provided sem e-semaphore.
SemTryLock() is similar to SemLock(), except that it returns FALSE if it can't immediately obtain a lock (instead of blocking).
WARNING: These functions literally do nothing, unless your program has OPT MULTITHREADED at the top. This allows you to write modules that support multi-threading, without needing to suffer semaphore overhead in single-threaded programs.
This module provides portable time & date related functions.
Supported OSes: All.
PROC CurrentTime() RETURNS time:BIGVALUE
CurrentTime() returns the current time & date, as the number of seconds which have elapsed since 0:00:00 on 1st January 2000. Times & dates before then are negative values!
This module provides standard functions that your functions can inherit. The aim is to allow functions written by one person to be used by algorithms written by another person.
For example, LIST-based implementations of Fmap() & Freduce() are provided, and they will work with any functions that inherit the appropriate standard functions.
Supported OSes: All.
Be warned that this module is still considered an "alpha" version, and therefore may change significantly (or may have major bugs).
FUNC funcParam0empty() FUNC funcParam0 () OF funcParam0empty RETURNS value
FUNC funcParam1empty(p1) FUNC funcParam1 (p1) OF funcParam1empty RETURNS value
FUNC funcParam2empty(p1, p2) FUNC funcParam2 (p1, p2) OF funcParam2empty RETURNS value
FUNC funcParam3empty(p1, p2, p3) FUNC funcParam3 (p1, p2, p3) OF funcParam3empty RETURNS value
FUNC funcParam4empty(p1, p2, p3, p4) FUNC funcParam4 (p1, p2, p3, p4) OF funcParam4empty RETURNS value
FUNC funcParam5empty(p1, p2, p3, p4, p5) FUNC funcParam5 (p1, p2, p3, p4, p5) OF funcParam5empty RETURNS value
FUNC funcParam6empty(p1, p2, p3, p4, p5, p6) FUNC funcParam6 (p1, p2, p3, p4, p5, p6) OF funcParam6empty RETURNS value
FUNC funcParam7empty(p1, p2, p3, p4, p5, p6, p7) FUNC funcParam7 (p1, p2, p3, p4, p5, p6, p7) OF funcParam7empty RETURNS value
FUNC funcParam8empty(p1, p2, p3, p4, p5, p6, p7, p8) FUNC funcParam8 (p1, p2, p3, p4, p5, p6, p7, p8) OF funcParam8empty RETURNS value
For more information please see the "Functional programming" chapter of the main PortablE manual.
PROC Fmap(function:PTR TO funcParam1, list:LIST) PROC Freduce(function:PTR TO funcParam2, list:ILIST, init)
For more information please see the "Functional programming" chapter of the main PortablE manual.
Use this module instead of the cApp module, to simplify things for beginners.
This module is used to describe your program (Application) to the OS in a portable way. It is needed by several other modules (such as cGfx & cGui) so that they can work together (otherwise cGfx windows would seem to come from a different program to the cGui windows!).
Supported OSes: The same as cApp.
The simplest use of this module would be:
IsDesktopApp()
If you wanted your window to fully cover the screen:
IsFullWindowApp()
If you wanted your own screen:
IsFullScreenApp(640, 480)
One of the following procedures must be called before you open any windows (using cGfx or cGui). You must not call more than one procedure. Typically you would call it at the start of your program.
PROC IsDesktopApp( title=NILA:ARRAY OF CHAR) PROC IsFullWindowApp(title=NILA:ARRAY OF CHAR) PROC IsFullScreenApp(width, height, title=NILA:ARRAY OF CHAR)
IsDesktopApp() indicates that your program will appear on the computer's desktop (called Workbench on Amiga). You can supply a title (i.e. name) for your program, otherwise your executable's file name will be used. This must be called before opening any windows!
IsFullWindowApp() indicates that your program will have a window that takes up the whole screen. Typically used by 'serious' applications. You can supply a title (i.e. name) for your program, otherwise your executable's file name will be used. This must be called before opening any windows!
IsFullScreenApp() indicates that your program will use the whole screen, without any window borders. You must supply the width & height of the screen. Typically used by games. You can supply a title (i.e. name) for your program, otherwise your executable's file name will be used. This must be called before opening any windows!
This module is used to describe your program (Application) to the OS in a portable way. It is needed by several other modules (such as cGfx & cGui) so that they can work together (otherwise cGfx windows would seem to come from a different program to the cGui windows!).
Supported OSes: AmigaOS4, AmigaOS3, AROS, MorphOS.
The simplest use of this module would be:
CreateApp().build()
A better use of this module might look like this:
CreateApp('my program name').initVersion('v1.0').initDescription('a cliched demo').build()
It is not usually necessary, but you can also do this:
DEF app:PTR TO cApp
app := CreateApp('my program name')
app.initVersion('v1.0')
app.initDescription('a cliched demo')
app.build()
PROC CreateApp(title=NILA:ARRAY OF CHAR) RETURNS app:PTR TO cApp PROC DestroyApp() PROC MinimiseApp(undo=FALSE:BOOL)
CreateApp() creates & returns a cApp object that will represent your Application. You can supply a title (i.e. name) for your program, otherwise your executable's file name will be used. You should then use it's methods (see below) to describe your program, before finally building it. You are only allowed to create one cApp object!
DestroyApp() destroys your cApp object. Since there can only ever be once cApp object, you do not need to supply it. It will also destroy any resources that depend on it, such as open windows. Since it is automatically called when your program quits, you don't normally need to use it!
Since DestroyApp() is automatically called when your program quits, any open windows (and other resources) will also be automatically closed.
MinimiseApp() minimises your Application, or undoes minimisation you supply TRUE for undo. The actual behaviour depends on the OS, but on AmigaOS it will cause MUI windows to be iconified (while cGfx windows are currently unaffected).
/* Methods of cApp */ METHOD initVersion( info:ARRAY OF CHAR) RETURNS self:PTR TO cApp METHOD initCopyright( info:ARRAY OF CHAR) RETURNS self:PTR TO cApp METHOD initAuthor( info:ARRAY OF CHAR) RETURNS self:PTR TO cApp METHOD initDescription(info:ARRAY OF CHAR) RETURNS self:PTR TO cApp METHOD initFullWindow() RETURNS self:PTR TO cApp METHOD initFullScreen(width, height) RETURNS self:PTR TO cApp METHOD build()
initVersion() sets a string that gives your program's version. This must be called before the App is built.
initCopyright() sets a string that gives your program's copyright information. This must be called before the App is built.
initAuthor() sets a string that gives your program's author (names). This must be called before the App is built.
initDescription() sets a string that gives a short description of your program's purpose. This must be called before the App is built.
initFullWindow() indicates that your program should have a window that takes up the whole screen. This must be called before the App is built. Typically used by 'serious' applications. You cannot use this with initFullScreen()!
initFullScreen() indicates that your program should use the whole screen, without any window borders. You must supply the width & height of the screen. This must be called before the App is built. Typically used by games. You cannot use this with initFullWindow()!
build() causes your Application to be built according to the information already given. So it should be called after using any init methods that you need. Other modules canNOT use cApp until it has been built!
/* more methods of cApp */ METHOD infoTitle() RETURNS info:ARRAY OF CHAR METHOD infoVersion() RETURNS info:ARRAY OF CHAR METHOD infoCopyright() RETURNS info:ARRAY OF CHAR METHOD infoAuthor() RETURNS info:ARRAY OF CHAR METHOD infoDescription() RETURNS info:ARRAY OF CHAR METHOD infoFullWindow() RETURNS fullWindow:BOOL METHOD infoFullScreen() RETURNS fullScreen:BOOL, width, height
infoTitle() returns the title you set using the CreateApp() procedure.
infoVersion() returns the version you set using the initVersion() method, or NILA if none was set.
infoCopyright() returns the copyright you set using the initCopyright() method, or NILA if none was set.
infoAuthor() returns the author you set using the initAuthor() method, or NILA if none was set.
infoDescription() returns the description you set using the initDescription() method, or NILA if none was set.
infoFullWindow() returns whether you used the initFullWindow() method or not.
infoFullScreen() returns whether you used the initFullScreen() method or not. It also returns the width & height of the screen you set.
/* more methods of cApp */ METHOD minimise(undo=FALSE:BOOL)
minimise() has the same effect as the MinimiseApp() procedure.
This module is the same as the cGfx module (which provides pixel-based graphics), except that it provides a few extras to simplify things for beginners. Those extras are detailed below.
Beware that you canNOT use this module at the same time as the cGfxSpritesSimple module, to draw within the same window. Use one or the other, but not both at the same time.
Supported OSes: The same as cGfx.
How to open a window:
IsDesktopApp() ->you only need to do this once! OpenWindow(640, 480)
How to draw in the window:
SetColour(RGB_ORANGE) DrawBox( 20,20, 50,50) SetColour(RGB_BLACK) DrawText(20,20, 'Hello world!')
Here is one way to show a picture in the window:
StoreBitmap('player', 0, LoadPicture('spaceship.gif'))
UseBitmap('player', 0).draw(50,50)
Or you could do this:
StoreBitmap('player', 0, LoadPicture('spaceship.gif'))
LastBitmap().draw(50,50)
Here's another way to show a picture in the window:
DEF player:PTR TO cGfxBitmap
player := LoadPicture('spaceship.gif')
player.draw(50,50)
The following example programs use it:
Examples/std/Graphics/Clock.e Examples/std/Graphics/Cosmic/cosmic_deluxe.e Examples/std/Graphics/IfsFern.e Examples/std/Graphics/Mandel.e Examples/std/Graphics/Pythagoras.e Examples/std/Graphics/StarsXY.e Examples/std/Graphics/StarsZ.e Examples/std/Graphics/StarsZYX.e Examples/std/Graphics/ToySketch.e Examples/std/Multimedia/ShadowOfTheBlitz_Scroller/sotb_orig.e Examples/std/Multimedia/StarsDemo.e
Released programs which are known to use it:
HueFlow ( os4depot.net/?function=showfile&file=game/puzzle/hueflow.lha ) Ami-Scratch ( os4depot.net/?function=showfile&file=graphics/misc/amiscratch.lha ) Ami-Bootguard ( os4depot.net/?function=showfile&file=utility/misc/ami-bootguard.lha ) Ami-Lineapolis ( www.lineapolis.dizzy.pl )
You do not need to use CreateGfxWindow(), because it is automatically called, with the result stored in the gfx global variable.
The 'std/cAppSimple' module is automatically available, so you can use it's procedures if you want.
The following RGB constants are provided for use with SetColour():
RGB_WHITE, RGB_BLACK, RGB_GRAY, RGB_GREY, RGB_SILVER, RGB_RED, RGB_GREEN, RGB_BLUE, RGB_YELLOW, RGB_MAGENTA, RGB_CYAN, RGB_ORANGE, RGB_PURPLE, RGB_PINK, RGB_BROWN
PROC LastBitmap() RETURNS bitmap:PTR TO cGfxBitmap PROC ChangeGfxWindow(title=NILA:ARRAY OF CHAR, hideMousePointer=FALSE:BOOL)
LastBitmap() gives you the last bitmap that was returned by one of the following procedures. If there was no last bitmap, then it protects you by throwing an exception.
ChangeGfxWindow() allows you to give a title (i.e. name) for your window. If you give TRUE for hideMousePointer then the mouse pointer will not be visible for the window. But you can only make these changes before opening the window!
PROC InfoScreenWidth() RETURNS width PROC InfoScreenHeight() RETURNS height PROC OpenWindow(width, height, resizable=FALSE:BOOL) PROC OpenFull() PROC CloseWindow() PROC CloseFull() PROC GetPosition() RETURNS x, y PROC SetPosition(x, y) PROC InfoWidth() RETURNS width PROC InfoHeight() RETURNS height PROC ChangeSize(width, height) PROC SetFrameSkipping(frameSkipping:BOOL) PROC SetAutoUpdate(autoUpdate:BOOL) PROC UpdateAndWaitForScreenRefresh() RETURNS skippingNextFrame:BOOL PROC WaitForScreenRefresh() PROC Clear(rgb) PROC SetColour(rgb) PROC GetColour() RETURNS rgb PROC SetColor(rgb) PROC GetColor() RETURNS rgb PROC ReadDot(x, y) RETURNS rgb PROC DrawDot(x, y) PROC DrawLine(x1, y1, x2, y2, thickness=1) PROC DrawBox(x, y, width, height, unfilled=FALSE:BOOL) PROC DrawCircle(x, y, radius, unfilled=FALSE:BOOL) PROC SetFont(name:ARRAY OF CHAR, size, style0plain1underlined2bold4italic=0) RETURNS success:BOOL PROC GetFont() RETURNS name:ARRAY OF CHAR, size, style PROC DrawText( x, y, fmtString:ARRAY OF CHAR, arg1=0, ..., arg8=0) PROC DrawTextL(x, y, fmtString:ARRAY OF CHAR, args=NILL:ILIST, backgroundColour=-1) PROC InfoSizeOfTextL(fmtString:ARRAY OF CHAR, args=NILL:ILIST) RETURNS width, height PROC ScrollBox(dx, dy, x, y, width, height) PROC GetLastEvent() RETURNS type, subType, value, value2 PROC InfoScreenFPS() RETURNS fps PROC StoreBitmap(name:ARRAY OF CHAR, number, bitmap:PTR TO cGfxBitmap) RETURNS storedBitmap:PTR TO cGfxBitmap PROC UseBitmap( name:ARRAY OF CHAR, number, allowReturnNIL=FALSE:BOOL) RETURNS bitmap:PTR TO cGfxBitmap PROC DestroyBitmap(bitmap:PTR TO cGfxBitmap) RETURNS nil:PTR TO cGfxBitmap PROC LoadPicture(file:ARRAY OF CHAR, maskFile=NILA:ARRAY OF CHAR, maskColour=-1) RETURNS pic:PTR TO cGfxBitmap PROC ExtractBitmap(x, y, width, height, notDrawable=FALSE:BOOL) RETURNS copy:PTR TO cGfxBitmap PROC MakeFractalBitmap(size, pen255colour, pen0colour, roughness=0, maskBelowPen=0, seed=0) RETURNS fractal:PTR TO cGfxBitmap
These are the same as cGfxWindows's methods (see chapter 19.3. Methods of cGfxWindow), but they look simpler because they are procedures. Only the most important methods are available as procedures, and unlike the methods they start with a capital letter.
If LoadPicture() could not load a picture, then it it protects you by throwing an exception.
(Note that both the CloseWindow() & CloseFull() procedures are the same as the close() method. And that the DestroyBitmap() procedure is essentially the same as the destroyDrawable() method.)
Don't forget the procedures from 19. MODULE 'std/cGfx'.
This module provides fairly easy pixel-based graphics, which is suitable for games, animation & multimedia. It is intended to be nearly as easy as AMOS, but more powerful.
Please note that many more features are planned for the future.
Supported OSes: AmigaOS4, AmigaOS3, AROS, MorphOS.
The simplest way to open a window:
DEF win:PTR TO cGfxWindow
CreateApp().build() ->you only need to do this once!
win := CreateGfxWindow('demo')
win.openWindow(640, 480)
How you open a full-screen window:
DEF win:PTR TO cGfxWindow, width, height
CreateApp().initFullWindow().build()
win := CreateGfxWindow('demo')
win.openFull()
width := win.infoWidth()
height := win.infoHeight()
The simplest way to draw in the window:
win.setColour($FF8800) ->sets Red to $FF, Green to $88, and Blue to $00, giving an orange colour win.drawBox( 20,20, 50,50) win.setColour($000000) win.drawText(20,20, 'Hello world!')
How to do flicker-free (double buffered) drawing in the window:
DEF x win.setAutoUpdate(FALSE) ->THIS IS IMPORTANT win.setColour($FF8800) FOR x := 0 TO win.infoWidth() win.clear($808080) win.drawBox(x,20, 50,50) win.updateAndWaitForScreenRefresh() ->THIS IS IMPORTANT ENDFOR
How to show a picture in the window:
DEF pic:PTR TO cGfxBitmap
pic := win.loadPicture('myPicture.gif')
pic.draw(20,20)
How to handle events from a single open window:
DEF quit:BOOL, type, subType, value, value2 quit := FALSE REPEAT IF WaitForGfxWindowEvent() = win type, subType, value, value2 := win.getLastEvent() IF type = EVENT_WINDOW IF subType = EVENT_WINDOW_CLOSE THEN quit := TRUE ELSE IF type = EVENT_KEY IF subType = EVENT_KEY_ASCII win.setColour($FF0000) win.drawTextL(50, 50, 'You pressed the "\c" key.', [value], $808080) ENDIF ENDIF ENDIF UNTIL quit win.close()
The following example programs use it:
Examples/std/Graphics/StarsXY_ToySpaceshipSprite1.e Examples/std/Graphics/StarsZYX_ToySpaceshipSprite1.e Examples/std/Multimedia/StarsDemo.e
PROC CreateGfxWindow(title:ARRAY OF CHAR, hideMousePointer=FALSE:BOOL) RETURNS win:PTR TO cGfxWindow PROC DestroyGfxWindow(win:PTR TO cGfxWindow) RETURNS nil:PTR TO cGfxWindow PROC MakeRGB(red, green, blue) RETURNS rgb PROC Pause(delayInTenthsOfSecond) PROC WaitForGfxWindowEvent() RETURNS win:PTR TO cGfxWindow, type, subType, value, value2 PROC CheckForGfxWindowEvent(keepPreviousEvents=FALSE:BOOL) RETURNS win:PTR TO cGfxWindow, type, subType, value, value2
CreateGfxWindow() creates & returns a cGfxWindow object for a new graphics window. You must supply a title (i.e. name) for your window. If you give TRUE for hideMousePointer then the mouse pointer will not be visible for the window. The window starts off closed, so you must use a method to open it. You can create as many windows as you want!
DestroyGfxWindow() destroys the supplied window. It will also destroy any resources that depend on it, such a bitmaps. Your windows will be automatically destroyed when your program quits, so you may not need to use this! You may pass it a NIL parameter without any problem. It returns NIL for your convenience.
MakeRGB() returns an RGB value made of the supplied red, green & blue components. They must each be in the range 0 to 255 (inclusive).
Pause() waits for the delay given in 1/10th of a second. So 10 is one second.
WaitForGfxWindowEvent() waits for an event from any window. It then returns the window that the event came from, and also values that describe the event. Please see the 19.6. Events sub-chapter. You don't have to store the event values, as they can be retrieved from the window using the getLastEvent() method. Note WaitForGfxWindowEvent() does not clear the last event from other windows.
Also note that it will only remember the most recent events (typically the last 100), so ensure that you watch for events regularly.
CheckForGfxWindowEvent() checks whether any event has occured yet, and returns it if it has. But if no event has happened, then it returns NIL for win. This method DOES clear the last event from all others windows, unless you supplied TRUE for keepPreviousEvents.
The cGfxWindow class is a window in which you can draw graphics. The window has a "current drawing colour", which is used by some drawing methods.
Unlike some graphical systems, it does NOT have a "background drawing colour", nor does it have a "current drawing position" (because these were felt to either be unnecessary, or else more of a hiderance than a help).
/* Methods of cGfxWindow */ METHOD infoScreenWidth() RETURNS width METHOD infoScreenHeight() RETURNS height METHOD openWindow(width, height, resizable=FALSE:BOOL) METHOD openFull() METHOD close() METHOD infoIsOpen() RETURNS isOpen:BOOL METHOD infoTitle() RETURNS title:ARRAY OF CHAR METHOD getPosition() RETURNS x, y METHOD setPosition(x, y) METHOD infoWidth() RETURNS width METHOD infoHeight() RETURNS height METHOD changeSize(width, height)
infoScreenWidth() & infoScreenHeight() return the size of the main screen. You can use them to decide what size window you should open.
openWindow() opens a window of the given size. If you use TRUE for resizable then the user will be allowed to resize the window (you will get an EVENT_WINDOW_RESIZED event when that happens). You may not use this method if the initFullWindow() or initFullScreen() methods were used on cApp.
openFull() opens a full window/screen, as previously specified by the initFullWindow() or initFullScreen() method that MUST have been used on cApp.
close() closes the window, loosing whatever was drawn in it. An exception will be thrown if the window is not open.
infoIsOpen() returns whether the window is open or not.
infoTitle() returns the title you set using the CreateGfxWindow() procedure.
getPosition() return the position of the window.
setPosition() changes the position of the window. This can be done before the window is opened.
infoWidth() & infoHeight() return the size of the window.
changeSize() changes the size of the window, and cause an EVENT_WINDOW_RESIZED event (the same as when a user resizes the window).
NOTE: That on AmigaOS the window's size may not actually change for up to 0.1 seconds (i.e. 6 frames). You can find out when it has actually changed by checking for an EVENT_WINDOW_RESIZED event.
/* more methods of cGfxWindow */ METHOD getFrameSkipping() RETURNS frameSkipping:BOOL METHOD setFrameSkipping(frameSkipping:BOOL) METHOD setAutoUpdate(autoUpdate:BOOL) METHOD getAutoUpdate() RETURNS autoUpdate:BOOL METHOD updateAndWaitForScreenRefresh() RETURNS skippingNextFrame:BOOL METHOD infoSkippingNextFrame() RETURNS skippingNextFrame:BOOL METHOD waitForScreenRefresh()
getFrameSkipping() & setFrameSkipping() allow you to change & retrieve whether or not the window has frame skipping enabled. For frame skipping to work, it also needs auto-update to be disabled. Typically a new window defaults to FALSE for frameSkipping, which means that all frames will be displayed. With it set to TRUE, it will skip frames which have been missed. That means your program should run at the same speed on slower machines, but it can cause jerkiness due to the skipping of frames.
Note that on AROS frameSkipping defaults to TRUE, because AROS is usually run under emulation, and that is far too slow for a 60Hz frame rate.
setAutoUpdate() & getAutoUpdate() allow you to change & retrieve the window's auto-update mode. A new window defaults to TRUE for autoUpdate, which means that all changes to the window contents are immediately visible, although this can sometimes cause flickering. When autoUpdate is FALSE, no changes are shown in the window until the updateAndWaitForScreenRefresh() method is called, which allows you to have silky smooth graphics.
updateAndWaitForScreenRefresh() waits for the screen to have completed refreshing, before updating it with any changes you have made to the contents of the window. This is done using a double buffer, giving you "vsynced" graphics. AutoUpdate must have been disabled, or an exception will be thrown.
Normally it returns FALSE, but if it detects a screen refresh has been missed (and frame skipping is enabled), then it will return TRUE to indicate that it will automatically skip the next frame, to keep your program/game running smoothly. You can safely ignore this, but if you wish to optimise your program, then you can avoid doing any CPU or graphically intensive operations that are only needed for the next frame.
infoSkippingNextFrame() returns the same value as the last updateAndWaitForScreenRefresh() method call did.
waitForScreenRefresh() waits for the screen to have completed refreshing.
/* more methods of cGfxWindow */ METHOD clear(rgb) METHOD setColour(rgb) METHOD getColour() RETURNS rgb METHOD setColor(rgb) METHOD getColor() RETURNS rgb METHOD readDot(x, y) RETURNS rgb
clear() fills the entire contents of the window with the given colour. The current draw colour is unaffected.
setColour() sets the current draw colour to the given RGB value.
getColour() returns the current draw colour.
setColor() is the same as setColour().
getColor() is the same as getColour().
readDot() returns the colour of the pixel at x,y.
/* more methods of cGfxWindow */ METHOD drawDot(x, y) METHOD drawLine(x1, y1, x2, y2, thickness=1) METHOD drawBox(x, y, width, height, unfilled=FALSE:BOOL) METHOD drawCircle(x, y, radius, unfilled=FALSE:BOOL)
drawDot() draws a dot at position x,y using the current draw colour. Note that position 0,0 is the top left of the window.
drawLine() draws a line between position x1,y1 and x2,y2 using the current draw colour. The line has a width of 1 unless thickness is given. If the line goes outside of the drawable region then it is automatically clipped.
NOTE: Please beware that lines with a thickness>1 may not be exactly identical on different OSes.
drawBox() draws a rectangle, with the top left at the position x,y and with the given width & height (which must be not be negative). The rectangle is filled unless unfilled is TRUE. If the rectangle goes outside of the drawable region then it is automatically clipped.
drawCircle() draws a circle with centre at the position x,y and with the given radius (which must not be negative). The circle is filled, unless unfilled is TRUE. If the circle goes outside of the drawable region then it is automatically clipped.
/* more methods of cGfxWindow */ METHOD drawText( x, y, fmtString:ARRAY OF CHAR, arg1=0, ..., arg8=0) METHOD drawTextL(x, y, fmtString:ARRAY OF CHAR, args=NILL:ILIST, backgroundColour=-1) METHOD setFont(name:ARRAY OF CHAR, size, style0plain1underlined2bold4italic=0) RETURNS success:BOOL METHOD getFont() RETURNS name:ARRAY OF CHAR, size, style
drawText() draws the fmtString text, with the top left at the position x,y. The text may contain formatting commands, the same as Print(), and any required parameters will be taken from arg1, etc. The drawn text's background is effectively transparent, so you may first need to clear the area where it will be drawn.
e.g. win.drawText(20,20, '\d + \d = \d\n', 1, 2, 3)
drawTextL() is similar to drawText(), except that any parameters required for formatted text will be taken from a supplied list. Unlike drawText() you can give a background colour, in which case the background will not be transparent (which on Amiga will be drawn much more efficiently, and can be anti-aliased).
e.g. win.drawTextL(20,20, '\d + \d = \d\n', [1, 2, 3])
setFont() allows you to change the current font, size & style used by drawText() & drawTextL(). If the named font is found then it will return TRUE. If the named font did not exist then it will return FALSE, and the current font will be unchanged. The plain style is 0, add 1 for underlining, add 2 for bold, and add 4 for italics. setFont() can be a slow operation if the specified size of font is not already in memory.
e.g. win.setFont('Times', 10)
getFont() returns the current font, size & style.
/* more methods of cGfxWindow */ METHOD makeText( fmtString:ARRAY OF CHAR, arg1=0, ..., arg8=0) RETURNS text:PTR TO cGfxDrawable METHOD makeTextL(fmtString:ARRAY OF CHAR, args=NILL:ILIST, backgroundColour=-1) RETURNS text:PTR TO cGfxDrawable METHOD makeBitmapTextL(fmtString:ARRAY OF CHAR, args=NILL:ILIST, backgroundColour=-1, notDrawable=FALSE:BOOL) RETURNS text:PTR TO cGfxBitmap METHOD infoSizeOfTextL(fmtString:ARRAY OF CHAR, args=NILL:ILIST) RETURNS width, height
makeText() & makeTextL() are similar to the drawText() & drawTextL() methods, except that they return an object that can be used to repeatedly draw the text (at any position & any time). Using the draw() method of this object is exactly the same as using the window's drawText() method, except that it uses the colour & font that were 'current' when the object was created. Since the text is stored as a plain string, it is slower but more memory efficient than the makeBitmapTextL() method. You must use destroyDrawable() or END on the returned object when you no-longer need it.
makeBitmapTextL() is similar to the drawTextL() method, except that it draws the text into the bitmap which is returned. Using the draw() method of this bitmap will draw it in the window, just as if you had called the drawTextL() method. The behaviour is exactly the same as for the makeTextL() method, but it stores the text as a graphical bitmap instead of a string. This makes drawing it much faster, but it uses more memory. You must use destroyDrawable() or END on the returned object when you no-longer need it.
infoSizeOfTextL() this returns the size of the object you would get from the makeTextL() or makeBitmapTextL() method, without the need to create it. It is also the effective size of the text drawn by the drawTextL() method. It allows you efficiently modify the text, to get exactly the needed size, before you make or draw the text.
/* more methods of cGfxWindow */ METHOD setDrawableRegion(x=0,y=0, width=-1,height=-1) METHOD getDrawableRegion() RETURNS x, y, width, height METHOD scrollBox(dx, dy, x, y, width, height) METHOD getLastEvent() RETURNS type, subType, value, value2 METHOD setLastEvent(type, subType, value=0, value2=0)
setDrawableRegion() allows you to change the drawable region, which is usually the whole of the window. Any subsequent drawing won't make any changes outside of the drawable region. This can be very useful if you want to have different parts of the window used for different purposes, such as the game world & the status bar. If width/height is set to -1 then the right/bottom of the drawable region is set to the edge of the window.
getDrawableRegion() returns the current drawable region.
scrollBox() scrolls the area inside the given box by dx,dy pixels. If the box is outside of the drawable region then it is automatically clipped.
getLastEvent() returns the last event (for this window) that was returned by the WaitForGfxWindowEvent() or CheckForGfxWindowEvent() procedure. If there were no events, then it returns EVENT_NONE for type.
setLastEvent() allows you to fake (or clear) the last event.
/* more methods of cGfxWindow */ METHOD startTimer(periodInMilliSeconds=0) METHOD stopTimer() METHOD infoPeriodOfTimer() RETURNS periodInMilliSeconds METHOD infoScreenFPS() RETURNS fps
startTimer() starts a timer which repeats every periodInMilliSeconds thousandths of a second. When the timer runs out, it will generate an event with type=EVENT_TIMER & subType=EVENT_TIMER_EXPIRED. The event's value is the count of the number of times that the event has expired, since the last timer event was reported (normally this will be 1 unless you don't check events often enough).
stopTimer() stops the timer.
infoPeriodOfTimer() returns the period of the timer in thousandths of a second, or 0 if no timer is running.
infoScreenFPS() returns the screen's Frames Per Second, also known as it's refresh rate in Hertz. Use this to convert a desired delay (in seconds) into a delay of a whole number of frames, so that you can update something smoothly on screen. Beware that the first call to this method may pause your program for around a second, while it measures the screen's FPS.
/* more methods of cGfxWindow */ METHOD loadPicture(file:ARRAY OF CHAR, maskFile=NILA:ARRAY OF CHAR, maskColour=-1, notDrawable=FALSE:BOOL) RETURNS pic:PTR TO cGfxBitmap METHOD extractBitmap(x, y, width, height, notDrawable=FALSE:BOOL) RETURNS copy:PTR TO cGfxBitmap METHOD makeFractalBitmap(size, pen255colour, pen0colour, roughness=0, maskBelowPen=0, seed=0) RETURNS fractal:PTR TO cGfxBitmap METHOD storeBitmap(name:ARRAY OF CHAR, number, bitmap:PTR TO cGfxBitmap) RETURNS storedBitmap:PTR TO cGfxBitmap METHOD useBitmap( name:ARRAY OF CHAR, number, allowReturnNIL=FALSE:BOOL) RETURNS bitmap:PTR TO cGfxBitmap METHOD destroyDrawable(drawable:PTR TO cGfxDrawable, force=FALSE:BOOL) RETURNS nil:PTR TO cGfxDrawable
loadPicture() loads the given picture, and returns a bitmap that can be used to draw the picture in the window. The file path must be given in the portable format used by the cPath module, so you may need to use it's ImportFilePath() procedure first.
If the picture has a mask then this will be used. Alternatively, you can use another file as the mask, in which case maskColour chooses the transparent colour. If you want to use the picture itself as the mask, then just use '' for maskFile.
When maskColour is -1 it uses the top-left pixel's colour, otherwise maskColour indicates the palette number or RGB value (depending on whether the picture has a depth <= 8 or not). Typically you would use 0 for maskColour.
Normally the bitmap is stored in video memory, and so can be drawn into the window. But if you wish to save video memory then give TRUE for notDrawable.
extractBitmap() creates & returns a bitmap containing part of the window. x,y gives the top left corner of the new bitmap, and width,height gives the size of the new bitmap. If you try to copy beyond the edge of the window then an exception will be thrown.
Beware that this can be quite slow, especially if width & height are large.
Normally the bitmap is stored in video memory, and so can be drawn into the window. But if you wish to save video memory then give TRUE for notDrawable.
makeFractalBitmap() creates & returns a bitmap containing a randomly generated 'cloud' or 'terrain' fractal. It can be very useful as a 'background' bitmap, since it tiles perfectly.
size gives the width & heigth of the bitmap, but if it isn't a power of two then it will be rounded-up to one. For example, if you supply 500 for size, then you will get a bitmap which is 512 by 512 pixels.
The bitmap effectively has a depth of 8-bits, since it contains 256 colours. pen255colour gives the RGB value of the highest pen colour, while pen0colour gives the lowest pen colour. The rest of the pen colours change smoothly between those two. For example, if you gave white for pen255colour & black for pen0colour, then you would get various shades of gray for the rest of the colours. For example, you might give a light & a dark shade of green to create a "grass bitmap":
win.makeFractalBitmap(size, $006000, $004000, 8)
Or give red & orange to create a "lava bitmap":
win.makeFractalBitmap(size, $FF0000, $FF6000)
roughness is value between 0 & 10 (inclusive) which controls how un-smooth the colour changes are. 0 is very smooth, while 10 is completely random. Values above 8 are unlikely to be useful!
maskBelowPen gives the pen number below which the bitmap is transparent. (It will also cause "pen0colour" to be the last non-transparent colour (so you are still giving the whole visible colour range).) For example, you could use it to make a whitish "cloud bitmap" which has gaps betweens clouds:
win.makeFractalBitmap(size, $606060, $E0E0E0, 0, 128)
seed allows you to give a particular random number seed, which will always give the same bitmap (even on different PortablE targets!). This allows you to search for a good looking fractal bitmap, which you can then easily recreate (rather than having to save it for future use).
storeBitmap() & useBitmap() allow you to store & retrieve bitmaps using a name string, and optionally a number. The string must be an 'immediate string', not one you have created. It returns the stored bitmap, so you can use it straight away. Here's an example of how you might use it:
IF win.storeBitmap('player', 0, win.loadPicture('spaceship.gif')) = NIL THEN Print('Failed to load picture.\n')
win.useBitmap('player', 0).draw(x,y)
If you try to store more than one bitmap with the same name & number combination, then an exception will be raised. This is to prevent you accidentally reusing them. And if you try to use a non-existant bitmap, then an exception will be raised; unless you gave TRUE for allowReturnNIL, in which case NIL will be returned.
destroyDrawable() takes the given bitmap/drawable & destroys it. You may pass it a NIL parameter without any problem. It returns NIL for your convenience.
For safety it will NOT destroy a bitmap/etc if it is being used by another object (such as a sprite), UNLESS you give TRUE for force, as this would normally cause a crash.
/* more methods of cGfxWindow */ METHOD queryExtra(specific:QUAD) RETURNS value, unknown:BOOL METHOD registerForResizes( client:PTR TO cGfxNotifyOfWindowResize) METHOD unregisterForResizes(client:PTR TO cGfxNotifyOfWindowResize)
queryExtra() allows you to retrieve OS-specific information. For example, if you give "WIND", then it will return the Amiga window pointer. And "SCRN" will return the Amiga screen pointer. Please only use this method as a last resort, because it will stop your code from being portable!
registerForResizes() & unregisterForResizes() are used to tell this window when another object needs to know that it has been resized. You do not normally need to use these methods! (This is used by the cGfxStack class to redraw itself when it's window is resized.)
Note that any sub-class of cGfxNotifyOfWindowResize should implement this method:
windowHasResized(oldWidth, oldHeight)
cGfxDrawable is an abstract class for any fixed-size object that can be drawn inside a window. It does not have to be a bitmap, and can use any window draw methods. You can easily create your own sub-classes of cGfxDrawable, please see the 19.7. Creating your own cGfxDrawable sub-class sub-chapter.
/* Methods of cGfxDrawable */ METHOD infoWidth() RETURNS width METHOD infoHeight() RETURNS height METHOD infoWindow() RETURNS win:PTR TO cGfxWindow METHOD infoIsTransparent() RETURNS isTransparent:BOOL METHOD draw(x, y) METHOD drawTiled(x, y, tileX:BOOL, tileY:BOOL)
infoWidth() & infoHeight() return the size of the drawable object.
infoWindow() returns the cGfxWindow that this object draws to.
infoIsTransparent() returns whether or not it is (partially) transparent. In the case of a bitmap, this would mean it has a mask.
draw() draws the object at the given position.
drawTiled() is the same as draw(), but it allows the object to be horizontally or vertically tiled, so it appears to be infinitely wide (when tileX is TRUE) and/or infinitely tall (when tileY is TRUE). When tiled, the drawable will be repeated in a 'tiled' fashion, thus allowing you to easily have background(s) that go on 'forever'.
The following methods are for advanced users only:
/* more methods of cGfxDrawable */ METHOD hitCheck(insideX, insideY) RETURNS hit:BOOL METHOD overlaps(drawable:PTR TO cGfxDrawable, insideX, insideY) RETURNS overlaps:BOOL
hitCheck() returns whether a particular point (relative to the top left of the drawable) will be drawn or not. (This is used by cGfxStack's findSpriteAt() method.)
overlaps() returns whether the provided drawable would overlap the current drawable, if the provided one was offset from the current one by the given coordinates (which are relative to the top left of the current drawable). If either drawable is a bitmap with a mask, then that will be taken into account. This method is handy for performing collision detection.
The following methods are for EXPERT users only:
/* more methods of cGfxDrawable */ METHOD changeUsageCount(increaseBy) METHOD infoUsageCount() RETURNS usageCount IS self.usageCount METHOD registerForChanges( client:PTR TO cGfxNotifyOfDrawableChanges) METHOD unregisterForChanges(client:PTR TO cGfxNotifyOfDrawableChanges) METHOD addToGfx(gfx:PTR TO cGfxWindow)
changeUsageCount() & infoUsageCount() is used to change & retrieve how many times this object is being used within the current window. The usage count is reduced by using negative values for increaseBy. And usageCount defaults to 0. You do not normally need to use these methods! (This is used by the cGfxBitmap sub-class to make itself non-drawable when it's usage count drops to 0, to save video memory. The cGfxSprite class uses it.)
registerForChanges() & unregisterForChanges() are used to tell this drawable when another object needs to know that it's size or contents changes. You do not normally need to use these methods! (This is used by the cGfxSprite class to redraw itself when it's drawable is changed.)
Note that any sub-class of cGfxNotifyOfDrawableChanges should implement this method:
drawableHasChanged(oldWidth, oldHeight, drawable:PTR TO cGfxDrawable)
addToGfx() should only be called once, by the drawable itself. This registers it with the cGfxWindow that it draws to, so that it will be automatically destroyed when the cGfxWindow is destroyed. gfx is stored in the inherited member self.gfx, which you can read yourself if needed. You never need to use this method, unless you are creating your own cGfxDrawable sub-class.
The cGfxBitmap class is a special kind of cGfxDrawable class, which is a bitmap (picture) that can be drawn into the window. Bitmaps use video memory, unless they are made non-drawable (in which case the draw() method will throw an exception if you try to use it).
/* Methods of cGfxBitmap, which inherits cGfxDrawable */ METHOD clone(changeIsDrawable=FALSE:BOOL, isDrawable=FALSE:BOOL) RETURNS clone:PTR TO cGfxBitmap METHOD extract(x, y, width, height, changeIsDrawable=FALSE:BOOL, isDrawable=FALSE:BOOL) RETURNS copy:PTR TO cGfxBitmap METHOD setIsDrawable(isDrawable:BOOL) METHOD getIsDrawable() RETURNS isDrawable:BOOL
clone() creates & returns a copy of the bitmap. If you want to change the drawable state then give TRUE for changeIsDrawable, in which case isDrawable will indicate whether the new bitmap should be drawable or not.
extract() creates & returns a copy of part of the bitmap. x,y gives the top left corner of the new bitmap (where 0,0 is the existing corner), and width,height gives the size of the new bitmap. If you try to copy beyond the edge of the bitmap then an exception will be thrown. As with the clone() method, you can change the drawable state of the new bitmap.
setIsDrawable() & getIsDrawable() allow you to change & retrieve the drawable state. When a bitmap is drawable it uses video memory, and you are allowed to use the draw() method.
/* more methods of cGfxBitmap */ METHOD savePicture(file:ARRAY OF CHAR, ignoreMask=FALSE:BOOL) RETURNS success:BOOL METHOD flip(horizontally:BOOL, vertically:BOOL) METHOD rotate(degrees) METHOD scaleTo(newWidth, newHeight) METHOD scaleBy(multiplier, divider) METHOD makeScaledTo(newWidth, newHeight) RETURNS scaledBitmap:PTR TO cGfxBitmap METHOD makeScaledBy(multiplier, divider) RETURNS scaledBitmap:PTR TO cGfxBitmap ->plus methods inherited from cGfxDrawable
For the inherited methods read 19.4. Methods of cGfxDrawable.
savePicture() saves the current bitmap as a picture, in a standard format (IFF on Amiga, although it will be PNG on AROS). Normally the mask will be saved as part of the picture, but you can use TRUE for ignoreMask to prevent this. It returns whether saving the picture was successful or not.
flip() horizontally and/or vertically flips the bitmap, such that it becomes the mirror-image of itself.
rotate() rotates the bitmap clockwise. degrees must be in 90 degree steps, such that 0, 90, 180 and 270 are allowed.
scaleTo() enlarges or shrinks the bitmap to the given size.
scaleBy() enlarges or shrinks the bitmap by the ratio multiplier / divider. Thus it enlarges it by the integer multiplier, and shrinks it by the integer divider. Both width & height are scaled by the same amount.
makeScaledTo() & makeScaledBy() are the same as the scaleTo() & scaleBy() methods, except that they return a new (scaled) bitmap, rather than modify the existing one. (This is more efficient than clone()ing a bitmap & then using scaleTo() or scaleBy().)
All events are described by up to four returned values:
type, subType, value, value2
Where type can be one of the following values:
EVENT_NONE, EVENT_MOUSE, EVENT_KEY, EVENT_WINDOW, EVENT_TIMER, EVENT_UNKNOWN
Where subType gives more information on the kind of event:
EVENT_MOUSE_MOVE, EVENT_MOUSE_SCROLL, EVENT_MOUSE_DOUBLECLICK, EVENT_MOUSE_LEFT, EVENT_MOUSE_LEFTUP, EVENT_MOUSE_RIGHT, EVENT_MOUSE_RIGHTUP, EVENT_MOUSE_MIDDLE, EVENT_MOUSE_MIDDLEUP EVENT_KEY_ASCII, EVENT_KEY_ASCIIUP, EVENT_KEY_SPECIAL, EVENT_KEY_SPECIALUP EVENT_WINDOW_CLOSE, EVENT_WINDOW_ACTIVE, EVENT_WINDOW_INACTIVE, EVENT_WINDOW_RESIZED EVENT_TIMER_EXPIRED EVENT_UNKNOWN_DONOTUSE ->EVENT_SCREEN_REFRESH
Where value and value2 are optional, and their meaning depends on the event subType.
Beware that different event types can use the same subType values, so you MUST check type before you check subType. When type is EVENT_x, you need to check for subTypes that begin with EVENT_x_. For example, when type is EVENT_KEY, you must check for the subTypes EVENT_KEY_ASCII & EVENT_KEY_SPECIAL.
Here is a description of subTypes, and what value & value2 mean (if anything):
EVENT_MOUSE_MOVE indicates that the mouse has been moved to x,y location value,value2. EVENT_MOUSE_SCROLL indicates that the scroll wheel has been moved by value,value2 for x,y steps. EVENT_MOUSE_DOUBLECLICK indicates the left mouse button has been double-clicked at x,y location value,value2. EVENT_MOUSE_LEFT indicates the left mouse button has been depressed at x,y location value,value2. EVENT_MOUSE_RIGHT indicates the right mouse button has been depressed at x,y location value,value2. EVENT_MOUSE_MIDDLE indicates the middle mouse button has been depressed at x,y location value,value2. EVENT_MOUSE_LEFTUP indicates the left mouse button has been raised at x,y location value,value2. EVENT_MOUSE_RIGHTUP indicates the right mouse button has been raised at x,y location value,value2. EVENT_MOUSE_MIDDLEUP indicates the middle mouse button has been raised at x,y location value,value2. EVENT_KEY_ASCII indicates that a normal key has been pressed, with "value" for the ascii code. EVENT_KEY_SPECIAL indicates that a special key has been pressed, with "value" being a constant (see later). EVENT_KEY_ASCIIUP indicates that a normal key has been released (with "value" for the ascii code). EVENT_KEY_SPECIALUP indicates that a special key has been released (with "value" being a constant). EVENT_WINDOW_CLOSE indicates that the user has asked the window to close. EVENT_WINDOW_ACTIVE indicates that the window became active (e.g. the user clicked on it). EVENT_WINDOW_INACTIVE indicates that the window became inactive (e.g. the user clicked on another window). EVENT_WINDOW_RESIZED indicates that the window has changed size (with value,value2 being the new width,height). EVENT_TIMER_EXPIRED indicates that a cGfx timer has completed the given time. EVENT_UNKNOWN_DONOTUSE should not be used! EVENT_SCREEN_REFRESH indicates a screen refresh has occured. It is not guaranteed to be available, and may even be removed in the future!
When subType is EVENT_KEY_SPECIAL, value can be one of these self-explanatory constants:
EVENT_KEY_SPECIAL_ENTER, EVENT_KEY_SPECIAL_ESCAPE, EVENT_KEY_SPECIAL_TAB, EVENT_KEY_SPECIAL_BACKSPACE, EVENT_KEY_SPECIAL_INSERT, EVENT_KEY_SPECIAL_DELETE, EVENT_KEY_SPECIAL_HOME, EVENT_KEY_SPECIAL_END, EVENT_KEY_SPECIAL_PAGEUP, EVENT_KEY_SPECIAL_PAGEDOWN, EVENT_KEY_SPECIAL_UP, EVENT_KEY_SPECIAL_DOWN, EVENT_KEY_SPECIAL_LEFT, EVENT_KEY_SPECIAL_RIGHT, EVENT_KEY_SPECIAL_LSHIFT, EVENT_KEY_SPECIAL_RSHIFT, EVENT_KEY_SPECIAL_LCTRL, EVENT_KEY_SPECIAL_RCTRL, EVENT_KEY_SPECIAL_LALT, EVENT_KEY_SPECIAL_RALT, EVENT_KEY_SPECIAL_LCOMMAND, EVENT_KEY_SPECIAL_RCOMMAND, EVENT_KEY_SPECIAL_F1, EVENT_KEY_SPECIAL_F2, EVENT_KEY_SPECIAL_F3, EVENT_KEY_SPECIAL_F4, EVENT_KEY_SPECIAL_F5, EVENT_KEY_SPECIAL_F6, EVENT_KEY_SPECIAL_F7, EVENT_KEY_SPECIAL_F8, EVENT_KEY_SPECIAL_F9, EVENT_KEY_SPECIAL_F10
What does a sub-class of cGfxDrawable actually do? It is an object which behaves very much like a cGfxBitmap, and so you can (for example) ask it to draw itself at a particular location, using it's draw(x,y) method.
Why would you want to do that? On it's own this isn't much use, but if you write some code that draws a user-supplied bitmap somewhere, then it might be handy if it could also draw other things. One obvious example is the 'std/cGfxSprites' module, which allows you to have sprites. In that case you can have sprites draw something other than a simple bitmap (e.g. some text that changes). A specific example can be found here:
Examples/std/Graphics/StarsXY_ToySpaceshipSprite1.e
This example has an animated "3D star field" as a drawable object, and uses this as the background upon which a spaceship sprite moves around.
So how do you go about creating a cGfxDrawable sub-class? The previously mentioned example gives a nice concrete demonstration of how to do it, but you might like to know the theory behind it...
First you should take a look at the 19.4. Methods of cGfxDrawable sub-chapter, to see what methods your object will have. Back again? There were rather a lot of methods, right? Don't worry about that! Many of them have sensible defaults, so you can probably get away with writing only the following methods:
METHOD infoWidth() RETURNS width METHOD infoHeight() RETURNS height METHOD draw(x, y)
They should be pretty self-explanatory. infoWidth() & infoHeight() simply report the actual size of your object. It is VERY important that your object has a fixed size. draw() simply uses the standard cGfx methods to draw your object at the given coordinates. It is VERY important that your object draws the same thing each time this method is called.
But what if you want to change the size of your object, or change what it draws? You can do that, but it should only happen when a method of your object is called. You will have to invent your own method! In the case of the previously mentioned example, the method is named setStarsOrigin() since it moves your viewpoint of the stars. In any case, it is VERY important that this method finishes with the following bit of code:
self.notifyClientsOfChange(oldWidth, oldHeight)
Where oldWidth & oldHeight give the OLD size of your object. You MUST do this even if your object's size has not changed, so that anything using your object will know that it's contents has changed, and thus redraw it if necessary.
But how does your object know it's size & target window in the first place? This is where your object's constructor comes in. While you can call this method anything you want, it is usual to call it new(). Thus you MIGHT have a constructor method that looks like this:
PROC new(win:PTR TO cGfxWindow, width, height) OF myDrawable self.addToGfx(win) self.width := width self.height := height ENDPROC
Note that your constructor MUST call the addToGfx() method. And you don't need to store win yourself, because it will do that for you in the inherited member self.gfx .
And then your object would look like this:
CLASS myDrawable OF cGfxDrawable width height ENDCLASS
And your "info" methods would look like this:
PROC infoWidth() OF myDrawable RETURNS width IS self.width PROC infoHeight() OF myDrawable RETURNS height IS self.height Of course your ||draw()|| method depends on exactly what your object draws! But it might look like this:
PROC draw(x, y) OF myDrawable
self.gfx.setColour($FF0000)
self.gfx.drawBox(x, y, self.width, self.height)
ENDPROC
You would create your object using code along these lines:
DEF foo:PTR TO myDrawable NEW foo.new(gfx, 100, 100)
If you are creating a drawable for use as a background for sprites (as in the previously mentioned example), then you should be aware of an extra limitation. Usually your drawable will be tiled, which means it must look ok when it is tiled. This is usually easy to manage for 2D effects, but if it contains a fake 3D perspective then you cannot normally do it. It just so happens that the fake 3D parallax algorithm used by the StarsXY_ToySpaceshipSprite1.e example can be tiled, but that is a very unusual case.
What about those other cGfxDrawable methods that we ignored? If your object is transparent (i.e. it does NOT draw every pixel within it's given size) then you will need to consider writing the following methods:
METHOD infoIsTransparent() RETURNS isTransparent:BOOL METHOD hitCheck(insideX, insideY) RETURNS hit:BOOL METHOD overlaps(drawable:PTR TO cGfxDrawable, insideX, insideY) RETURNS overlaps:BOOL
infoIsTransparent() must return TRUE. You can ignore the other two methods, unless you want to perform accurate collision-detection on your drawable object. hitCheck() shouldn't be too hard to write, but overlaps() may be impossible! Probably the best you can do for overlaps() is to check whether drawable is one of your own objects (using the IsOfClassType() method), and only in that case will you have enough information that you can perform a more accurate overlap check (in all other cases you will need to fall-back on the default parent method, by calling SUPER self.overlaps(drawable, insideX, insideY)).
But what about those other methods we ignored? If your object contains other drawables (typically bitmaps), then you will need to write the following methods:
METHOD changeUsageCount(increaseBy) METHOD registerForChanges( client:PTR TO cGfxNotifyOfDrawableChanges) METHOD unregisterForChanges(client:PTR TO cGfxNotifyOfDrawableChanges)
For each of these methods, you must call the same method on all the drawables you contain, and then call the parent method. For example, say that your drawable object contains the member picture:PTR TO cGfxBitmap, then your methods would look like this:
PROC changeUsageCount(increaseBy) OF myDrawable self.picture.changeUsageCount(increaseBy) SUPER self.changeUsageCount(increaseBy) ENDPROC PROC registerForChanges(client:PTR TO cGfxNotifyOfDrawableChanges) OF myDrawable self.picture.registerForChanges(client) SUPER self.registerForChanges(client) ENDPROC PROC unregisterForChanges(client:PTR TO cGfxNotifyOfDrawableChanges) OF myDrawable self.picture.unregisterForChanges(client) SUPER self.unregisterForChanges(client) ENDPROC
That should cover everything you need to know, but as this is quite an advanced subject, feel free to ask me about anything that is not clear. And of course remember to look at the StarsXY_ToySpaceshipSprite1.e example.
This module is the same as the cGfxSprites module (which provides sprite-based graphics), except that it provides a few extras to simplify things for beginners. Those extras are detailed below.
Beware that you canNOT use this module at the same time as the cGfxSimple module, to draw within the same window. Use one or the other, but not both at the same time.
Supported OSes: The same as cGfx.
When you use this module, it automatically uses the window you open:
IsDesktopApp() ->you only need to do this once! OpenWindow(640, 480)
Here's one way to create & move a sprite.
StoreBitmap('player', 0, LoadPicture('spaceship.gif'))
StoreSprite('player', 0, CreateSprite(20,20, LastBitmap()))
Pause(20) ->wait 2 seconds
UseSprite('player', 0).move(30,0) ->move the sprite horizontally
LastSprite().move(50,0) ->move the sprite again
Here's another way to create & move a sprite:
DEF playerSprite:PTR TO cGfxSprite, playerBitmap:PTR TO cGfxBitmap
playerBitmap := LoadPicture('spaceship.gif')
playerSprite := CreateSprite(20,20, playerBitmap)
Pause(20) ->wait 2 seconds
playerSprite.move(30,0) ->move the sprite horizontally
playerSprite.move(50,0) ->move the sprite again
Here's how to move a sprite smoothly:
SetAutoUpdate(FALSE)
REPEAT
playerSprite.move(1,0)
UpdateAndWaitForScreenRefresh()
UNTIL playerSprite.getPosition() >= InfoWidth()
The following example programs use it:
Examples/std/Graphics/StarsXY_ToySpaceshipSprite1.e Examples/std/Graphics/StarsZYX_ToySpaceshipSprite1.e Examples/std/Graphics/ToySpaceshipSprite1.e Examples/std/Graphics/ToySpaceshipSprite2.e Examples/std/Multimedia/ShadowOfTheBlitz_Scroller/SOTB.e
Released programs which are known to use it:
Ami-Ingenious ( os4depot.net/index.php?function=showfile&file=game/board/ami-ingenious.lha ) FlowerWay ( os4depot.net/?function=showfile&file=game/puzzle/flowerway.lha )
You do not need to use CreateGfxStack(), because it is automatically called, with the result stored in the gfxStack global variable. And the first layer is automatically stored in the gfxLayer global variable.
Note that you don't need to call CreateGfxWindow() either, because the cGfxSimple module is used.
PROC LastSprite() RETURNS sprite:PTR TO cGfxSprite
LastSprite() gives you the last sprite that was returned by one of the following procedures. If there was no last sprite, then it protects you by throwing an exception.
PROC DestroySprite(sprite:PTR TO cGfxSprite) RETURNS nil:PTR TO cGfxSprite PROC FindSpriteAt(x, y, lastMatch=NIL:PTR TO cGfxSprite) RETURNS match:PTR TO cGfxSprite PROC FindSpriteOverlapping(sprite:PTR TO cGfxSprite, lastMatch=NIL:PTR TO cGfxSprite) RETURNS match:PTR TO cGfxSprite PROC StoreSprite(name:ARRAY OF CHAR, number, sprite:PTR TO cGfxSprite) RETURNS storedSprite:PTR TO cGfxSprite PROC UseSprite( name:ARRAY OF CHAR, number, allowReturnNIL=FALSE:BOOL) RETURNS sprite:PTR TO cGfxSprite PROC SetBackgroundColour(rgb) PROC SetBackgroundDrawable(drawable=NIL:PTR TO cGfxDrawable, x=0, y=0, noTileX=FALSE:BOOL, noTileY=FALSE:BOOL, noScrollX=FALSE:BOOL, noScrollY=FALSE:BOOL) PROC ScrollAllSprites(dx, dy) PROC ScrollAllLayers(dx, dy)
These are the same as cGfxStack's methods (see chapter 21.3. Methods of cGfxStack), but they look simpler because they are procedures. Only the most important methods are available as procedures, and unlike the methods they start with a capital letter.
(Note that cGfxSimple's UpdateAndWaitForScreenRefresh() procedure is modified to automatically call cGfxStack's redraw() method, so you don't need to. And cGfxSimple's SetAutoUpdate() procedure is modified to automatically call cGfxStack's setAutoRedraw() method, so you don't need to. The upshot of this is that the sprite system will work much more efficiently when you use SetAutoUpdate(FALSE).)
PROC ScrollSprites(dx, dy) PROC ScrollLayer(dx, dy) PROC SetOrigin(x, y) PROC GetOrigin() RETURNS x, y PROC CreateSprite(x, y, drawable:PTR TO cGfxDrawable, hidden=FALSE:BOOL) RETURNS sprite:PTR TO cGfxSprite
These are the same as cGfxLayer's methods (see chapter 21.4. Methods of cGfxLayer), but they look simpler because they are procedures. They always operate on gfxLayer, which is the top layer of sprites. Only the most important methods are available as procedures, and unlike the methods they start with a capital letter.
PROC FullyRedrawSprites()
FullyRedrawSprites() will force all the sprites to be redrawn. This is useful if you want to "clean up" after have directly drawn in the window using 'std/cGfx'.
Don't forget the procedures from 21. MODULE 'std/cGfxSprites'.
This module provides fairly easy sprite-based graphics (and was written using the cGfx module itself).
While there are some advanced features, the default behaviour is quite simple: A cGfxStack covers the entire window, and is given the responsibility for all drawing in that window. It is a stack of cGfxLayers (you start with just one). Each cGfxLayer is a layer of cGfxSprites. And each cGfxSprite is just a bitmap that knows what position it should be drawn at.
A cGfxStack initially has one layer, and you can create sprites in that layer. You can change the position of sprites at any time, and see the result immediately.
You can get away with just using a single layer, but they are very handy for organising your sprites. For example:
Supported OSes: The same as cGfx.
The simplest way to create a stack:
DEF win:PTR TO cGfxWindow, stack:PTR TO cGfxStack
CreateApp().build()
win := CreateGfxWindow('demo')
win.openWindow(640, 480)
stack := CreateGfxStack(win)
How to create & move a sprite:
DEF layer:PTR TO cGfxLayer, sprite:PTR TO cGfxSprite
layer := stack.infoTopLayer()
sprite := layer.createSprite(20,20, win.loadPicture('SomePicture.jpg'))
Pause(20) ->wait 2 seconds
sprite.move(30,0) ->move the sprite horizontally
The following example programs use it:
Examples/std/Multimedia/ShootEmUp/ShootEmUp.e
Released programs which are known to use it:
PictureAlbum ( cshandley.co.uk )
PROC CreateGfxStack(gfx:PTR TO cGfxWindow) RETURNS stack:PTR TO cGfxStack PROC DestroyGfxStack(stack:PTR TO cGfxStack) RETURNS nil:PTR TO cGfxStack
CreateGfxStack() creates & returns a cGfxStack object using the supplied window. By default it covers the whole window, so you must use the setRegion() method if you want to change that.
DestroyGfxStack() destroys the supplied stack. It will also destroy all layers & sprites inside the stack. The stacks will be automatically destroyed when your program quits, so you may not need to use this! You may pass it a NIL parameter without any problem. It returns NIL for your convenience.
A single cGfxStack normally covers the entire window, but it can be restricted to a region. It is given the responsibility for all drawing (and refreshing) of it's region, so you must never (use a cGfxWindow or cGfxBitmap to) draw there yourself! A cGfxStack is a stack of cGfxLayers, with each layer on top of the next one.
/* Methods of cGfxStack */ METHOD infoTopLayer() RETURNS top:PTR TO cGfxLayer METHOD infoBottomLayer() RETURNS bottom:PTR TO cGfxLayer METHOD destroyLayer(layer:PTR TO cGfxLayer) RETURNS nil:PTR TO cGfxLayer METHOD destroySprite(sprite:PTR TO cGfxSprite) RETURNS nil:PTR TO cGfxSprite METHOD findSpriteAt(x, y, lastMatch=NIL:PTR TO cGfxSprite) RETURNS match:PTR TO cGfxSprite METHOD findSpriteOverlapping(sprite:PTR TO cGfxSprite, lastMatch=NIL:PTR TO cGfxSprite) RETURNS match:PTR TO cGfxSprite METHOD storeSprite(name:ARRAY OF CHAR, number, sprite:PTR TO cGfxSprite) RETURNS storedSprite:PTR TO cGfxSprite METHOD useSprite( name:ARRAY OF CHAR, number, allowReturnNIL=FALSE:BOOL) RETURNS sprite:PTR TO cGfxSprite
infoTopLayer() returns the layer at the top of the stack, whose sprites appear above all the other layers.
infoBottomLayer() returns the layer at the bottom of the stack, which is a special layer that is a solid (background) colour. You should not try to add sprites to this layer, nor destroy it.
destroyLayer() destroys the supplied layer, along with all it's sprites. You may pass it a NIL parameter without any problem. It returns NIL for your convenience.
destroySprite() destroys the supplied sprite. The sprite's bitmap/drawable will not be destroyed. You may pass it a NIL parameter without any problem. It returns NIL for your convenience.
findSpriteAt() searches all the layers (from the top downwards), looking for a sprite at the given position. It returns the first sprite that it finds. If you want to continue looking, then for lastMatch you must give the previously returned sprite.
findSpriteOverlapping() searches all the layers (from the top downwards), looking for a sprite which overlaps the given sprite. It returns the first sprite that it finds. If you want to continue looking, then for lastMatch you must give the previously returned sprite.
storeSprite() & useSprite() allow you to store & retrieve sprites using a name string, and optionally a number. The string must be an 'immediate string', not one you have created. It returns the stored sprite, so you can use it straight away. Here's an example of how you might use it:
stack.storeSprite('player', 0, layer.createSprite(x,y, playerBitmap, TRUE))
stack.useSprite('player', 0).setHidden(FALSE)
If you try to store more than one sprite with the same name & number combination, then an exception will be raised. This is to prevent you accidentally reusing them. And if you try to use a non-existant sprite, then an exception will be raised; unless you gave TRUE for allowReturnNIL, in which case NIL will be returned.
/* more methods of cGfxStack */ METHOD setBackgroundColour(rgb) METHOD getBackgroundColour() RETURNS rgb METHOD setBackgroundDrawable(drawable=NIL:PTR TO cGfxDrawable, x=0, y=0, noTileX=FALSE:BOOL, noTileY=FALSE:BOOL, noScrollX=FALSE:BOOL, noScrollY=FALSE:BOOL) METHOD getBackgroundDrawable() RETURNS drawable:PTR TO cGfxDrawable METHOD setRegion(x=0, y=0, width=-1, height=-1) METHOD getRegion() RETURNS x, y, width, height METHOD scrollAllSprites(dx, dy) METHOD scrollAllLayers(dx, dy)
setBackgroundColour() & getBackgroundColour() allow you to change & retrieve the colour of the special background layer.
setBackgroundDrawable() & getBackgroundDrawable() allow you to change & retrieve a drawable/bitmap for the special background layer. The drawable/bitmap will be tiled, unless you use noTileX & noTileY. The drawable/bitmap will be scrolled by the scrollAllSprites() & scrollAllLayers() methods, unless you use noScrollX & noScrollY, in which case scrolling canNOT be optimised. Note that if the bitmap has a mask then the background colour will show through.
setRegion() & getRegion() allow you to change & retrieve the rectangular region which the stack is responsible for drawing. If you set width/height to -1 then the right/bottom of the region is set to the edge of the window.
scrollAllSprites() causes all sprites to be to be moved by the same dx,dy pixels. It does this by changing the sprite positions. This is done very efficiently, without having to redraw most of the stack... UNLESS the background drawable is prevent from being scrolled (by noScrollX/Y). Or unless the scrolling is done in both X & Y directions.
You would tend to use this for game worlds where sprites only exist to be seen by the player (so you will want sprite positions to correspond to their on-screen position). For example Shoot-em'ups.
scrollAllLayers() causes all layers to be moved by dx,dy pixels (the sprites move along with their layer). It does this by changing the layer "origin". This is done very efficiently, without having to redraw most of the stack... UNLESS the background drawable is prevent from being scrolled (by noScrollX/Y)... Or unless the scrolling is done in both X & Y directions.
You would tend to use this for game worlds where sprites exist even when they cannot be seen by the player (so you will want the sprite positions to correspond to their position in the simulated game world). For example Real Time Strategy & RPG games.
/* more methods of cGfxStack */ METHOD setAutoRedraw(autoRedraw:BOOL) METHOD getAutoRedraw() RETURNS autoRedraw:BOOL METHOD redraw(forceFull=FALSE:BOOL)
setAutoRedraw() allows you to change whether the stack should automatically redraw itself after every change. It defaults to automatic redrawing, which is easier, but far less efficient.
If you disable autoRedraw then you must call the redraw() method when you have finished updating the stack. You would be advised to also disable cGfx's autoUpdate, and then call redraw() shortly before calling it's updateAndWaitForScreenRefresh() method. Note that the procedures of the 'std/cGfxSpriteSimple' module automatically call redraw(), so you don't have to.
getAutoRedraw() returns whether the stack is automatically redrawing or not.
redraw() forces the stack to redraw anything that you have changed since the last redraw(). If you give TRUE for forceFull then the entire stack will be redrawn, even where no sprites have changed. forceFull is useful if you want to "clean up" after have directly drawn inside the stack's area.
/* more methods of cGfxStack */ METHOD setAutoIsDrawable(autoIsDrawable:BOOL) METHOD getAutoIsDrawable() RETURNS autoIsDrawable:BOOL
setAutoIsDrawable() allows you to call cGfxLayer's setAutoIsDrawable() method on all the layers.
getAutoIsDrawable() returns the last value that the setAutoIsDrawable() method was called with. It is used by all layers that are created. By default autoIsDrawable is TRUE
Each cGfxLayer is a layer of cGfxSprites. Sprites in the layer above will always appear above the sprites in the layer below. Within a layer the sprites should not normally overlap, but if they do then those sprites will appear above or below each other according to their order in the layer (which you can change).
Sprite positions are relative to the "origin" of it's layer (which is normally the top left of the window). This can be used to make all the layer's sprites scroll in a direction.
/* Methods of cGfxLayer */ METHOD scrollSprites(dx, dy) METHOD scrollLayer(dx, dy) METHOD setOrigin(x, y) METHOD getOrigin() RETURNS x, y
scrollSprites() causes all sprites (on the layer) to be moved by dx,dy pixels. It does this by changing the sprite positions.
You would tend to use this for game worlds where sprites only exist to be seen by the player (so you will want sprite positions to correspond to their on-screen position). For example Shoot-em'ups.
scrollLayer() causes the layer to be moved by dx,dy pixels (the sprites will move along with the layer). It does this by changing the layer's "origin".
You would tend to use this for game worlds where sprites exist even when they cannot be seen by the player (so you will want the sprite positions to correspond to their position in the simulated game world). For example Real Time Strategy & RPG games.
setOrigin() & getOrigin() allow you to change & retrieve the "origin" of the layer, which will result in all the sprites moving.
/* more methods of cGfxLayer */ METHOD createSprite(x, y, drawable:PTR TO cGfxDrawable, hidden=FALSE:BOOL) RETURNS sprite:PTR TO cGfxSprite METHOD findSpriteAt(x, y, lastMatch=NIL:PTR TO cGfxSprite) RETURNS match:PTR TO cGfxSprite METHOD findSpriteOverlapping(sprite:PTR TO cGfxSprite, lastMatch=NIL:PTR TO cGfxSprite) RETURNS match:PTR TO cGfxSprite
createSprite() creates & returns a sprite at position x,y in the layer. You would usually give a bitmap for drawable, but other drawables (such as returned by the cGfx.makeText() method) are also fine. The sprite is created at the 'top' of the layer. If you give TRUE for hidden then the sprite won't be visible.
You can use the same bitmap/drawable for many sprites, allowing you to save video memory. But this also means you must NOT destroy the bitmap/drawable while you are using the sprite!
findSpriteAt() does the same as cGfxStack's findSpriteAt() method, except that it only searches this layer.
findSpriteOverlapping() does the same as cGfxStack's findSpriteOverlapping() method, except that it only searches this layer.
/* more methods of cGfxLayer */ METHOD createLayerBelow() RETURNS layer:PTR TO cGfxLayer METHOD infoAbove() RETURNS above:PTR TO cGfxLayer METHOD infoBelow() RETURNS below:PTR TO cGfxLayer METHOD infoHasSprites() RETURNS hasSprites:BOOL METHOD infoTopSprite() RETURNS sprite:PTR TO cGfxSprite METHOD infoBottomSprite() RETURNS sprite:PTR TO cGfxSprite
createLayerBelow() creates & returns a layer below the current one.
infoAbove() returns the layer above the current one, however if you are already on the top layer, then the bottom layer will be returned!
infoBelow() returns the layer below the current one, however if you are already on the bottom layer, then the top layer will be returned!
infoHasSprites() returns whether or not the layer contains any sprites.
infoTopSprite() returns the sprite at the top of the layer, which appears above all other sprites in that layer. If there are no sprites then an exception will be raised, so you should first check using infoHasSprites().
infoBottomSprite() returns the sprite at the bottom of the layer.
/* more methods of cGfxLayer */ METHOD setAutoIsDrawable(autoIsDrawable:BOOL) METHOD getAutoIsDrawable() RETURNS autoIsDrawable:BOOL
setAutoIsDrawable() allows you to change whether the sprites in this layer have their bitmaps/etc automatically made drawable or not (using cGfxBitmap's setIsDrawable() method) according to whether they are visible in the stack's region or not. Thus if a bitmap is not being used by any sprite that can be seen, then it will be made non-drawable, and so save your precious video memory! The downside to this is that it takes a short while to load the bitmap back into memory (when it becomes visible again), but you should not notice this unless many (or huge) bitmaps have to be loaded back at the same time.
The stack defaults to creating all layers with TRUE for autoIsDrawable.
getAutoIsDrawable() returns whether the sprites in this layer have their bitmaps/drawables automatically made drawable or not.
Each cGfxSprite is a bitmap that will be drawn at a given position. The position of sprites are unaffected by where cGfxStack's region is, and so are normally given using their actual position in the window. However, if the "origin" of the layer is moved away from the top left corner of the window, then the visible position of all sprites will be moved along with it.
/* Methods of cGfxSprite */ METHOD infoWidth() RETURNS width METHOD infoHeight() RETURNS height METHOD infoLayer() RETURNS layer:PTR TO cGfxLayer METHOD infoAbove() RETURNS sprite:PTR TO cGfxSprite METHOD infoBelow() RETURNS sprite:PTR TO cGfxSprite METHOD infoIsInsideRegion(fullyInside=FALSE:BOOL) RETURNS insideRegion:BOOL
infoWidth() & infoHeight() return the size of the sprite.
infoLayer() returns the layer the sprite is in.
infoAbove() returns the sprite above the current one, however if you are already on the top sprite, then the bottom sprite will be returned!
infoBelow() returns the sprite below the current one, however if you are already on the bottom sprite, then the top sprite will be returned!
infoIsInsideRegion() returns whether the sprite is inside the stack's region (and thus potentially visible). By default fullyInside is FALSE, which means it returns TRUE even if the sprite is only partially inside the region. If you give TRUE for fullyInside then it only returns TRUE if the sprite is completely inside the region.
/* more methods of cGfxSprite */ METHOD move(dx, dy) METHOD setPosition(x, y) METHOD getPosition() RETURNS x, y METHOD setHidden(hidden:BOOL) METHOD getHidden() METHOD setDrawable(drawable:PTR TO cGfxDrawable, frame=0) METHOD getDrawable(frame=0) RETURNS drawable:PTR TO cGfxDrawable METHOD setFrame(frame) RETURNS exists:BOOL METHOD getFrame() RETURNS frame METHOD setTiled(tileX:BOOL, tileY:BOOL) METHOD getTiled() RETURNS tileX:BOOL, tileY:BOOL METHOD setData(data) METHOD getData() RETURNS data METHOD setDataPtr(data:PTR) METHOD getDataPtr() RETURNS data:PTR
move() allows you to change the sprite's position by dx,dy pixels.
setPosition() & getPosition() allow you to change & retrieve the position of the sprite within the layer. The position is relative to the layer's "origin".
setHidden() & getHidden() allow you to change & retrieve whether the sprite is invisible or not.
setDrawable() & getDrawable() allow you to change & retrieve the bitmap/drawable used by the sprite. If you supply a frame number, then you will store & retrieve the bitmap/drawable of the given animation frame.
Rather than just changing frame 0 to change the sprite's appearance, you should let the sprite know all the frames it will be showing, and then using setFrame() to change the shown frame. Not only is this easier to manage sprite animation, but the sprite will ensure that all frames are drawable (when autoIsDrawable is enabled) so that your animations are smooth.
setFrame() & getFrame() allow you to change & retrieve the currently shown frame number. setFrame() will return TRUE for exists when the given frame existed.
setTiled() & getTiled() allow you to change & retrieve whether the sprite is tiled across the whole window or not. Normal sprites are NOT tiled, but if you make them tiled then they appear to be infinitely wide (when tileX is TRUE) and/or infinitely tall (when tileY is TRUE). When tiled, their drawable will be repeated in a 'tiled' fashion, thus allowing you to easily have background(s) that go on 'forever'.
Note that tiled sprites can still be moved by changing their position. And you can still perform collision (hit/overlap) checks with tiled sprites.
setData() & getData() allow you to store & retrieve one piece of data for each sprite. If you need to store an object pointer, then please use setDataPtr() & getDataPtr() instead.
setDataPtr() & getDataPtr() allow you to store & retrieve one piece of data for each sprite. This data is a pointer to something, typically an object related to the sprite. This object is not automatically deallocated, so you may need to keep track of them.
/* more methods of cGfxSprite */ METHOD overlaps(sprite:PTR TO cGfxSprite) RETURNS overlaps:BOOL METHOD moveToBottomOfLayer() METHOD moveToTopOfLayer() METHOD clone() RETURNS clone:PTR TO cGfxSprite
overlaps() returns whether the given sprite overlaps the current sprite. Bitmap masks are taken into account.
moveToBottomOfLayer() allows you to move the sprite to the 'bottom' of the layer, so all other sprites in the layer will appear above it.
moveToTopOfLayer() allows you to move the sprite to the 'top' of the layer, so all other sprites in the layer will appear below it.
clone() returns a new sprite, which is identical to the current one.
This module provides a fairly easy way of creating a GUI. It will look like a native GUI (such as MUI), but you don't need to know anything about the native GUI system, as it behaves the same whatever native GUI is used. It is rather easier to use than MUI, but not as flexible.
Currently it uses MUI (for all Amiga OSes), but it is hoped that eventually Reaction will be used for AmigaOS4.
Please note that this is not finished, and more advanced features are planned for the future.
Supported OSes: AmigaOS4, AmigaOS3, AROS, MorphOS.
How to open a GUI window:
DEF win:PTR TO cGuiWindow, button:PTR TO cGuiButton
CreateApp().build() ->you only need to do this once!
win := CreateGuiWindow('demo')
win.beginGroupVertical()
win.addTextBox('label').setState('Hello world!').initFixedFont()
button := win.addButton('OK')
win.endGroup()
win.build()
How to handle events from a single open window:
DEF quit:BOOL, item:PTR TO cGuiItem quit := FALSE REPEAT item := WaitForChangedGuiItem() IF item = NIL IF win.getCloseRequest() THEN quit := TRUE ELSE IF item = button quit := TRUE ENDIF UNTIL quit win.close()
How to handle events with SEVERAL open windows:
DEF quit:BOOL, item:PTR TO cGuiItem, itemWin:PTR TO cGuiWindow quit := FALSE REPEAT item, itemWin := WaitForChangedGuiItem() IF itemWin = win ->handle items of the "win" window IF item = NIL IF win.getCloseRequest() THEN quit := TRUE ELSE IF item = button quit := TRUE ENDIF ENDIF UNTIL quit win.close()
The following example programs use it:
Examples/std/GUI/SimpleCalculator.e Examples/std/GUI/SimpleModPlayer.e
Released programs which are known to use it:
PictureAlbum ( cshandley.co.uk ) AmiSystemRestore ( os4depot.net/?function=showfile&file=utility/misc/amisystemrestore.lha ) Ami-Ingenious ( os4depot.net/index.php?function=showfile&file=game/board/ami-ingenious.lha ) FlowerWay ( os4depot.net/?function=showfile&file=game/puzzle/flowerway.lha ) HueFlow ( os4depot.net/?function=showfile&file=game/puzzle/hueflow.lha ) Ami-Scratch ( os4depot.net/?function=showfile&file=graphics/misc/amiscratch.lha ) Ami-Bootguard ( os4depot.net/?function=showfile&file=utility/misc/ami-bootguard.lha ) Ami-Lineapolis ( www.lineapolis.dizzy.pl )
CreateGuiWindow(title:ARRAY OF CHAR) RETURNS win:PTR TO cGuiWindow DestroyGuiWindow(win:PTR TO cGuiWindow) RETURNS nil:PTR TO cGuiWindow WaitForChangedGuiItem() RETURNS item:PTR TO cGuiItem, win:PTR TO cGuiWindow CheckForChangedGuiItem(keepPreviousChangedItems=FALSE:BOOL) RETURNS item:PTR TO cGuiItem, win:PTR TO cGuiWindow
CreateGuiWindow() creates & returns a cGuiWindow object for a new GUI window. You must supply a title (i.e. name) for your window. You must add GUI items to it, before building it. You can create as many windows as you want!
DestroyGuiWindow() destroys the supplied window, and it's contents. Your windows will be automatically destroyed when your program quits, so you may not need to use this! You may pass it a NIL parameter without any problem. It returns NIL for your convenience.
WaitForChangedGuiItem() waits for a GUI item to be changed by the user (in any window). It then returns that item. You should find what has changed by checking the item's state (typically using the item's getState() method).
CheckForChangedGuiItem() checks whether any GUI item has been changed yet, and returns it if it has. But if nothing has changed, then it returns NIL for item. This method DOES clear the last event from all windows (except for the current one), unless you supplied TRUE for keepPreviousChangedItems.
The cGuiWindow class is a window which contains a GUI. You must add GUI items to it, before building it. Once a GUI window is built, you cannot add any more GUI items. (In the future things may become a little more flexible.) Building the GUI will also open the window, unless you indicate otherwise. Windows may be opened & closed at any time.
GUI items are arranged within the window using groups, normally as horizontal & vertical rows. You can have groups inside of groups, which gives great flexibility. Beware that you cannot add any items to a window, until you have started a group.
Once a window is built, you must use the WaitForChangedGuiItem() or CheckForChangedGuiItem() procedure in a loop. They will tell you when the user changes a GUI item, as well as ensuring the GUI reacts to the user. You can also set GUI items to call a notification function when the user changes them.
/* Methods of cGuiWindow */ METHOD beginGroupHorizontal(borderTitle=NILA:ARRAY OF CHAR) RETURNS item:PTR TO cGuiGroupHorizontal METHOD beginGroupVertical( borderTitle=NILA:ARRAY OF CHAR) RETURNS item:PTR TO cGuiGroupVertical METHOD beginGroupGrid(width,borderTitle=NILA:ARRAY OF CHAR) RETURNS item:PTR TO cGuiGroupGrid METHOD beginGroupPage( borderTitle=NILA:ARRAY OF CHAR) RETURNS item:PTR TO cGuiGroupPage METHOD endGroup()
beginGroupHorizontal() marks the beginning of a horizontal group. All items in the group will be arranged horizontally. See 22.14. Methods of cGuiGroupHorizontal & cGuiGroupVertical for more info.
NOTE: If you give a borderTitle then the whole group itself has a name, and the group will gain a border if it doesn't already have one.
beginGroupVertical() marks the beginning of a vertical group. All items in the group will be arranged vertically. See 22.14. Methods of cGuiGroupHorizontal & cGuiGroupVertical for more info.
beginGroupGrid() marks the beginning of a grid group. All items in the group will be arranged in a grid.
You must give the width of the grid in items. Items added to the group get put in the first row, as if it was a horizontal group, but after width items have been added, further items will go into the next row, etc. See 22.15. Methods of cGuiGroupGrid for more info.
beginGroupPage() marks the beginning of a multi-page group. Each item in the group is treated as a separate "page", with only one page visible at a time. Normally each item would be a horizontal or vertical group. See 22.16. Methods of cGuiGroupPage for more info.
endGroup() marks the end of the current group.
/* more methods of cGuiWindow */ METHOD addBreak() METHOD addBar( title=NILA:ARRAY OF CHAR) METHOD addLabel( label:ARRAY OF CHAR) RETURNS item:PTR TO cGuiLabel METHOD addText( label:ARRAY OF CHAR) RETURNS item:PTR TO cGuiText METHOD addTextBox( label:ARRAY OF CHAR) RETURNS item:PTR TO cGuiTextBox METHOD addButton( label:ARRAY OF CHAR) RETURNS item:PTR TO cGuiButton METHOD addTick( label:ARRAY OF CHAR) RETURNS item:PTR TO cGuiTick METHOD addString( label:ARRAY OF CHAR) RETURNS item:PTR TO cGuiString METHOD addStringBox( label:ARRAY OF CHAR) RETURNS item:PTR TO cGuiStringBox METHOD addPathString( label:ARRAY OF CHAR) RETURNS item:PTR TO cGuiPathString METHOD addNumberString(label:ARRAY OF CHAR, min, max) RETURNS item:PTR TO cGuiNumberString METHOD addSlider( label:ARRAY OF CHAR, min, max) RETURNS item:PTR TO cGuiSlider METHOD addCycleChoice( label:ARRAY OF CHAR, stringChoices:ARRAY OF ARRAY OF CHAR) RETURNS item:PTR TO cGuiCycleChoice METHOD addRadioChoice( label:ARRAY OF CHAR, stringChoices:ARRAY OF ARRAY OF CHAR) RETURNS item:PTR TO cGuiRadioChoice METHOD infoCurrentBuildGroup() RETURNS item:PTR TO cGuiGroupItem
addBreak() adds an invisible separator (typically in a vertical group) between items, such that the items either side of the break are not aligned. It has a similar effect to addBar(), but there is no line visible.
addBar() adds a horizontal/vertical line (in a vertical/horizontal group). Used to clearly separate items within a group, and items either side of the line are not aligned. It may be given a title. See 22.17. Methods of cGuiBar for more info.
addLabel() adds text that looks the same as the labels of other items. It is typically used for displaying a single line of text, or as an 'empty item' in a page group. See 22.18. Methods of cGuiLabel for more info.
But it can also be used to fake your own "custom item". For example you can have a horizontal group, add an item with no label, and then add the label after it, to get a "custom item" that has the label on the right (instead of the left).
addText() adds a text line, for displaying a single line of text. You must supply the item's label. It's setState() method must be used to set the string to be displayed. See 22.19. Methods of cGuiText for more info.
addTextBox() adds a text box, for displaying multiple lines of text. You must supply the item's label. It's setState() method must be used to set the string to be displayed. See 22.20. Methods of cGuiTextBox for more info.
addButton() adds a button, which the user can click on. You must supply the item's label. See 22.21. Methods of cGuiButton for more info.
addTick() adds a tick button, which the user can toggle ticked or unticked. You must supply the item's label. It's setState() method can be used to set whether it is ticked or not. See 22.22. Methods of cGuiTick for more info.
addString() adds a string input line. You must supply the item's label. It's setState() method can be used to set the shown string. See 22.23. Methods of cGuiString for more info.
addStringBox() adds a multi-line string input box. You must supply the item's label. It's setState() method can be used to set the shown string. See 22.24. Methods of cGuiStringBox for more info.
addPathString() adds a path input line, for choosing the file/dir path of something. Typically it has a button that will open a file requester. You must supply the item's label. See 22.25. Methods of cGuiPathString for more info.
addNumberString() adds a number input line. You must supply the item's label, and the min & max allowed values. It's setState() method can be used to set the shown value. See 22.26. Methods of cGuiNumberString for more info.
addSlider() adds a slider, for choosing a number. You must supply the item's label, and the min & max allowed values. It's setState() method can be used to set the slider's position. See 22.27. Methods of cGuiSlider for more info.
addCycleChoice() adds a cyclable/pop-up choice box, for choosing from several fixed options. You must supply the item's label, and the list of actual choices for stringChoices, which must end with NILA:
e.g. ['first choice', 'second choice', 'etc', NILA]:ARRAY_OF_CHAR
It's setState() method can be used to set the selected choice. See 22.28. Methods of cGuiCycleChoice for more info.
addRadioChoice() adds a radio-style choice list, for choosing from several fixed options. You must supply the item's label, and the list of actual choices for stringChoices, which must end with NILA:
e.g. ['first choice', 'second choice', 'etc', NILA]:ARRAY_OF_CHAR
It's setState() method can be used to set the selected choice. See 22.29. Methods of cGuiRadioChoice for more info.
infoCurrentBuildGroup() returns the current group that items are being added to. You are unlikely to need this method.
/* more methods of cGuiWindow */ METHOD beginFixedList(columns=1, borderTitle=NILA:ARRAY OF CHAR) OF cGuiWindow RETURNS item:PTR TO cGuiFixedList METHOD endFixedList() METHOD addFixedListEntry(label:ARRAY OF CHAR) OF cGuiWindow RETURNS item:PTR TO cGuiFixedListEntry
beginFixedList() marks the beginning of a fixed list. columns defines how many 'vertically aligned labels' (aka columns) the list has. If you give a borderTitle then the whole list itself has a name, and the list will gain a border if it doesn't already have one. You may only add fixed list entries to it. See 22.30. Methods of cGuiFixedList for more info.
endFixedList() marks the end of the fixed list.
addFixedListEntry() adds an entry to the fixed list. Each entry is a single line of text, and they appear in the order they are added. The label defines the text for ALL columns of an entry, with each column being separated by a \t character. Each entry will have a tick box if the list was defined as having selectable entries. BEWARE that it always returns item=NIL if there is no tick box. See 22.31. Methods of cGuiFixedListEntry for more info.
/* more methods of cGuiWindow */ METHOD build(keepWindowClosed=FALSE:BOOL) METHOD open() METHOD close() METHOD infoIsOpen() METHOD infoTitle() RETURNS title:ARRAY OF CHAR
build() takes all the added GUI items, and creates the GUI using them. It then automatically opens the window, unless you gave TRUE for keepWindowClosed.
open() opens the window, so that it is visible.
close() closes the window, so that it is hidden. The GUI items will remember their last state, so they will appear about the same when the window is reopened.
infoIsOpen() returns whether the window is open or not.
infoTitle() returns the title you set using the CreateGuiWindow() procedure.
/* more methods of cGuiWindow */ METHOD getLastChangedItem() RETURNS item:PTR TO cGuiItem METHOD setLastChangedItem(item:PTR TO cGuiItem) METHOD getCloseRequest() RETURNS closeRequest:BOOL METHOD setCloseRequest(closeRequest:BOOL) METHOD getQuitRequest() RETURNS quitRequest:BOOL METHOD setQuitRequest(quitRequest:BOOL) METHOD getBusy() RETURNS busy:BOOL METHOD setBusy(busy:BOOL)
getLastChangedItem() returns the last item that was changed by the user.
setLastChangedItem() allows you to change (or clear) the indication of the last item that was changed by the user.
getCloseRequest() returns whether the window has received a close request, say due to the user clicking on the close button.
setCloseRequest() allows you to change (or clear) the close request indication.
getQuitRequest() returns whether the App has received a quit request. All windows will receive the same quit request.
setQuitRequest() allows you to change (or clear) the quit request. This is shared by all windows.
getBusy() & setBusy() allow you to change & retrieve the window's busy state. A busy window will not accept user input, and the user will be able to see that the window is busy (depending on the target OS & GUI, it might appear ghosted or the mouse pointer might be an hourglass).
/* more methods of cGuiWindow */ METHOD getPosition() RETURNS x, y METHOD setPosition(x, y) METHOD infoWidth() RETURNS width METHOD infoHeight() RETURNS height METHOD changeSize(width, height) METHOD queryExtra(specific:QUAD) RETURNS value, unknown:BOOL
getPosition() return the position of the window.
setPosition() changes the position of the window. This can be done before the window is opened.
infoWidth() & infoHeight() return the size of the window.
changeSize() changes the size of the window.
queryExtra() allows you to retrieve OS-specific information. For example, if you give "OBJT", then it will return the Amiga MUI window object. And "SIGS" will return all the Amiga MUI signals. Please only use this method as a last resort, because it will stop your code from being portable!
The following GUI item classes are "abstract", which means they are never directly used for created objects. Instead they are used as parents of classes, to help organise similar GUI items together, and to allow them to share (some of) the same methods.
For example, the abstract cGuiInputItem class is used by all GUI items that allow the user to provide input, such as cGuiStringBox (but unlike cGuiLabel). The cGuiInputItem class (and all the classes that use it) has the setGhosted() method, which allows you to "ghost" the GUI item, preventing the user from changing it.
The name of every abstract class ends in "Item".
All GUI items eventually inherit this class. The main purpose is to allow all GUI items to be given to or returned as a PTR TO cGuiItem.
/* Methods of cGuiItem */ METHOD setData(data) RETURNS self:PTR TO cGuiItem METHOD getData() RETURNS data IS self.data METHOD infoNextInGroup() RETURNS item:PTR TO cGuiItem
setData() & getData() allow you to store & retrieve one value. This is useful if you have a large number of GUI items, and want to identify them by sequential numbers rather than having to each of their object pointers.
infoNextInGroup() returns the next item in the current group. You probably won't need to use this.
All groups inherit this class, and they are GUI items themselves.
/* Methods of cGuiGroupItem, which inherits from cGuiItem */ METHOD initScrollable() RETURNS self:PTR TO cGuiGroupItem METHOD initEqualSizedItems() RETURNS self:PTR TO cGuiGroupItem METHOD infoHasBorder() RETURNS hasBorder:BOOL METHOD infoTitle() RETURNS title:ARRAY OF CHAR METHOD infoSize() RETURNS size METHOD infoFirstItem() RETURNS item:PTR TO cGuiItem METHOD infoLastItem() RETURNS item:PTR TO cGuiItem METHOD infoScrollable() RETURNS scrollable:BOOL METHOD infoEqualSizedItems() RETURNS equalSizedItems:BOOL METHOD setGhosted(ghosted:BOOL) RETURNS self:PTR TO cGuiGroupItem ->plus methods inherited from cGuiItem
For the inherited methods read 22.5. Methods of cGuiItem.
initScrollable() indicates that the group does not need to completely fit inside the window, and so will scroll if the window is too small.
initEqualSizedItems() indicates that all items in the group should have the same size (where possible).
infoHasBorder() returns TRUE if the group has a border, which it will if it was created with a string given to borderTitle.
infoTitle() returns the group's title, if it was not created with a non-empty string for borderTitle, otherwise it returns NILA. i.e. It returns NILA if '' was given for borderTitle.
infoSize() returns the number of items inside of the group.
infoFirstItem() returns the first item in the group.
infoLastItem() returns the last item in the group.
infoScrollable() returns whether initScrollable() was used or not.
infoEqualSizedItems() returns whether initEqualSizedItems() was used or not.
setGhosted() calls the setGhosted() method on all the group's items.
This is inherited by any GUI item with a label. So it is used by most GUI items!
/* Methods of cGuiLabelledItem, which inherits from cGuiItem */ METHOD infoLabel() RETURNS label:ARRAY OF CHAR ->plus methods inherited from cGuiItem
For the inherited methods read 22.5. Methods of cGuiItem.
infoLabel() returns the label that the GUI item was created with.
This is inherited by any GUI item that can display some data. So it is used by most GUI items! It allows you to add a pop-up description to it.
/* Methods of cGuiOutputItem, which inherits from cGuiLabelledItem */ METHOD initUseLeastSpace() RETURNS self:PTR TO cGuiOutputItem METHOD infoUseLeastSpace() RETURNS useLeastSpace:BOOL METHOD setPopupHint(popupHint:NULL ARRAY OF CHAR) RETURNS self:PTR TO cGuiOutputItem METHOD getPopupHint() RETURNS popupHint:ARRAY OF CHAR ->plus methods inherited from cGuiLabelledItem
For the inherited methods read 22.7. Methods of cGuiLabelledItem.
initUseLeastSpace() indicates that the GUI item should use as little space as possible. Beware that this could cause your window to have a fixed size.
NOTE: This does not yet do anything for some GUI items.
infoUseLeastSpace() returns whether initUseLeastSpace() was used or not.
setPopupHint() & getPopupHint() allow you to change & retrieve a pop-up description to help the user. getPopupHint() will return NILA if there is no hint, while setPopupHint() may be supplied NILA to clear any existing hint. But don't rely on being able to change the pop-up hint after the GUI is built.
This is inherited by any GUI item that can accept some input from the user. It allows you to ghost the item, so that the user cannot change it. It also allows you to have a function called when the user changes it.
/* Methods of cGuiInputItem, which inherits from cGuiOutputItem */ METHOD setGhosted(ghosted:BOOL) RETURNS self:PTR TO cGuiInputItem METHOD getGhosted() RETURNS ghosted:BOOL METHOD setNotifyFunction(func:NULL PTR TO funcGuiNotify) RETURNS self:PTR TO cGuiItem METHOD getNotifyFunction() RETURNS func:PTR TO funcGuiNotify ->plus methods inherited from cGuiOutputItem
For the inherited methods read 22.8. Methods of cGuiOutputItem.
setGhosted() & getGhosted() allow you to change & retrieve the ghosted state. A ghosted item should not accept any user input.
setNotifyFunction() & getNotifyFunction() allow you to store & retrieve the notification function, which will be called whenever the user makes any changes. Your notification function must inherit funcGuiNotify, for example:
FUNC yourNotification(changedItem:PTR TO cGuiItem) OF funcGuiNotify IS ...
This is inherited by any GUI item that allows the user to change a string.
/* Methods of cGuiStringItem, which inherits from cGuiInputItem */ METHOD setState(string:ARRAY OF CHAR) RETURNS self:PTR TO cGuiStringItem METHOD getState() RETURNS string:ARRAY OF CHAR ->plus methods inherited from cGuiInputItem
For the inherited methods read 22.9. Methods of cGuiInputItem.
setState() & getState() allow you to change & retrieve the displayed string.
This is inherited by any GUI item that allows the user to change a number.
/* Methods of cGuiNumberItem, which inherits from cGuiInputItem */ METHOD setState(number) RETURNS self:PTR TO cGuiNumberItem METHOD getState() RETURNS number METHOD initUnit(unit:ARRAY OF CHAR) RETURNS self:PTR TO cGuiNumberItem METHOD infoUnit() RETURNS unit:ARRAY OF CHAR METHOD infoMin() RETURNS min METHOD infoMax() RETURNS max ->plus methods inherited from cGuiInputItem
For the inherited methods read 22.9. Methods of cGuiInputItem.
setState() & getState() allow you to change & retrieve the displayed number.
initUnit() sets the unit the number is a measure of; for example 'miles'.
infoUnit() returns the unit set using initUnit(), or NILA if none was set.
infoMin() & infoMax() returns the min & max values given when the item was created.
This is inherited by any GUI item that allows the user to choose from a list of several fixed options.
/* Methods of cGuiChoiceItem, which inherits from cGuiNumberItem */ METHOD setState(choice) RETURNS self:PTR TO cGuiChoiceItem METHOD getState() RETURNS choice METHOD infoChoices() RETURNS choices:ARRAY OF ARRAY OF CHAR ->plus methods inherited from cGuiNumberItem
For the inherited methods read 22.11. Methods of cGuiNumberItem.
setState() & getState() allow you to change & retrieve the currently selected choice.
infoChoices() returns the stringChoices given when the item was created.
The following GUI item classes are "real", which means they will be directly used for created objects. They will inherit an "abstract" class according to the kind of GUI items they are.
For example, the real cGuiStringBox class is an actual GUI item that you can add to the window. It inherits the abstract cGuiStringItem class, because it allows the user to change a string.
These are classes which arrange their GUI items in a horizontal or vertical row.
/* Methods of cGuiGroupHorizontal & cGuiGroupVertical, which inherits from cGuiGroupItem */ ->plus methods inherited from cGuiGroupItem
For the inherited methods read 22.6. Methods of cGuiGroupItem.
This class arranges it's GUI items in a grid.
/* Methods of cGuiGroupGrid, which inherits from cGuiGroupItem */ ->plus methods inherited from cGuiGroupItem
For the inherited methods read 22.6. Methods of cGuiGroupItem.
This class is a multi-page group. Each item in it is treated as a separate "page", with only one page visible at a time. Normally each item would be a horizontal or vertical group.
/* Methods of cGuiGroupPage, which inherits from cGuiGroupItem */ METHOD setState(pageNumber) RETURNS self:PTR TO cGuiGroupPage METHOD getState() RETURNS pageNumber METHOD setStateItem(pageItem:PTR TO cGuiItem) RETURNS self:PTR TO cGuiGroupPage METHOD getStateItem() RETURNS pageItem:PTR TO cGuiItem METHOD infoMaxPageNum() RETURNS pageNum METHOD infoPageNumOfPageItem(pageItem:PTR TO cGuiItem) RETURNS pageNumber METHOD infoPageItemOfPageNum(pageNumber) RETURNS pageItem:PTR TO cGuiItem ->plus methods inherited from cGuiGroupItem
For the inherited methods read 22.6. Methods of cGuiGroupItem.
setState() & getState() allow you to change & retrieve the currently shown page, using the page number. The first page is number 0.
setStateItem() & getStateItem() allow you to change & retrieve the currently shown page, using the actual page item to be shown.
infoMaxPageNum() returns the largest page number that exists.
infoPageNumOfPageItem() returns the page number of the provided page item.
infoPageItemOfPageNum() returns the page item of the provided page number.
This class is a horizontal/vertical line (in a vertical/horizontal group). It is used to clearly separate items within a group.
/* Methods of cGuiBar, which inherits from cGuiItem */ METHOD infoTitle() RETURNS title:ARRAY OF CHAR ->plus methods inherited from cGuiItem
For the inherited methods read 22.5. Methods of cGuiItem.
infoTitle() returns the title given when the item was created, or NILA if none was given.
This class shows some text that looks the same as the labels of other items.
/* Methods of cGuiLabel, which inherits from cGuiOutputItem */ METHOD initAlignLeft() RETURNS self:PTR TO cGuiLabel METHOD initAlignCenter() RETURNS self:PTR TO cGuiLabel METHOD initAlignRight() RETURNS self:PTR TO cGuiLabel METHOD infoAlignLeft() RETURNS isAlignedLeft :BOOL METHOD infoAlignCenter() RETURNS isAlignedCenter:BOOL METHOD infoAlignRight() RETURNS isAlignedRight :BOOL METHOD initAltColour() RETURNS self:PTR TO cGuiLabel ->plus methods inherited from cGuiOutputItem
For the inherited methods read 22.8. Methods of cGuiOutputItem.
initAlignLeft(), initAlignCenter() & initAlignRight() indicates that the label should be left/center/right aligned. By default the alignment is the same as that used by the labels of other GUI items.
infoAlignCenter(), infoAlignCenter() & infoAlignRight() returns whether initAlignLeft(), initAlignCenter() & initAlignRight() was used or not.
initAltColour() indicates that the label should be shown in an alternative (typically more noticable) colour.
This class shows a single line of text. It usually defaults to a variable-width font, but it can use a fixed-width (mono-spaced) font if you want.
/* Methods of cGuiText, which inherits from cGuiOutputItem */ METHOD setState(text:ARRAY OF CHAR) RETURNS self:PTR TO cGuiText METHOD getState() RETURNS text:ARRAY OF CHAR METHOD initFixedFont() RETURNS self:PTR TO cGuiTextBox METHOD initAlignCenter() RETURNS self:PTR TO cGuiTextBox METHOD initAlignRight() RETURNS self:PTR TO cGuiTextBox METHOD infoFixedFont() RETURNS fixedFont:BOOL METHOD infoAlignCenter() RETURNS isAlignedCenter:BOOL METHOD infoAlignRight() RETURNS isAlignedRight :BOOL ->plus methods inherited from cGuiOutputItem
For the inherited methods read 22.8. Methods of cGuiOutputItem.
setState() & getState() allow you to change & retrieve the currently shown text.
initFixedFont() indicates that a fixed-width font should be used. This must be called before the GUI is built.
initAlignCenter() & initAlignRight() indicates that the shown text should be center/right aligned (rather than the default of left alignment).
infoFixedFont() returns whether initFixedFont() was used or not.
infoAlignCenter() & infoAlignRight() returns whether initAlignRight() or initAlignCenter() was used or not.
This class shows multiple lines of text. It usually defaults to a variable-width font, but it can use a fixed-width (mono-spaced) font if you want.
/* Methods of cGuiTextBox, which inherits from cGuiOutputItem */ METHOD setState(text:ARRAY OF CHAR) RETURNS self:PTR TO cGuiTextBox METHOD getState() RETURNS text:ARRAY OF CHAR METHOD initFixedFont() RETURNS self:PTR TO cGuiTextBox METHOD infoFixedFont() RETURNS fixedFont:BOOL ->plus methods inherited from cGuiOutputItem
For the inherited methods read 22.8. Methods of cGuiOutputItem.
setState() & getState() allow you to change & retrieve the currently shown text.
initFixedFont() indicates that a fixed-width font should be used. This must be called before the GUI is built.
infoFixedFont() returns whether initFixedFont() was used or not.
This class is for a button, which the user can click on. Although it has no "state", you will still be notified that is has changed when the user clicks on it.
/* Methods of cGuiButton, which inherits from cGuiInputItem */ METHOD initPic(picPath:ARRAY OF CHAR) RETURNS self:PTR TO cGuiInputItem METHOD infoPic() RETURNS picPath:ARRAY OF CHAR ->plus methods inherited from cGuiInputItem
For the inherited methods read 22.9. Methods of cGuiInputItem.
initPic() adds a picture to the button, next to it's label. The file path must be given in the portable format used by the cPath module, so you may need to use it's ImportFilePath() procedure first.
infoPic() returns the picture path set using initPic(), or NILA if none was set.
This class is a tick button, which the user can toggle ticked or unticked.
/* Methods of cGuiTick, which inherits from cGuiInputItem */ METHOD setState(ticked:BOOL) RETURNS self:PTR TO cGuiTick METHOD getState() RETURNS ticked:BOOL ->plus methods inherited from cGuiInputItem
For the inherited methods read 22.9. Methods of cGuiInputItem.
setState() & getState() allow you to change & retrieve the ticked/unticked state.
This class is a string input line, which allows the user to change the string.
/* Methods of cGuiString, which inherits from cGuiStringItem */ ->plus methods inherited from cGuiStringItem ->METHOD setState(string:ARRAY OF CHAR) RETURNS self:PTR TO cGuiString ->METHOD getState() RETURNS string:ARRAY OF CHAR
For the inherited methods read 22.10. Methods of cGuiStringItem.
This class is a multi-line string input box, which allows the user to change the string. It usually defaults to a variable-width font, but it can use a fixed-width (mono-spaced) font if you want.
/* Methods of cGuiStringBox, which inherits from cGuiStringItem */ METHOD initFixedFont() RETURNS self:PTR TO cGuiStringBox METHOD infoFixedFont() RETURNS fixedFont:BOOL ->plus methods inherited from cGuiStringItem ->METHOD setState(string:ARRAY OF CHAR) RETURNS self:PTR TO cGuiStringBox ->METHOD getState() RETURNS string:ARRAY OF CHAR
For the inherited methods read 22.10. Methods of cGuiStringItem.
initFixedFont() indicates that a fixed-width font should be used. This must be called before the GUI is built.
infoFixedFont() returns whether initFixedFont() was used or not.
This class is a path input line, for choosing the file/dir path of something. Typically it has a button that will open a file requester.
It's getState() method is used to retrieve the chosen path. The path is returned in the portable format used by the cPath module, so you may need to use it's ExportPath() procedure afterwards.
It's setState() method can be used to set the shown path. The path must be given in the portable format used by the cPath module, so you may need to use it's ImportFilePath() or ImportDirPath() procedure first.
/* Methods of cGuiPathString, which inherits from cGuiStringItem */ METHOD initOnlyShowFolders() RETURNS self:PTR TO cGuiPathString METHOD initUseSaveMode() RETURNS self:PTR TO cGuiPathString METHOD initShowSystemFiles() RETURNS self:PTR TO cGuiPathString
initOnlyShowFolders() indicates that the file requester should only show folders (not files). This must be called before the GUI is built.
initUseSaveMode() indicates that the file requester should use 'save mode', which means it will ask about replacing existing files. This must be called before the GUI is built.
initShowSystemFiles() indicates that the file requester should show system files (which on the Amiga means show .info files). This must be called before the GUI is built.
/* more methods of cGuiPathString */ METHOD infoOnlyShowFolders() RETURNS onlyShowFolders:BOOL METHOD infoUseSaveMode() RETURNS useSaveMode:BOOL METHOD infoShowSystemFiles() RETURNS showSystemFiles:BOOL ->plus methods inherited from cGuiStringItem ->METHOD setState(string:ARRAY OF CHAR) RETURNS self:PTR TO cGuiPathString ->METHOD getState() RETURNS string:ARRAY OF CHAR
For the inherited methods read 22.10. Methods of cGuiStringItem.
infoOnlyShowFolders() returns whether initOnlyShowFolders() was used or not.
infoUseSaveMode() returns whether initUseSaveMode() was used or not.
infoShowSystemFiles() returns whether initShowSystemFiles() was used or not.
This class is a number input line, which only allows the user to enter a number. It also ensures that the number is within an allowed range.
/* Methods of cGuiNumberString, which inherits from cGuiNumberItem */ ->plus methods inherited from cGuiNumberItem ->METHOD setState(number) RETURNS self:PTR TO cGuiNumberString ->METHOD getState() RETURNS number ->METHOD initUnit(unit:ARRAY OF CHAR) RETURNS self:PTR TO cGuiNumberString ->METHOD infoUnit() RETURNS unit:ARRAY OF CHAR ->METHOD infoMin() RETURNS min ->METHOD infoMax() RETURNS max
For the inherited methods read 22.11. Methods of cGuiNumberItem.
This class is a slider, for choosing a number within an allowed range.
/* Methods of cGuiSlider, which inherits from cGuiNumberItem */ ->plus methods inherited from cGuiNumberItem ->METHOD setState(number) RETURNS self:PTR TO cGuiSlider ->METHOD getState() RETURNS number ->METHOD initUnit(unit:ARRAY OF CHAR) RETURNS self:PTR TO cGuiSlider ->METHOD infoUnit() RETURNS unit:ARRAY OF CHAR ->METHOD infoMin() RETURNS min ->METHOD infoMax() RETURNS max
For the inherited methods read 22.11. Methods of cGuiNumberItem.
This class is a cyclable/pop-up choice box, for choosing from several fixed options.
/* Methods of cGuiCycleChoice, which inherits from cGuiChoiceItem */ ->plus methods inherited from cGuiChoiceItem ->METHOD setState(choice) RETURNS self:PTR TO cGuiCycleChoice ->METHOD getState() RETURNS choice ->METHOD infoChoices() RETURNS choices:ARRAY OF ARRAY OF CHAR
For the inherited methods read 22.12. Methods of cGuiChoiceItem.
This class is a radio-style choice list, for choosing from several fixed options.
/* Methods of cGuiRadioChoice, which inherits from cGuiChoiceItem */ ->plus methods inherited from cGuiChoiceItem ->METHOD setState(choice) RETURNS self:PTR TO cGuiRadioChoice ->METHOD getState() RETURNS choice ->METHOD infoChoices() RETURNS choices:ARRAY OF ARRAY OF CHAR
For the inherited methods read 22.12. Methods of cGuiChoiceItem.
This class is a scrollable list of entries, where each entry is a single line of text. If the list is defined as having selectable entries, then each entry will have a tick box.
It is NOT suitable for very large lists, because every entry is built out of several other cGui items. This means that large lists will take a long time to build, and will probably use a lot of memory.
/* Methods of cGuiFixedList, which inherits from cGuiGroupItem */ METHOD initSelectableEntries(multiSelect=FALSE:BOOL) RETURNS self:PTR TO cGuiFixedList METHOD initColumnAlignment(alignment:ARRAY OF CHAR) RETURNS self:PTR TO cGuiFixedList METHOD initColumnTitles(titles:ARRAY OF CHAR) RETURNS self:PTR TO cGuiFixedList METHOD infoSelectableEntries() RETURNS selectable:BOOL, multiSelect:BOOL METHOD infoColumnAlignment() RETURNS alignment:ARRAY OF CHAR METHOD infoColumnTitles() RETURNS titles:ARRAY OF CHAR METHOD infoColumns() RETURNS columns METHOD infoSelectionCount() RETURNS selectionCount METHOD infoSingleSelectionEntry() RETURNS item:PTR TO cGuiFixedListEntry METHOD setMultiSelect(multiSelect:BOOL) METHOD getMultiSelect() RETURNS multiSelect:BOOL ->plus methods inherited from cGuiGroupItem ->METHOD infoHasBorder() RETURNS hasBorder:BOOL ->METHOD infoTitle() RETURNS title:ARRAY OF CHAR ->METHOD infoSize() RETURNS size ->METHOD infoFirstItem() RETURNS item:PTR TO cGuiFixedListEntry ->METHOD infoLastItem() RETURNS item:PTR TO cGuiFixedListEntry ->METHOD setGhosted(ghosted:BOOL) ->the following inherited methods are NOT supported ->METHOD initScrollable() RETURNS self:PTR TO cGuiFixedList ->METHOD initEqualSizedItems() RETURNS self:PTR TO cGuiFixedList ->METHOD infoScrollable() RETURNS scrollable:BOOL ->METHOD infoEqualSizedItems() RETURNS equalSizedItems:BOOL
For the inherited methods read 22.6. Methods of cGuiGroupItem.
initSelectableEntries() indicates that the list's entries are selectable by the user. Normally selecting a second entry will cause the first to become unselected, but if you give TRUE for multiSelect then all entries stay selected (until unselected). This method must be called before any entries are added.
initColumnAlignment() indicates how the columns should be aligned. alignment is a string, with one character per column, where "L" means left aligned, "C" means center aligned, and "R" means right aligned. Thus 'LLCR' means left align the first two columns, then center the next column, then right align the next column. By default everything is left aligned.
initColumnTitles() indicates what title should appear at the top of each column. The titles defines the text for ALL columns, with each column being separated by a \t character. BEWARE that the titles are a kludge, as they actually appear inside the scrollable list, and so they will not be visible when it is scrolled vertically.
infoSelectableEntries() returns whether initSelectableEntries() was used or not. It also returns what multiSelect was supplied when it was called.
infoColumnAlignment() returns the "alignment" string which represents how the columns will be aligned (see the initColumnAlignment() description for more details).
infoColumnTitles() returns the "titles" string which was given to initColumnTitles(), or NILA if none was given.
infoColumns returns the number of columns the list was created with.
infoSelectionCount() returns how many entries are selected.
infoSingleSelectionEntry() returns the selected entry, or NIL if nothing is selected. It may only be used when multiSelect=FALSE.
setMultiSelect() & getMultiSelect() allow you to change & retrieve multiSelect, but only if you used initSelectableEntries(TRUE).
This class is a single line of text, which appears inside a scrollable list. Optionally it can be selectable, which means that it will have a tick box next to the text.
/* Methods of cGuiFixedListEntry, which inherits from cGuiItem */ METHOD setState(ticked:BOOL) METHOD getState() RETURNS ticked:BOOL METHOD infoLabel() RETURNS label:ARRAY OF CHAR METHOD infoIndex() RETURNS index METHOD initAltColour() RETURNS self:PTR TO cGuiFixedListEntry METHOD setGhosted(ghosted:BOOL) METHOD getGhosted() RETURNS ghosted:BOOL METHOD setNotifyFunction(func:NULL PTR TO funcGuiNotify) METHOD getNotifyFunction() RETURNS func:PTR TO funcGuiNotify ->plus methods inherited from cGuiItem ->setData(data) RETURNS self:PTR TO cGuiFixedListEntry ->getData() RETURNS data ->infoNextInGroup() RETURNS item:PTR TO cGuiFixedListEntry
For the inherited methods read 22.5. Methods of cGuiItem.
setState() & getState() allow you to change & retrieve the selection state.
infoLabel() returns the label that the GUI item was created with.
infoIndex() returns the unique number used to identify this entry. The first entry is 0, the second is 1, and so on. (If this is not a convenient way to identify entries, don't forget that you can use setData() & getData() as with any GUI item.)
initAltColour() indicates that the line of text should be shown in an alternative (typically more noticable) colour.
setGhosted() & getGhosted() are the same as in 22.9. Methods of cGuiInputItem.
setNotifyFunction() & getNotifyFunction() are the same as in 22.9. Methods of cGuiInputItem.
This module provides an easy way of playing music, which is suitable for games & multimedia.
Supported OSes: AmigaOS4, AmigaOS3, AROS, MorphOS.
NOTE: Currently it can only load & play Protracker music (using the ptplay.library). I expect to add MP3 support in the future.
How to play music:
DEF music:PTR TO cMusic
CreateApp().build() ->you only need to do this once!
music := LoadMusic('MyMusic.mod')
music.play()
How to wait for the music to finish playing:
music.waitForPlayToFinish()
A more flexible way to wait for the music to finish playing:
WHILE WaitForMusicEvent() <> music DO EMPTY
Here's another way to play music:
CreateApp().build() ->you only need to do this once!
StoreMusic('test', 0, LoadMusic('MyMusic.mod'))
UseMusic('test', 0).play()
The following example programs use it:
Examples/std/GUI/SimpleModPlayer.e Examples/std/Multimedia/ShadowOfTheBlitz_Scroller/SOTB.e Examples/std/Multimedia/ShootEmUp/ShootEmUp.e Examples/std/Multimedia/StarsDemo.e
PROC LoadMusic(file:ARRAY OF CHAR, allowReturnNIL=FALSE:BOOL) RETURNS music:PTR TO cMusic PROC DestroyMusic(music:PTR TO cMusic) RETURNS nil:PTR TO cMusic PROC WaitForMusicEvent() RETURNS music:PTR TO cMusic PROC CheckForMusicEvent() RETURNS music:PTR TO cMusic PROC StoreMusic(name:ARRAY OF CHAR, number, music:OWNS PTR TO cMusic) RETURNS storedMusic:PTR TO cMusic PROC UseMusic(name:ARRAY OF CHAR, number, allowReturnNIL=FALSE:BOOL) RETURNS music:PTR TO cMusic
LoadMusic() loads the given music, and returns a cMusic object for it. The file path must be given in the portable format used by the cPath module, so you may need to use it's ImportFilePath() procedure first. If the file could not be loaded, then an exception will be raised (unless TRUE was given to allowReturnNIL, in which case NIL would be returned instead).
DestroyMusic() destroys the supplied music object. Your music will be automatically destroyed when your program quits, so you may not need to use this! You may pass it a NIL parameter without any problem. It returns NIL for your convenience.
WaitForMusicEvent() waits for any playing music to stop (unless one has already stopped), and then returns that music. Note that it will only remember the most recent events (typically the last 100), so ensure that you watch for events regularly.
CheckForMusicEvent() checks if any previously playing music has stopped, and returns that music. If no music has stopped, then it returns NIL.
StoreMusic() & UseMusic() allow you to store & retrieve music using a name string, and optionally a number. The string must be an 'immediate string', not one you have created. It returns the stored music, so you can use it straight away. Here's an example of how you might use it:
StoreMusic('title', 0, LoadMusic('music/Title.mod'))
UseMusic('title', 0).play()
If you try to store more than one music with the same name & number combination, then an exception will be raised. This is to prevent you accidentally reusing them. And if you try to use a non-existant music, then an exception will be raised; unless you gave TRUE for allowReturnNIL, in which case NIL will be returned.
The cMusic class is music which can be played. You can only play one piece of music at a time. Playing a new piece of music will stop the previously playing one.
/* Methods of cMusic */ METHOD play(playCount=1) METHOD stop() METHOD infoLength() RETURNS milliSeconds METHOD infoIsPlaying() RETURNS isPlaying:BOOL METHOD waitForPlayToFinish() METHOD setVolume(volume) RETURNS music:PTR TO cMusic METHOD getVolume() RETURNS volume
play() starts playing the music, using the given parameters. playCount indicates how many times the music should be played (back to back). Use 0 if you want the music to play forever.
stop() stops the music from playing.
infoLength() returns the length of the music in milliseconds.
infoIsPlaying() returns whether or not the music is currently playing.
waitForPlayToFinish() pauses until the music has stopped playing.
setVolume() & getVolume() allow you to change & retrieve volume. This is how loud the music will be played, where 100 is maximum volume, 50 is half volume, 0 is silent, and so on. It is used by subsequent play() calls, and it also affects the music if it is currently playing.
This module provides easy access to files & directories. It hides the host OS's path format (and any DOS quirks). So it should work identically whatever OS is used, and thus allow the same file/directory code everywhere.
As you typically only want to handle paths, or files, or directories, but not all three, this module has been split into three smaller modules, so that you can reduce your executable size & compile time. These modules are:
Supported OSes: All.
While the module has many procedures & methods (to do almost anything you could ever want), these examples should cover the main things you might want to do.
How to turn a host OS path into a portable path that we can use:
DEF portablePath:STRING
portablePath := ImportFilePath('path of some file')
Print('The portable path is "\s".\n', portablePath)
IF Exists(portablePath) THEN Print('It exists!\n')
END portablePath
How to create or open a directory:
DEF dir:PTR TO cDir
NEW dir.new()
IF dir.open('examplePortablePath/')
->use the file now
IF dir.getAttributes() AND CPA_DELETE = 0 THEN Print('The folder is protected from deletion.\n')
dir.close()
ENDIF
END dir
How to create or open a file:
DEF file:PTR TO cFile
NEW file.new()
IF file.open('examplePortablePath.txt')
->use the dir now
Print('The file size is \d bytes.\n', file.getSize() !!VALUE)
file.close()
ENDIF
END file
How to read the contents of an opened file:
DEF buffer:ARRAY OF BYTE, size
size := file.getSize() !!VALUE
NEW buffer[size+1]
file.setPosition(0)
file.read(buffer, size)
buffer[size] := 0 ->make it a valid string
Print('The file contents:\n')
Print('\s\n', buffer)
END buffer
How to add a string to the end of an opened file:
file.setPosition(-1)
file.write('Hello world!\n', STRLEN)
How to list the contents of an opened directory:
DEF list:PTR TO cDirEntryList
Print('The folder "\s" contains:\n', dir.getName())
list := dir.makeEntryList()
IF list.gotoFirst()
REPEAT
Print('* \s\n', list.infoName())
UNTIL list.gotoNext() = FALSE
ENDIF
END list
How to check a file or directory exists:
IF Exists('portablePath')
Print('It exists!\n')
ENDIF
How to delete a file or (empty) directory:
IF Delete('portablePath') = FALSE
Print('Failed to delete it!\n')
ENDIF
How to turn a portable path back into a host OS path the user will expect:
DEF hostPath:STRING
hostPath := ExportPath('portable/path/of/some file or directory')
Print('The host OS path is "\s".\n', hostPath)
END hostPath
The following example programs use it:
Examples/std/Shell/AmigaAttributes.e Examples/std/Shell/BinDif.e Examples/std/Shell/DeleteModuleCache.e Examples/std/Shell/PEGCC.e Examples/std/Shell/RecursiveDir.e Examples/std/Shell/ToyInterpreter/ToyInterpreter.e
Released programs which are known to use it:
FolderSync2 ( cshandley.co.uk ) AmigaAttributes ( cshandley.co.uk ) PictureAlbum ( cshandley.co.uk ) Ami-Ingenious ( os4depot.net/index.php?function=showfile&file=game/board/ami-ingenious.lha ) FlowerWay ( os4depot.net/?function=showfile&file=game/puzzle/flowerway.lha ) HueFlow ( os4depot.net/?function=showfile&file=game/puzzle/hueflow.lha ) Ami-Scratch ( os4depot.net/?function=showfile&file=graphics/misc/amiscratch.lha ) Ami-Bootguard ( os4depot.net/?function=showfile&file=utility/misc/ami-bootguard.lha ) Ami-Lineapolis ( www.lineapolis.dizzy.pl )
So that you can more easily understand the procedures & methods, here are a few common terms:
All of these procedures can also be found in the smaller 'std/cPath_shared' module, with the exception of the procedures DeleteDir(), CreateDirs() & RecurseDir().
PROC IsFile(path:ARRAY OF CHAR) RETURNS isFile:BOOL PROC IsDir( path:ARRAY OF CHAR) RETURNS isDir:BOOL PROC FastIsFile(path:STRING) RETURNS isFile:BOOL PROC FastIsDir( path:STRING) RETURNS isDir:BOOL PROC InvalidFilePath(filePath:ARRAY OF CHAR) RETURNS invalid:BOOL PROC InvalidFileName(fileName:ARRAY OF CHAR) RETURNS invalid:BOOL PROC InvalidDirPath( dirPath:ARRAY OF CHAR) RETURNS invalid:BOOL PROC InvalidDirName( dirName:ARRAY OF CHAR) RETURNS invalid:BOOL
IsFile() & IsDir() check whether the given path is for a file or dir, by checking whether it ends in a slash or not. Since a dir always ends in a slash, this is completely reliable.
FastIsFile() & FastIsDir() are faster versions of IsFile() & IsDir(), but they require that the given path is an e-string.
InvalidFilePath(), InvalidFileName(), InvalidDirPath() & InvalidDirName() check whether the given path/name conforms to basic validity rules, such as ending with a slash or not.
PROC FindName( path:ARRAY OF CHAR) RETURNS name:ARRAY OF CHAR, nameLength PROC ExtractName( path:ARRAY OF CHAR) RETURNS name:OWNS STRING PROC ExtractDevice( path:ARRAY OF CHAR) RETURNS devicePath:OWNS STRING PROC ExtractSubPath(path:ARRAY OF CHAR) RETURNS subPath:OWNS STRING
FindName() finds the name in a (file or directory) path, and returns a name array that points to it. It also returns the name length as nameLength.
ExtractName() returns an e-string containing a copy of the name in a path.
ExtractDevice() returns an e-string containing a copy of the device in a path (which will end in a :/), or an empty e-string if there is no device.
ExtractSubPath() returns an e-string containing a copy of everything except the name in a path.
PROC CurrentDirPath() RETURNS dirPath:OWNS STRING PROC Exists(path:ARRAY OF CHAR, fileOrDir=FALSE:BOOL) RETURNS exists:BOOL PROC Delete( path:ARRAY OF CHAR, force=FALSE:BOOL, fileOrDir=FALSE:BOOL) RETURNS success:BOOL PROC DeleteDir(dirPath:ARRAY OF CHAR, force=FALSE:BOOL) RETURNS success:BOOL PROC ImportDirPath( hostDirPath:ARRAY OF CHAR) RETURNS dirPath:OWNS STRING PROC ImportFilePath(hostFilePath:ARRAY OF CHAR) RETURNS filePath:OWNS STRING PROC ExportPath(path:ARRAY OF CHAR) RETURNS hostPath:OWNS STRING PROC ExpandPath(path:ARRAY OF CHAR) RETURNS expandedPath:OWNS STRING PROC MakeUniquePath(file1dir2, path:ARRAY OF CHAR, base=NILA:ARRAY OF CHAR) RETURNS path:OWNS STRING
CurrentDirPath() returns the program's current directory as an e-string.
Exists() returns whether the given file/dir exists. If fileOrDir is TRUE then it will ignore whether the given path is for a file or dir (since many filingsystems disallow files with the same names as directories).
Delete() attempts to delete the given file/dir, returning whether it succeeded or not. It will fail if the directory is not empty. If force is TRUE then it will unprotect the file/dir before attempting to delete it. If fileOrDir is TRUE then it will ignore whether the given path is for a file or dir (since many filingsystems disallow files with the same names as directories).
DeleteDir() attempts to delete the given dir, and everything it contains, including all sub-directories, returning whether it completely succeeded or not. If force is TRUE then it will unprotect any dirs before attempting to delete them.
ImportFilePath() & ImportDirPath() converts a host OS file/directory path into the portable format, returning an e-string. If a NILA parameter is supplied, then NILS will be returned.
ExportPath() converts a portable path into the host OS file/directory format, returning an e-string. If a NILA parameter is supplied, then NILS will be returned.
ExpandPath() takes a portable path and makes it as full & unamiguous as possible. Thus it replaces any aliases or links or assignments with the actual physical path, and ensures that the path is not relative to the current directory. It returns an e-string.
MakeUniquePath() creates an e-string path that does not yet exist. For file1dir2, supply 1 for a file path, or 2 for a dir path. If base is not given then it will default to 'TMP'. The name of the created path will begin with base.
PROC CreateLink(path:ARRAY OF CHAR, targetPath:ARRAY OF CHAR, specific:QUAD) RETURNS success:BOOL, unknown:BOOL PROC CreateDirs(path:ARRAY OF CHAR, ignoreName=FALSE:BOOL) RETURNS success:BOOL PROC RecurseDir(dirPath:ARRAY OF CHAR, funcFile:PTR TO funcRecurseFile, funcDir=NIL:PTR TO funcRecurseDir, funcDirFailure=NIL:PTR TO funcRecurseDirFailure, funcDirAbort=NIL:PTR TO funcRecurseDirAbort)
CreateLink() creates a link from path to targetPath of the type given by specific. path must not exist, while targetPath should exist, otherwise it will return FALSE for success. It will return FALSE for unknown unless specific was not recognised.
This is much more efficient than creating an empty file with cFile/cDir, and then using changeExtra() to turn it into a link. As with changeExtra(), targetPath must be in the portable format.
CreateDirs() ensures that all the dirs of a given path exist, creating them if necessary, and returning whether it succeeded or not. If ignoreName is TRUE then the final file/dir at the end of the path is ignored.
RecurseDir() recursively scans the dirPath directory (and sub-directories), calling the supplied funcFile function on every file it finds. If the optional funcDir function is supplied, then it calls that on every sub-directory it finds, and only scans that directory if the function returns TRUE. If the optional funcDirFailure function is supplied, then it calls that when opening a directory for scanning fails, and continues with further scans if the function returns TRUE. All three functions are passed the path as a STRING, with funcDirFailure also being passed two strings explaining the failure's origin & reason. Note that directory scanning is performed breadth-first & alphanumerically.
If a Ctrl-C is received then scanning is halted. By default it will then raise a "BRK" exception, but if the optional funcDirAbort function is supplied, then it calls that with the next directory that would have been scanned, and then RecurseDir() returns.
Thus skeleton functions look like this:
FUNC yourFuncFile(filePath:STRING) OF funcRecurseFile
ENDFUNC
FUNC yourFuncDir(dirPath:STRING) OF funcRecurseDir RETURNS scanDir:BOOL
scanDir := TRUE
ENDFUNC
FUNC yourFuncDirFailure(dirPath:STRING, failureOrigin=NILA:ARRAY OF CHAR, failureReason=NILA:ARRAY OF CHAR) OF funcRecurseDirFailure RETURNS continueScan:BOOL
continueScan := TRUE
ENDFUNC
FUNC yourFuncDirAbort(nextDirPath:STRING) OF funcRecurseDirAbort
Raise("BRK")
ENDPROC
And RecurseDir() would use them like this:
RecurseDir('your dir', yourFuncFile, yourFuncDir, yourFuncDirFailure, yourFuncDirAbort)
But if you are feeling particularly clever, then you can combine the first two directory functions into one, whose skeleton looks like this:
FUNC yourFuncDir2(dirPath:STRING, failureOrigin=NILA:ARRAY OF CHAR, failureReason=NILA:ARRAY OF CHAR) OF funcRecurseDirFailure RETURNS doScan:BOOL
IF failureOrigin
doScan := TRUE ->equivalent to continueScan := TRUE
ELSE
doScan := TRUE ->equivalent to scanDir := TRUE
ENDIF
ENDFUNC
And you would use it like this:
RecurseDir('your dir', yourFuncFile, yourFuncDir2, yourFuncDir2)
Alternatively, another clever thing you can do is combine the file & first directory functions into one, whose skeleton looks like this:
FUNC yourFuncFileDir(path:STRING) OF funcRecurseDir RETURNS scanDir:BOOL
IF FastIsFile(path) ->do file stuff ELSE ->do dir stuff scanDir := TRUE ENDIF ENDFUNC
And you would use it like this:
RecurseDir('your dir', yourFuncFileDir, yourFuncFileDir, yourFuncDirFailure)
You could even combine this function with the funcDirFailure directory function, in a similar fashion to before, which is left as an exercise for the reader.
Note that the funcRecurseDirAbort function must always be implemented separately.
This (abstract) class is the parent of both the cFile & cDir classes, so that both files & directories share many methods. This mean that not only are there less methods for you to learn, but it also allows you to treat files & directories in a similar way.
(And advanced users can write procedures which take a cPath (instead of a cFile or cDir), so that they will work on both files & directories.)
So please keep in mind that the following methods apply to both files & directories!
The cPath class can also be found in the smaller 'std/cPath_shared' module.
/* Methods of cPath, which inherits cExtra */ METHOD open(path:ARRAY OF CHAR, readOnly=FALSE:BOOL, forceOpen=FALSE:BOOL) RETURNS success:BOOL METHOD create(path:ARRAY OF CHAR, doNotReplace=FALSE:BOOL, forceOpen=FALSE:BOOL) RETURNS success:BOOL METHOD close() METHOD flush() METHOD clone(writeNotRead=FALSE:BOOL) RETURNS clone:OWNS PTR TO cPath METHOD infoFailureReason() RETURNS reason:ARRAY OF CHAR METHOD infoFailureOrigin() RETURNS origin:ARRAY OF CHAR METHOD infoReadOnly() RETURNS readOnly:BOOL METHOD infoIsOpen() RETURNS isOpen:BOOL
open() must be used before any other method. And if you wish to use any setX() methods, then readOnly must be FALSE. If forceOpen is TRUE then it will clear any read or write protection, so that the file can be opened. Be sure to check that TRUE is returned for success, and if it isn't then you can use infoFailureReason()/etc just like for any other method that fails.
create() is an alternative to open, which ensures that an empty file/dir is created. If the file/dir already exists then normally it will delete that file/dir, but if doNotReplace is TRUE then it will just fail (returning FALSE).
close() must be used when you are finished with the file/dir, and before you use open() again. In read-write mode, all cached changes are comitted to disk.
flush() forces the cache to be emptied. In read-only mode the cache will be refreshed with current information, while in read-write mode all cached changes will be comitted to disk.
clone() creates another object with the same file/dir open, but in read-only mode unless writeNotRead is TRUE. If it fails to open the file/dir, then it will return NIL.
infoFailureReason() & infoFailureOrigin() return strings that describe the reason for the last failure & the method in which the failure originated. No return codes are provided, because these would be inherantly non-portable.
infoReadOnly() returns the readOnly value that open() was supplied with.
infoIsOpen() returns whether anything is currently open.
/* more methods of cPath */ METHOD setAttributes(attr, mask=-1) RETURNS success:BOOL METHOD getAttributes() RETURNS attr METHOD getAttributesSupported() RETURNS mask METHOD setPath(path:ARRAY OF CHAR) RETURNS success:BOOL METHOD getPath() RETURNS path:ARRAY OF CHAR METHOD setSubPath(path:ARRAY OF CHAR) RETURNS success:BOOL METHOD getSubPath() RETURNS path:OWNS STRING METHOD setName(name:ARRAY OF CHAR) RETURNS success:BOOL METHOD getName() RETURNS name:ARRAY OF CHAR ->plus methods inherited from cExtra
For the inherited methods read 24.8. Methods of cExtra.
setAttributes() changes the attributes (flags) to attr, but only affects the attributes given by mask. The available attribute are:
CPA_STRICT, CPA_READ, CPA_WRITE, CPA_DELETE, CPA_HIDE, CPA_UNUSED1, CPA_UNUSED2, CPA_UNUSED3, CPA_UNUSED4
Note that CPA_STRICT affects how the other attributes are interpreted, for example: The FAT filing system combines the meaning of CPA_WRITE & CPA_DELETE into one flag. Without CPA_STRICT you must clear both CPA_WRITE & CPA_DELETE before either of them is cleared. But with CPA_STRICT you only need to clear either of CPA_WRITE or CPA_DELETE before both are cleared.
getAttributes() returns the current attributes, such as CPA_READ. Note that CPA_STRICT has no meaning here.
getAttributesSupported() returns a mask indicating which attributes are supported by the current host OS.
setPath() & getPath() allow you to change & retrieve the complete path (subpath & name) of the current file/dir as an e-string.
setSubPath() & getSubPath() allow you to change & retrieve the subpath of the current file/dir. Changing the subpath is equivalent to moving it. BEWARE that getSubPath() returns a new string, which you must END when you are finished with it.
setName() & getName() allow you to change & retrieve the name of the current file/dir. Changing the name is equivalent to renaming it.
This class is for handling files. You must create an object (using the new() method), after which you can open() & close() files as many times as you want.
The cFile class can also be found in the smaller 'std/cPath_File' module.
/* Methods of cFile, which inherits cPath */ METHOD new(padByte=0:BYTE) METHOD open(filePath:ARRAY OF CHAR, readOnly=FALSE:BOOL, forceOpen=FALSE:BOOL, atPastEndNotStart=FALSE:BOOL) RETURNS success:BOOL METHOD read( buffer:ARRAY, lengthInBytes, offsetInBytes=0, toByte=-1:INT) RETURNS nextPos:BIGVALUE, numOfPadBytes METHOD write(buffer:ARRAY, lengthInBytes, offsetInBytes=0, noAutoExtend=FALSE:BOOL) RETURNS nextPos:BIGVALUE, numOfLostBytes METHOD infoPadByte() RETURNS padByte:BYTE
new() is the object's constructor. You can specify a pad byte other than 0 here.
open() has the additional atPastEndNotStart parameter. Normally the read/write position is at the start of a file, but if atPastEndNotStart is TRUE then it will be just past the end of the file.
read() reads lengthInBytes bytes into the buffer from the current read/write position. The current position is not changed by this method, so you must use the setPosition() method to change it. Luckily it returns the next sequential position, nextPos, should you need it.
offsetInBytes is an offset into the buffer (to avoid pointer arithmetic). Pad bytes will appear if you read after the end of the file. If toByte is given then it will not read past the occurance of the first toByte byte, with the remainder of the buffer being filled with pad bytes. If you read past the end of the file, then the buffer will similarly be filled with pad bytes.
write() writes lengthInBytes bytes from the buffer to the current read/write position. The current position is not changed by this method, so you must use the setPosition() method to change it. Luckily it returns the next sequential position, nextPos, should you need it.
offsetInBytes is an offset into the buffer (to avoid pointer arithmetic). Normally writing past the end of a file will cause it's size to grow as needed, but if noAutoExtend is TRUE then the file will NOT grow any larger (in which case numOfLostBytes will indicate how many bytes were not written). If you start writing beyond the end of a file, then any gap between the end of the file & your start position will be filled with pad bytes.
infoPadByte() returns the padByte value that new() was supplied with.
/* more methods of cFile */ METHOD setPosition(pos:BIGVALUE) METHOD getPosition(fromEnd=FALSE:BOOL) RETURNS pos:BIGVALUE METHOD setSize(sizeInBytes:BIGVALUE) METHOD getSize() RETURNS sizeInBytes:BIGVALUE METHOD setTime(time:BIGVALUE) RETURNS success:BOOL METHOD getTime() RETURNS time:BIGVALUE METHOD makeCopy(path:ARRAY OF CHAR) RETURNS copy:OWNS PTR TO cFile ->plus methods inherited from cPath
For the inherited methods read 24.4. Methods of cPath.
setPosition() changes the current read/write position. You may go beyond the end of the file without changing the file's size. A negative pos indicates position from the end of the file (-1=after last byte, -2=last byte, etc). Note that an error will be raised if you attempt to go before the beginning of the file.
Positions are BIGVALUEs (which are typically 64-bit), although the host OS may not support positions which exceed 32-bits. (In fact no cFile implementation yet supports 64-bit values, but this will hopefully change.)
getPosition() retrieves the current read/write postion. If fromEnd is TRUE then it returns a negative position as measured from the end of the file (see setPosition()).
setSize() & getSize() allow you to change & retrieve the file's current size in bytes.
setTime() & getTime() allow you to change & retrieve the file's current time.
makeCopy() creates a precise copy of a file, including cExtra information, returning a file opened in write mode. It will not overwrite an existing file. It will return NIL if an error occured.
This class is for handling directories. You must create an object (using the new() method), after which you can open() & close() directories as many times as you want.
The cDir class can also be found in the smaller 'std/cPath_Dir' module.
/* Methods of cDir, which inherits cPath */ METHOD new() METHOD openParent(forceOpen=FALSE:BOOL) RETURNS success:BOOL METHOD openChild(relativePath:ARRAY OF CHAR, forceOpen=FALSE:BOOL) RETURNS success:BOOL METHOD makeEntryList() RETURNS list:OWNS PTR TO cDirEntryList ->plus methods inherited from cPath
For the inherited methods read 24.4. Methods of cPath.
new() is the object's constructor.
openParent() closes the current dir & opens the parent dir. If it fails then it will return FALSE for success & leave the original dir open. forceOpen has the same meaning as it does for the open() method.
openChild() closes the current dir & opens the given sub-dir, which must be a dirpath relative to the current dir. If it fails then it will return FALSE for success & leave the original dir open. forceOpen has the same meaning as it does for the open() method.
makeEntryList() returns a cDirEntryList object containing the result of a scan of the current directory.
This class is a sorted list containing the result of a directory scan. You can also do various things with it, such as combining two lists, and generating a "unique name" which is not present in the list.
The cDirEntryList class can also be found in the smaller 'std/cPath_Dir' module.
/* Methods of cDirEntryList */ METHOD clone() RETURNS clone:OWNS PTR TO cDirEntryList METHOD gotoFirst(any0file1dir2=0) RETURNS exists:BOOL METHOD gotoNext( any0file1dir2=0) RETURNS exists:BOOL METHOD infoName() RETURNS path:ARRAY OF CHAR METHOD findName(name:ARRAY OF CHAR, fileOrDir=FALSE:BOOL) RETURNS success:BOOL
clone() allows you to create an exact copy of the current object.
gotoFirst() changes the current position in the list to the first item. If any0file1dir2 is 1 then it goes to the first file in the list, while if it is 2 then it goes to the first directory in the list. Returns whether the requested item exists, with FALSE implying that the list is empty.
gotoNext() changes the current position in the list to the next item. If any0file1dir2 is 1 then it goes to the next file in the list, while if it is 2 then it goes to the next directory in the list. Returns whether the requested item exists, with FALSE implying that the end of the list has been reached.
infoName() returns the name of the current item.
findName() searches from the start of the list for the given name, returning whether it succeeded in finding a match. If fileOrDir is TRUE then it will ignore whether the given name is for a file or dir. If TRUE is returned for success then the current position is the matched item.
/* more methods of cDirEntryList */ METHOD remove() METHOD add(name:ARRAY OF CHAR) RETURNS success:BOOL METHOD addString(name:OWNS STRING) RETURNS success:BOOL METHOD addList(list:PTR TO cDirEntryList) RETURNS numOfSameEntries METHOD makeUniqueName(file1dir2, base=NILA:ARRAY OF CHAR) RETURNS name:OWNS STRING
remove() destroys the current item, moving to the next one.
add() creates an item with the given name, and add's it to the list such that it stays sorted. Returns FALSE if there was already an item with that name, since duplicates are not allowed.
addString() works like add(), but it uses the provided e-string for speed. The list will now handle deallocation of the e-string, so you must NOT deallocate it yourself. If it returns FALSE, then the e-string will be deallocated immediately.
addList() creates copies of all items in the provided list, and adds them to the current list. It returns the number of duplicates that were not added.
makeUniqueName() creates an e-string name that does not yet exist in the list. For file1dir2, supply 1 for a file path, or 2 for a dir path. If base is not given then it will default to 'TMP'. The created name will begin with base.
This class is used for all the host OS information which is not accessible by normal means. In the Amiga's case this means file comments & certain flags.
You must specify what item of information you want to read or change, using a specific:QUAD value. The supported values depend on the host OS. For example:
Take care using them, because they are not completely portable!
The cExtra class can also be found in the smaller 'std/cPath_shared' module.
/* Methods of cExtra */ METHOD setExtra(extra:PTR TO cExtra) RETURNS success:BOOL METHOD getExtra() RETURNS extra:OWNS PTR TO cExtra METHOD changeExtra(specific:QUAD, value) RETURNS success:BOOL, unknown:BOOL METHOD queryExtra( specific:QUAD) RETURNS value, unknown:BOOL
setExtra() makes the object have the same information as that stored by extra (which could be a cFile or cDir object). Returns FALSE if it could not set all of the information.
getExtra() returns a new cExtra object, which contains a copy of all the current object's cExtra information.
changeExtra() changes a particular piece of information (given by specific) in the object to the supplied value. Returns whether it succeeded or not, and if it failed then whether that failure was due to specific being unknown.
queryExtra() returns a particular piece of information (given by specific) in value. This will be 0 when specific is unknown, but for cases where this is a valid value you need to check unknown.
Portable paths are represented in one particular format, whatever OS is being used. This means that manipulation of path strings is portable (and also quite easy). You must use ImportFilePath(), ImportDirPath() & ExportPath() to convert between the OS format & the portable format.
Here are a some examples of valid paths:
'device:/subpath/filename' 'device:/subpath/dirname/' 'subpath/filename'
Date & time is measured as the number of seconds since 0:00:00 (midnight) on 1st January 2000. Dates before that are negative! Values are BIGVALUEs, which are typically 64-bit, but may be 32-bit for some targets (such as AmigaE).
Here is a list of exceptions that are used:
exception exceptionInfo Reason "FULL" (description) Error due to disk being full (no space); file left in previous state. "FILE" (description) Error due to a serious filing system failure. "BRK" (description) Received a break signal (Ctrl-C) during a lengthy operation. "EMU" (description) Error from Method Use (an inappropriate argument or use). "EPU" (description) Error from Procedure Use (an inappropriate argument or use). "BUG" (description) Error due to a bug being detected. "MEM" NILA Error due to a lack of memory.
As Windows does not support assignments (beyond single drive letters), there is support for 'faking' them, which only works for programs compiled by PortablE. They are stored in the text file C:\PortablE\Assignments.txt, or alternatively in C:\Assignments.txt, and these can be added to (or over-ridden) by an Assignments.txt file in the current directory (not program directory!) when a program starts.
As standard PortablE requires the PEmodules: assignment, which would look something like this in the text file:
PEmodules: C:\PortablE\PEmodules
Each assignment is on a single line, with the assignment name ending in a colon, followed by some tabs or spaces, and then the target path (which must be absolute not relative). The target path must not have any spaces after it, as they will be treated as part of the path. Note that the target path can use previously declared assignments, as well as network paths. Nonsensical lines will simply be ignored.
Here's an example Assignments.txt file:
Code: C:\Users\Chris\Documents\Code PEmodules: Code:\PEmodules
Various technical details have been overlooked so far, but you may find it useful to know some of them:
This module provides a easy way of playing sounds, which is suitable for games & multimedia.
Supported OSes: AmigaOS4, AmigaOS3, AROS, MorphOS.
How to play a sound:
DEF snd:PTR TO cSnd
CreateApp().build() ->you only need to do this once!
snd := LoadSound('MySound.wav')
snd.play()
How to wait for a sound to finish playing:
snd.waitForPlayToFinish()
A more flexible way to wait for a sound to finish playing:
WHILE WaitForSoundEvent() <> snd DO EMPTY
Here's another way to play a sound:
CreateApp().build() ->you only need to do this once!
StoreSound('test', 0, LoadSound('MySound.wav'))
UseSound('test', 0).play()
The following example programs use it:
Examples/std/Multimedia/ShootEmUp/ShootEmUp.e
Released programs which are known to use it:
Ami-Ingenious ( os4depot.net/index.php?function=showfile&file=game/board/ami-ingenious.lha )
PROC LoadSound(file:ARRAY OF CHAR, allowReturnNIL=FALSE:BOOL) RETURNS sound:PTR TO cSnd PROC DestroySound(sound:PTR TO cSnd) RETURNS nil:PTR TO cSnd PROC WaitForSoundEvent() RETURNS sound:PTR TO cSnd PROC CheckForSoundEvent() RETURNS sound:PTR TO cSnd PROC StoreSound(name:ARRAY OF CHAR, number, sound:PTR TO cSnd) RETURNS storedSound:PTR TO cSnd PROC UseSound(name:ARRAY OF CHAR, number, allowReturnNIL=FALSE:BOOL) RETURNS sound:PTR TO cSnd
LoadSound() loads the given sound, and returns a cSnd object for it. The file path must be given in the portable format used by the cPath module, so you may need to use it's ImportFilePath() procedure first. If the file could not be loaded, then an exception will be raised (unless TRUE was given to allowReturnNIL, in which case NIL would be returned instead).
DestroySound() destroys the supplied sound object. Your sounds will be automatically destroyed when your program quits, so you may not need to use this! You may pass it a NIL parameter without any problem. It returns NIL for your convenience.
WaitForSoundEvent() waits for any playing sound to stop (unless one has already stopped), and then returns that sound. Note that it will only remember the most recent events (typically the last 100), so ensure that you watch for events regularly.
CheckForSoundEvent() checks if any previously playing sound has stopped, and returns that sound. If no sound has stopped, then it returns NIL.
StoreSound() & UseSound() allow you to store & retrieve sounds using a name string, and optionally a number. The string must be an 'immediate string', not one you have created. It returns the stored sound, so you can use it straight away. Here's an example of how you might use it:
StoreSound('explosion', 0, LoadSound('explosion.wav'))
UseSound('explosion', 0).play()
If you try to store more than one sound with the same name & number combination, then an exception will be raised. This is to prevent you accidentally reusing them. And if you try to use a non-existant sound, then an exception will be raised; unless you gave TRUE for allowReturnNIL, in which case NIL will be returned.
The cSnd class is a sound which can be played. Not only can you play several different sounds (from different objects) at the same time, but you can also play the same sound (from one object) several times.
For example, you can have a "shoot" sound, and play it every time the player shoots. If he fires quickly enough, then several "shoot" sounds can be playing at once.
/* Methods of cSnd */ METHOD play(playCount=1, speed=100) METHOD stop() METHOD infoLength() RETURNS milliSeconds METHOD infoIsPlaying() RETURNS isPlaying:BOOL METHOD waitForPlayToFinish() METHOD setVolume(volume) RETURNS sound:PTR TO cSnd METHOD getVolume() RETURNS volume METHOD setPan(pan) RETURNS sound:PTR TO cSnd METHOD getPan() RETURNS pan
play() starts playing the sound, using the given parameters. playCount indicates how many times the sound should be played (back to back). Use 0 if you want the sound to play forever. speed allows you to change how fast the sound is played, where 100 is normal speed, 200 is double speed, 50 is half speed, and so on.
stop() stops the sound from playing (even if playing multiple times).
infoLength() returns the length of the sound in milliseconds.
infoIsPlaying() returns whether or not the sound is currently playing.
waitForPlayToFinish() pauses until the sound has stopped playing (completely).
setVolume() & getVolume() allow you to change & retrieve volume. This is how loud the sound will be played, where 100 is maximum volume, 50 is half volume, 0 is silent, and so on. It is used by subsequent play() calls.
setPan() & getPan() allow you to change & retrieve the pan. Pan allows the sound to be forced to come more from one speaker than the other, where -100 is entirely from the left speaker, 100 is entirely from the right speaker, 0 is evenly from both speakers, and so on. It will be used by subsequent play() calls.