OPL 32 reference

Alphabetical list of OPL commands

OPL Reference (ER5/ER6)

Introduction

Functions, commands and procedures

Notation used

Program control

Procedures

Program settings

Loops, branches and jumps

Error handling

Screen and keyboard control

Files

File management

Directory management

Database files

OPL program modules

Memory management

Variable declaration

Memory, dynamic allocation

Memory, addresses pointer arithmetic

Memory, reading and writing

Printing

Numeric functions

Trigonometric functions

General numeric functions

Statistical numeric functions

Numeric conversion

String handling

Date and time

Sound

Graphics

Window and bitmap manipulation

Window and bitmap characteristics

Window and bitmap information

Graphics ‘cursor’ positioning

Graphics text

Graphics drawing commands

Menus

Dialogs

Screen messages

Context sensitive help (ER6)

OPL applications (OPAs)

Event handling

I/O operations on files and devices


Alphabetical list of OPL commands

@ operator

gCOLOR

LN

ABS

gCOLORBACKGROUND

LOADM

ACOS

gCOLORINFO

LOC

ADDR

gCOPY

LOCAL

ADJUSTALLOC

gCREATE

LOCK

ALERT

gCREATEBIT

LOG

ALLOC

gELLIPSE

LOPEN

APP

GEN$

LOWER$

APPEND

GET

LPRINT

ASC

GET$

MAX

ASIN

GETCMD$

mCARD

AT

GETDOC$

mCARDX, ER6

ATAN

GETEVENT

mCASC

BACK

GETEVENT32

MEAN

BEEP

GETEVENTA32

MENU

BEGINTRANS

GETEVENTC

MID$

BOOKMARK

gFONT

MIN

BREAK

gGMODE

mINIT

BUSY

gGREY

MINUTE

BYREF

gHEIGHT

MKDIR

CANCEL

gIDENTITY

MODIFY

CAPTION

gINFO

MONTH

CHR$

gINFO32

MONTH$

CLEARFLAGS

gINVERT

mPOPUP

CLOSE

GIPRINT

NEXT

CLS

gLINEBY

NUM$

CMD$

gLINETO

OFF, ER5

COMMITTRANS

gLOADBIT

ONERR

COMPACT

gLOADFONT

OPEN

CONST

GLOBAL

OPENR

CONST

gMOVE

PARSE$

CONTINUE

gORDER

PAUSE

COPY

gORIGINX

PEEK$

COS

gORIGINY

PEEKB

COUNT

GOTO

PEEKF

CREATE

GOTOMARK

PEEKL

CURSOR

gPATT

PEEKW

DATETOSECS

gPEEKLINE

PI

DATIM$

gPOLY

POINTERFILTER

DAY

gPRINT

POKE$

DAYNAME$

gPRINTB

POKEB

DAYS

gPRINTCLIP

POKEF

DAYSTODATE

gRANK

POKEL

dBUTTONS

gSAVEBIT

POKEW

dCHECKBOX,ER5

gSCROLL

POS

dCHOICE

gSETPENWIDTH

POSITION

dDATE

gSETWIN

PRINT

DECLARE EXTERNAL

gSTYLE

PROC .. ENDP

DECLARE OPX

gTMODE

PUT

dEDIT

gTWIDTH

RAD

dEDITMULTI

gUNLOADFONT

RAISE

DEFAULTWIN

gUPDATE

RANDOMIZE

DEG

gUSE

REALLOC

DELETE (files)

gVISIBLE ON/OFF

REM

DELETE (database)

gWIDTH

RENAME

dFILE

gX

REPT$

dFLOAT

gXBORDER

RETURN

DIALOG

gXPRINT

RIGHT$

dINIT

gY

RMDIR

DIR$

HEX$

RND

dLONG

HOUR

ROLLBACK

DO...UNTIL

IABS

SCI$

DOW

ICON

SCREEN

dPOSITION

IF...ENDIF

SCREENINFO

dTEXT

INCLUDE

SECOND

dTIME

INPUT

SECSTODATE

dXINPUT

INSERT

SETDOC

EDIT

INT

SETFLAGS

ENDA

INTF

SETHELP, ER6

EOF

INTRANS

SETHELPUID, ER6

ERASE

IOA

SETPATH

ERR

IOC

SHOWHELP, ER6

ERR$

IOCANCEL

SIN

ERRX$

IOCLOSE

SIZE, ER6

ESCAPE OFF/ON

IOOPEN

SPACE

EVAL

IOREAD

SQR

EXIST

IOSEEK

STD

EXP

IOSIGNAL

STOP

EXTERNAL

IOW

STYLE

FIND

IOWAIT

SUM

FINDFIELD

IOWAITSTAT

TAN

FIRST

IOWAITSTAT32

TESTEVENT

FIX$

IOWRITE

TRAP

FLAGS

IOYIELD

UADD

FLT

KEY

UNLOADM

FONT

KEY$

UPDATE

FREEALLOC

KEYA

UPPER$

gAT

KEYC

USE

gBORDER

KILLMARK

USUB

gBOX

KMOD

VAL

gBUTTON

LAST

VAR

gCIRCLE

LCLOSE

VECTOR

gCLOCK

LEFT$

WEEK

gCLOSE

LEN

WHILE...ENDWH

gCLS

LENALLOC

YEAR


OPL Reference (ER5/ER6)


Introduction

All of the OPL functions and commands are described in detail; they are grouped by the nature of their task or function. Occasional items may be repeated if they are associated with more than one function.

The OPL language has gone through a number of developments and enhancements during its lifetime. Also, implementation of OPL on different Psion/Symbian machines can also vary.  This reference only includes the commands available in OPL on EPOC R5 and R6 (OPL32). Commands specific to older versions of OPL (OPL16, for example on Series 3 and Sibo machines) are not included in this reference.

Where necessary brief OPL examples are given, however, error-handling code is not usually included to keep the examples short and simple. For reliable programs it is always advisable to include code that tests for errors, attempts to recover or closes down gracefully.


Functions, commands and procedures

OPL functions are so called because they return a value, e.g.

s = SIN(angle)

Returns the sine of angle (in radians) to the variable s.

OPL commands carry out a specific task e.g.

CLS

Clears the text screen, CLS takes no arguments.

Or

AT x%,y%

Positions the cursor in the text window. The AT command takes two arguments to position the cursor at x% characters across and y% lines down the screen.  Arguments are any values required as part of a command or function call. Parameters are values passed to a procedure. In programming related text the terms ‘arguments’ and ‘parameters’ are often used interchangeably.

OPL procedures are sections of OPL code that you define; they can take a number of parameters and may return a single numeric or string value.


Notation used

For each command or function, all of the alternative options are given, where necessary the alternatives are marked which are only applicable to a particular machine or version of OPL.

Commands and functions can be entered in any combination of lower and upper case, except where clearly stated to the contrary.

Commands must be separated from their parameters by inserting a space character. Each parameter must be separated from the next by a comma ( , ).  Function keywords are followed immediately by an opening bracket ‘(‘. Parameters must be separated from each other by a comma and the list of function parameters must be terminated with a closing bracket ‘ )’.

Default values may be assumed if some parameters are not supplied. Default values for particular commands and functions are given in the individual command/function descriptions that follow.

Note: 'var' variables and #prefixes

If a parameter is preceded by 'var' you don’t need to type in 'var', it just indicates that a local or global variable must be used and not a constant. When you see 'var' the address of the variable is passed (see also BYREF for passing variables to OPX procedures), not the value held (it happens automatically, you don't have to use ADDR).

However, if you already hold the address of the variable, you can add a '#' prefix to a 'var' argument, this tells OPL that the expression following is the address to be used, not a variable whose address is to be taken.

Single elements of arrays may also be used for parameters labelled as ‘var’, but not database field variables or procedure parameters.

Note: OPL constants

OPL allows the inclusion of header files, and many useful OPL related constants are provided in a header file named CONST.OPH. Many of the ‘standard’ constants are used in the OPL examples given here.


Program control


Procedures

PROC...ENDP

Define the start and end of a procedure.

CONST

Declare a constant with global scope

INCLUDE

Include other files into an source file.

DECLARE OPX

Used in OPX header files to define its name etc.

Notes:

see DECLARE EXTERNAL and EXTERNAL for detecting procedures called before they have been defined.


PROC .. ENDP

PROC pname:(argumentlist)
...
ENDP

The PROC keyword declares the beginning of a new procedure, ENDP defines its end, and the pname: parameter defines its name. Names of procedures can be up to 32 characters long, including any variable type specifier.

The argumentlist for a procedure is optional and may be used to pass parameters to the procedure. For example:

PROC PrintString:(xPos%,yPos%,value$)

ENDP

defines a procedure that takes three arguments; the integers xPos% and yPos% and the string value$.

In OPL all arguments to procedures are passed by value and their content cannot be modified inside the procedure. It is not possible to pass variables to procedures by reference, except to some of the internal functions like gINFO32 and to OPX procedures (see BYREF). For example, the following code will not compile and result in a ‘Bad Assignment’ error:

PROC Test:(someVar%)
  someVar% = 10  REM “Bad assignment” error here
ENDP

Every procedure can (but does not have to) return a value (see RETURN). If a procedure does not return a value, a default value of 0 is returned. To return a specific type of value from a procedure (i.e. a string or long integer), the type specifier should follow the procedure name. If no type specifier follows the procedure name, the procedure will return a float:

PROC GetName$: REM returns a string value ($)
PROC GetRedValue%: REM returns an integer (%)
PROC GetRGBColor : REM returns a long integer ( )
PROC GetTemperature: REM returns a float


CONST

CONST KConstantName=value

Declares constants that are treated as literal values, and are not stored as data. CONST declarations must be made outside any procedure, usually at the beginning of the module.

KConstantName uses the normal type-specifiers (%, , $ or non for floating-point values) as for variables. CONST values have global scope, and are not overridden by local or global variables with the same name: in fact the translator will not allow the declaration of a local or global variable with the same name. By convention, all constants are usually named with a leading K to distinguish them from variables.

Note that it is not possible to define constants with values -32768 (for integers) and -214748648 (for long integers) in decimal notation, but hexadecimal notation may be used instead (i.e. values of $8000 and 80000000 respectively).

See INCLUDE, EXTERNAL.


INCLUDE

INCLUDE file$

Includes a file, file$, which may contain CONST definitions, prototypes for OPX procedures and prototypes for module procedures. The included file may not include module procedures themselves. Procedure and OPX procedure prototypes allow the translator to check parameters and coerce numeric parameters (that are not passed by reference) to the required type.

Including a file is logically identical to replacing the INCLUDE statement with the file’s contents.

The filename of the header may or may not include a path. If it does include a path, then OPL will only scan the specified folder for the file. However, the default path for INLCUDE is \System\Opl\, so when INCLUDE is called without specifying a path, OPL looks for the file firstly in the current folder and then in \System\Opl\ in all drives from Y: to A: and then in Z:, excluding any remote drives.

Note:

Individual INCLUDE statements are needed in all program modules (loaded with LOADM) where the CONST and prototype information is used, not just in the main program module. 

See CONST, EXTERNAL.


DECLARE OPX

DECLARE OPX opxname,opxUid ,opxVersion
  ...
END DECLARE

Declares an OPX. opxname is the name of the OPX, opxUid its UID and opxVersion its version number. Declarations of the OPX’s procedures should be made inside this structure.


Program settings

SETFLAGS

Change the behaviour of a running program

CLEARFLAGS

Clear flags set to affect the behaviour of a running program


SETFLAGS

SETFLAGS flags

Sets flags to produce various effects when running programs. Use CLEARFLAGS to clear any flags which have been set. The effects that can be achieved are as follows:

flags

effect

1

Restricts the memory available to your application to 64K, emulating OPL16 systems. Should only be used, if required, at the beginning of a program. Changing this setting repeatedly will have unpredictable effects.

2

Enables auto-compaction on closing databases. This can be slow, but it is advisable to use this setting when lots of changes have been made to a database.

4

Enables raising of overflow errors when floating-point values are greater than or equal to 1.0E+100 in magnitude, instead of allowing 3-digit exponents (for backwards compatibility).

8

Force the MENU keyword to behave in the same way as in previous OS releases (ER6 only)

16

Forces IOPEN and LOPEN to write out  ASCII test files instead of Unicode ones (ER6 only)

10000

Enables GETEVENT, GETEVENT32 and GETEVENTA32 to return the event code $403 to ev (1) when the machine switches on.

By default these flags are cleared.

See also GETEVENT32, CLEARFLAGS, MENU, IOOPEN, LOPEN.


CLEARFLAGS

CLEARFLAGS flags

Clears the flags given in flags if they have previously been set by SETFLAGS, returning to the default.

See SETFLAGS.


Loops, branches and jumps

 

Repeat a set of instructions:

DO...UNTIL

until a condition is true

WHILE...ENDWH

while a condition is true

BREAK

Break to the end of a repeating set of instructions

CONTINUE

Continue at the start of a repeating set of instructions

IF...ELSEIF...ELSE...ENDIF

Perform instructions according conditional tests

GOTO

Go to a specified label

VECTOR...ENDV

Jump to one of a list of labels

@ operator

Call a procedure according to the name in a string expression.

RETURN

To the calling procedure

STOP

Stop the program


DO...UNTIL

DO
  statement
  statement
  .
  .
UNTIL condition

DO causes the set of statements which follow it to execute repeatedly until the condition specified by UNTIL is met, in which case execution continues from the statement following UNTIL. Each DO must have a matching UNTIL to end the loop. This type of loop construct will always execute the statements in between the DO and UNTIL at least once.

If the tested condition is never met, the program will loop forever.  If the limit of eight DO… UNTIL levels of nesting is exceeded a ‘too complex’ error will be generated.

See BREAK and CONTINUE.


WHILE...ENDWH

WHILE condition
  ..
  ..
  ..
ENDWH

Loop, and repeatedly perform the set of instructions between the WHILE and the ENDWH statements, as long as the expression condition returns logical TRUE - non-zero.

If expression is not true (zero or FALSE), the program jumps to the statement after the ENDWH statement. Each WHILE must be closed with a matching ENDWH.

If the tested condition is never met, the program will loop forever.  If the limit of eight WHILE… ENDWH levels of nesting is exceeded a ‘too complex’ error will be generated.

See BREAK and CONTINUE.


BREAK

BREAK

Exit from a program DO...UNTIL loop or a WHILE...ENDWH loop to exit the loop and immediately execute the line following the UNTIL or ENDWH statement.

For example:

DO
  ...
  IF a=b
    BREAK REM break out of loop to x%=3 statement
  ENDIF
  ...
UNTIL KEY
x%=3
...


CONTINUE

CONTINUE

Jump to the test condition of a program loop, i.e. go immediately to the UNTIL...  statement of a DO...UNTIL loop, or to the WHILE... statement of a WHILE...ENDWH loop.

For example:

DO
  ...
  ...
  IF a 3.5
    CONTINUE REM continue loop at UNTIL
  ENDIF
  ...
  ...
UNTIL a b


IF...ENDIF

IF condition1
  ...
ELSEIF condition2
  ...
ELSE
  ...
ENDIF

Control the execution of program statements depending on one or more specified conditions. The program executes one of the following, depending on which condition (if any) is true:

After the ENDIF statement, execution of following statements continues as normal.

IF, ELSEIF, ELSE and ENDIF must be in that order.

Every IF statement must be matched with an ENDIF.

IF...ENDIF constructs may be nested inside others, for example:

IF condition1
  ...
ELSE
  IF condition2
    ...
  ENDIF
  ...
ENDIF

If the limit of eight IF… ENDIF levels of nesting is exceeded a ‘too complex’ error will be generated.


GOTO

GOTO label or GOTO label::
..
..
label::

Goes to the line following the label:: and continues from there.  The label:


VECTOR...ENDV

VECTOR index%
  label1,label2,...
  labelN
ENDV

Jump to a label in a list, depending on the value of index%.

The VECTOR and ENDV statements enclose a list of names of labels, where the labels themselves appear elsewhere in the same procedure. The list may spread over several lines, with a comma separating consecutive names in any one line. The last name in a line should not have a following comma.

VECTOR index% jumps to the label corresponding to number index% in the list that follows - if index% is 1 this will be the label matching the first name in the list, and so on.  If index% is not in the range 1 to N, where N is the number of labels, the program continues with the statement after the ENDV statement.

Using VECTOR...ENDV can avoid the need to write a very long IF...ENDIF constructs, with ELSEIF used many times.

For example:

...
VECTOR p%
  FUNCA,FUNCX
  FUNCR
ENDV
PRINT p% was not 1/2/3 :GET :GOTO end
FUNCA::
PRINT p% was 1 :GET :GOTO end
FUNCX::
PRINT p% was 2 :GET :GOTO end
FUNCR::
PRINT p% was 3 :GET :GOTO end
...
end::
...

Here, if p% is 1, VECTOR jumps to the label FUNCA::. If it is 2, it jumps to FUNCX::, and if 3, to FUNCR::. If p% is any other value, the program continues with the statement after the ENDV statement.


@ operator

r% = @%(procn$):(parameters)

Call a procedure by name, where a string expression holds the procedure name. This allows a program to ‘derive’ the name of a procedure to call under particular circumstances.

Use an @ symbol, optionally followed by a character to show what type of value is returned. For example, use a % character to return an integer value. The following examples show the four types of value that can be returned:

r% = @%(procn$):(parameters) for integer
r = @ (procn$):(parameters) for long integer
r$ = @$(procn$):(parameters) for string
r = @(procn$):(parameters) for floating-point

For example, if procn$ = “myproc” then:

r$ = @$(procn$):(a$,b$) REM is equivalent to
r$ = myproc$:(a$,b$)

Upper or lower case characters can be used (the case is ignored), and the string expression must not include the symbol for the return type (i.e. %, or $).


RETURN

RETURN

RETURN variable

Terminate the execution of a procedure and return control to the point where that procedure was called (ENDP does this automatically).

RETURN variable, in addition to returning control to the calling procedure, passes the value of variable back to the calling procedure. The variable may be of any type and may be an array element, for example RETURN x%(3). Only one value may be returned.

RETURN on its own, and the default return through ENDP, causes the procedure to return the value 0 or a null string ( ).

For example:

PROC price:
LOCAL x
  PRINT Enter price: ,
  INPUT x
  x=vat:(x)
  PRINT x
  GET
ENDP

PROC vat:(exclude)
  RETURN exclude+17.5%
ENDP


STOP

STOP

Terminates the running program as soon as the command is encountered.

Note:

STOP may not be used during an OPX callback; if it is used it will raise a ‘STOP used in callback’ error.


Error handling

ERR

After an error, get the error number

ERR$

Error message

ERRX$

Extended error message

ONERR

Declare or remove an error-handler

RAISE

Raise an error

TRAP

Let the program continue after an error

REM

Put an explanatory comment in your program


ERR

error% = ERR

Return the number of the last error that occurred or 0 if no error had occurred.

For example:

...
PRINT Enter age in years ,
DO
  TRAP INPUT age%
  IF ERR=-1
    PRINT Number please ,
  ENDIF
UNTIL ERR=0
...

You can set the value returned by ERR to 0 (or any other value) by using:

TRAP RAISE 0.

See also: ERR$, ERRX$.


ERR$

error$ = ERR$(error%)

Return the error message for the specified error code, error%.

ERR$(ERR) gives the message for the last error which occurred.

For example:

...
TRAP OPEN B:\FILE ,A,field1$
IF ERR
  PRINT ERR$(ERR)
  RETURN
ENDIF
...


ERRX$

x$ = ERRX$

Returns the current extended error message (when an error has been trapped), e.g.  ‘Error in MODULE\PROCEDURE,EXTERN1,EXTERN2,...’ would be presented in an Alert dialog if such an error had not been trapped. Allows the list of missing externals, missing procedure names, etc. to be found when an error is trapped by a handler.

Return the number of the last error that occurred or 0 if no error had occurred.

See also: ERR, ERR$.


ONERR

ONERR label or ONERR label::
..
..
ONERR OFF
...

The ONERR label instruction establishes an error handler in a procedure.

Normally when an error occurs the program is halted with an error message. If an error handler is declared with ONERR then an error will cause the program to jump to label:: instead. The code following label:: can then find out the error code and handle matters appropriately.

The label may be up to 32 characters long, starting with a letter. It ends in a double colon (::), although the colons are not needed in the ONERR statement.

ONERR OFF disables the ONERR command, so that any errors occurring after the ONERR OFF statement no longer jump to the label.

It is advisable to use the command ONERR OFF immediately after the label. This is to prevent an error in the error handling code causing an infinite loop.

For example:

ONERR argerr
PRINT SQR(-1) REM error handled
argerr::
ONERR OFF

The ONERR command has a lower priority than TRAP. In other words, a TRAPped command will not trigger the error handler, but any others will.

The following example uses RAISE to forcibly invoke the error handler installed with ONERR.

PROC test:
ONERR errh::
  PRINT Error occurs here
  RAISE -1 REM General failure
  REM this line will never be reached
errh::
  PRINT Error handling code
ENDP


RAISE

RAISE error%

Raise an error.

The error raised is error number error%. This may be one of the errors listed in the error handling chapter, or a new error number defined by the programmer.

The error is handled by the error processing mechanism currently in use - either OPL's own, which stops the program and displays an error message, or the ONERR handler if ONERR is on.


TRAP

TRAP command

Trap errors from a command. The TRAP command may precede any of these commands:

Data file commands

APPEND, UPDATE, COMPRESS, DELETE, BACK, NEXT, LAST, FIRST, POSITION, USE, CREATE, OPEN, OPENR, CLOSE, MODIFY, INSERT, PUT, CANCEL.

File and device commands

COPY, ERASE, RENAME, LOPEN, LCLOSE, LOADM, UNLOADM

Directory commands

MKDIR, RMDIR

Data entry commands

EDIT, INPUT

Graphics commands

gSAVEBIT, gCLOSE, gUSE, gUNLOADFONT, gFONT, gPATT, gCOPY

For example, TRAP DELETE fred.txt .

Any error resulting from the execution of the associated command will be trapped.  Program execution will continue at the statement after the TRAP statement, but ERR will be set to the error code.

TRAP has a higher priority than any ONERR that has been set.

You can set the value returned by ERR to 0 (or any other value) by using:

TRAP RAISE x% REM Sets the value of ERR to x% and clears the trap flag.


REM

REM comment

Designate text as a program comment.

The REM keyword precedes a remark included to explain how a program works. All text after the REM up to the end of the line is ignored.

If REM follows a statement on the same line it need only be preceded by a space, not a space and a colon.

For example:

INPUT a
b=a*.175 REM b = VAT

The REM keyword may also be used to temporarily disable a program statement during debugging.


Screen and keyboard control

SCREEN

Set the size and position of the text window

CLS

Clear the text window

SCREENINFO

Get text window information

FONT

Set text window font

STYLE

Set text window character style

gUPDATE

Control when the window server updates the screen

AT

Position the cursor

CURSOR ON/OFF

Display or hide the cursor

EDIT

Display a string to be edited and get a value from the keyboard

INPUT

Get a value from the keyboard

PRINT

Display text, numbers etc.

PAUSE

For a number of 1/20ths of seconds

 

Wait until a key is pressed and return the key pressed

GET

as a character code

GET$

as a character string

GETEVENT

For key press events see the section on Event handling later.

 

Find out which key was pressed, if any

KEY

as a character code (no pause)

KEY$>

as a character string (no pause)

GET

as a character code (pause for keypress)

GET$

as a character string (pause for keypress)

KMOD

Find out what combination of key modifiers was pressed

ESCAPE ON/OFF

Disable or enable Ctrl-ESC  from quitting a running program

OFF

Turn the machine off (ER5)


SCREEN

SCREEN width%,height%
SCREEN width%,height%,xchar%,ychar%

Changes the size of the window in which text is displayed using PRINT, AT etc.

The arguments xchar% and ychar% specify the character position of the top left corner. If these arguments are not supplied, the text window is centred in the screen.  An OPL program can initially display text to the whole screen.


CLS

CLS

Clears the contents of the text window.

The cursor is moved to the beginning of the top line. If you have used CURSOR OFF the cursor is still positioned there, but is not displayed.


SCREENINFO

SCREENINFO var info%()

Get information about the text window.

This information is useful when doing PRINT commands, etc.  This keyword allows you to mix text and graphics. It is required because while the default window (ID 1) is the same size as the physical screen, the text window is slightly smaller and is centred in the default window. The gaps of a few pixels around the text screen, referred to as the left margin and top margin, depend upon the font in use.  On return, the array info%(), which must have at least 10 elements, contains the following information:

info%(1)

left margin in pixels

info%(2)

top margin in pixels

info%(3)

text window width in character units

info%(4)

text window height in character units

info%(5)

reserved (window server id for default window)

In OPL16

info%(6)

font id (as set by FONT)

info%(7)

pixel width of text window character cell

info%(8)

pixel height of text window line

info%(9)

reserved

info%(10)

reserved

Font ID is a 32-bit integer and therefore will not fit into a single element of info%(). Hence, the least significant 16 bits of the font ID are returned to info%(9) and the most significant 16 bits to info%(10).

info%(6)

unused

info%(7)

pixel width of text window character cell

info%(8)

pixel height of text window line

info%(9)

least significant 16 bits of the font ID

info%(10)

most significant 16 bits of the font ID

Note:

Initially SCREENINFO returns the values for the initial text screen. Subsequently any keyword that changes the size of the text screen font, such as FONT, will change some of these values and SCREENINFO should therefore be called again.


FONT

FONT font ,style%

Set the font and style for the default text window.

FONT clears the screen and automatically resizes the text window and the default graphics windows to the maximum size.

Note:

FONT -$3fff,0 leaves the current font and style, it just adjusts the window sizes and clears them.

The font number, font% or font , is the same as for gFONT, and the style, style%, is the same as for gSTYLE.

The table below lists the fonts provided in the system.

Note:

Fonts are identified by a 32-bit UID. OPL does provide some mapping where possible between old OPL16 font IDs and OPL font UIDs. A full list of the fonts is provided in a header file CONST.OPH.

In the table below, Swiss and Arial refer to fonts without serifs while Roman and Times fonts either have serifs (e.g. font 6) or are in a style designed for serifs, but are too small to show them. Courier is a mono-spaced font, i.e. has characters that are all the same width (and have their pixel size as width x height). With proportional fonts, each character can have a different width.

Font

Name

Pixels WxH
or H only

Name

Pixels WxH
or H only

4

Mono

8x8

Courier

8

5

Roman

8

Times

8

6

Roman

11

Times

11

7

Roman

13

Times

13

8

Roman

16

Times

15

9

Swiss

8

Arial

8

10

Swiss

11

Arial

11

11

Swiss

13

Arial

13

12

Swiss

16

Arial

15

13

Mono

6x6

Tiny (mono)

3x4

The font style can be modified according to the following table.

style%

effect

OPL constant

0

normal style

KgStyleNormal%

1

bold

KgStyleBold%

2

underlined

KgStyleUnder%

4

inverse

KgStyleInverse%

8

double height

KgStyleDoubleHeight%

16

mono

KgStyleMonoFont%

32

italic

KgStyleItalic%

These styles can be combined by ORing their values together for example, to set underlined and double height and Times Roman 8 point, use:

FONT 5, 2 OR 8

Alternatively add the style% values together. For example, to set bold underlined and double height use:

FONT 5,11 (as 1+2+8=11)

To change fonts on a Series 3 the IOW function can be used.

See also STYLE, gFONT and gSTYLE.


STYLE

STYLE style%

Set the text window character style.

The style% argument can be 2 for underlined, or 4 for inverse.


gUPDATE

gUPDATE ON
gUPDATE OFF
gUPDATE

Update the screen, or switch screen-updating on/off.

The screen of the machine in OPL is, by default, updated whenever anything is drawn to it.  The gUPDATE OFF command switches off this feature. Drawing commands are buffered and the screen is automatically updated only when the command buffer is full, or when a screen or keyboard function that has to return a value immediately is called. The screen will be updated as few times as possible (though some keywords will always cause an update).

Switching updating off can result in a considerable speed improvement in some cases, for example, where a program contains sequences of graphics commands. In such a case, each sequence should be followed by gUPDATE. It is certainly advantageous to use gUPDATE OFF when about to write exclusively to bitmaps. An update can be forced at any time by using the gUPDATE command on its own, and gUPDATE ON returns to normal screen updating.

The gUPDATE command affects anything that displays to the screen. If a program uses a lot of PRINT commands, gUPDATE OFF may make a significant difference in speed.

Note:

With gUPDATE OFF, the buffering of graphics commands may delay the detection of runtime errors, thus causing the location of such errors to be incorrectly reported. For this reason, gUPDATE OFF is best used in the final stages of program development, and even then you may have to remove it to locate some errors.


AT

AT indent%,rowsdown%

Position the cursor at indent% characters across the text window and rowsdown% rows down.

The command AT(1,1) always moves to the top left corner of the text window. Initially the text window is the full size of the screen. The size and position of the text window is changed using the SCREEN command.

A common use of AT is to display strings at particular positions in the text window, for example:

AT 5,10
PRINT Fixed message

For example:

PROC records:
LOCAL k%
OPEN M:\ODB\CLIENTS.ODB ,A,nm$,tl$
  DO
    CLS
    AT 1,7
    PRINT Press a key to
    PRINT step to next record
    PRINT or Q to quit
    AT 2,3 :PRINT A.nm$
    AT 2,4 :PRINT A.tl$
    NEXT
    IF EOF
      AT 1,6 : PRINT End of file
      FIRST
    ENDIF
    k% = GET
  UNTIL k% = %Q OR k% = %q
  CLOSE
ENDP


CURSOR

CURSOR OFF
CURSOR ON
CURSOR winId%,ascent%,width%,height%,type%

CURSOR ON switches the text cursor on at the current cursor position. Initially no cursor is displayed.

You can switch on a graphics cursor in a window by following CURSOR with the ID of the window, winId%. This replaces any text cursor. At the same time, you can also specify the cursor's shape, and its position relative to the baseline of text.  The ascent% argument is the ascent - the number of pixels (-128 to 127) by which the top of the cursor should be above the baseline of the current font.  The height% and width% arguments (both from 0 to 255) are the cursor's height and width.

An error is raised if winId% specifies a bitmap rather than a window.

If you do not specify these three parameters, the following default values are used:

ascent% = font ascent

height% = font height

width% = 2

If type% is given it can have the following effects:

type%

cursor type

1

obloid (not S5)

2

Not flashing

4

Grey

The values can be added together to combine effects, e.g. if type% is 6 a grey non-flashing cursor is drawn.

The instruction CURSOR OFF switches off any cursor.

For a text cursor see also AT. For a graphics cursor see also gAT, gX, gY.


EDIT

EDIT string_variable$
EDIT log.field$

Display a string variable that the user can edit directly on the screen. All the usual editing keys are available - the arrow keys move along the line, Esc clears the line, and so on.  When the user has finished editing, Enter is pressed to confirm the changes. If Enter is pressed before any changes have been made, then the string will be unaltered.  If EDIT is used in conjunction with a PRINT statement, a comma should be used at the end of the PRINT statement, so that the string to be edited appears on the same line as the displayed string), e.g.:

PRINT Edit address: ,
EDIT A.address$

TRAP EDIT

If the Esc key is pressed while no text is on the input line, the 'Escape key pressed' error (number -114) will be returned by ERR - provided that the EDIT has been trapped, using TRAP EDIT. This feature can used to allow the user to press the Esc key to abandon editing a string.


INPUT

INPUT variable
INPUT log.field

Wait for a value to be entered at the keyboard, and then assign the value entered to a variable or data file field. The value can be edited as it is typed in. All the usual editing keys are available - the arrow keys move along the line, ESC key clears the line and so on.

If inappropriate input is entered (for example, a string when the input was to be assigned to an integer variable) a '?' is displayed and a new value can be entered. (See also the following description of TRAP INPUT).

The INPUT command is usually used in conjunction with a PRINT statement:

PROC temp:
LOCAL cent
  DO
    PRINT Temperature?
    PRINT (centigrade) ;
    INPUT cent
    PRINT That's ;32+cent*9/5, fahrenheit.
    GET
  UNTIL 0
ENDP

Note:

The ';' at the end of the PRINT statement, so that the cursor waiting for input appears on the same line as the message.

TRAP INPUT

If a bad value is entered (for example abc for a%) in response to a TRAP INPUT, the '?' is not displayed. Instead, the value of the variable is unchanged, the appropriate error condition is set and control passes on to the next line of the procedure.  The error number of any error that has occurred can be found by calling the ERR function.  For example, if the ESC key is pressed while no text is on the input line, the 'Escape key pressed' error (number -114) will be returned by ERR (provided that the INPUT has been trapped). This feature could be used to allow someone to press the ESC key to avoid inputting a value.

See also EDIT. This works in a similar way to INPUT, except that it displays a string to be edited and then assigns it to a variable or field. It can only be used with strings. Use dEDIT, for editable string input in a dialog.


PRINT

PRINT list

Display the results of a list of expressions in the OPL text window.

The list can be punctuated in one of these ways:

There can be as many items as needed in the list. A single PRINT on its own just moves to the next line.

For example, on 1st January 1990:

PRINT TODAY is ,
PRINT DAY; . ; MONTH; . ;YEAR

would display:

TODAY is 1.1.1990.

Furthermore:

PRINT 1 displays 1

PRINT Hello displays Hello

PRINT Number ,1 displays Number 1

Use LPRINT to print to an attached device, such as a printer, or to a file.

The output from the PRINT command is governed by the text attributes set by FONT and STYLE.


PAUSE

PAUSE timcode%

Pause the program for a certain time, (or until a key is pressed), depending on the value of timcode%:

timcode%

action

0

wait for a key to be pressed

+ve

pause for timcode% twentieths of a second

- ve

pause for timcode% twentieths of a second, or until a key is pressed.

So PAUSE 100 would make the program pause for 5 seconds (i.e. 100/20) , and PAUSE -100 would make the program pause for 5 seconds, or until a key is pressed.

If timcode% is 0 or negative, a following GET, GET$, KEY, KEY$, etc. will return the key press which terminated the pause. To discard this key press, if it is not required, clear the buffer after the PAUSE with a single KEY function:

PAUSE 0 :KEY


GET

keycode% = GET

Wait for a key to be pressed and return the character code for that key.

For example, if the 'A' key is pressed with Caps Lock off, the integer returned is 97 (a), or 65 (A) is returned if 'A' was pressed with the Shift key down.

See also KMOD for modifier key testing e.g., Shift, Ctrl etc.


GET$

keypress$ = GET$

Wait until a key is pressed and then return which key was pressed, as a string. For example, if the 'A' key is pressed in lower case mode, the string returned is a

See also KMOD for modifier key testing e.g., Shift, Ctrl etc.


KEY

keycode% = KEY

Returns the character code of the last key pressed, if there has been one since last calling one of the keyboard functions INPUT, EDIT, GET, GET$, KEY, KEY$ or GETEVENT, (and the menu and dialog input handling keywords).

If no key has been pressed, zero is returned.

See KMOD to check whether modifier keys (Shift, Ctrl, Fn or Caps Lock) were used.

This command does not wait for a key to be pressed, unlike GET.


KEY$

k$ = KEY$

Returns the last key pressed as a string, if there has been a keypress since last calling one of the keyboard functions INPUT, EDIT, GET, GET$, KEY, KEY$ or GETEVENT, (and the menu and dialog input handling keywords).

If no key has been pressed, a null string ( ) is returned.

See KMOD to check whether modifier keys (Shift, Ctrl, Fn or Caps Lock) were used.

This command does not wait for a key to be pressed, unlike GET$.


KMOD

modcode% = KMOD

Return a code representing the state of the modifier keys (whether they were pressed or not) at the time of the last keyboard access, (such as a GET or a KEY function).

The modifiers have these codes:

key state

decimal

hex

OPL constant

Shift key down

2

$2

KkmodShift%

Control key down (not HC)

4

$4

KkmodControl%

Caps Lock on

16

$10

KkmodCaps%

Fn down

128

$80

KkmodFn%

If there was no modifier, the function returns 0. If a combination of modifiers was pressed, the sum of their codes is returned - for example 18 is returned if Shift (2) was pressed, and Caps Lock was on (16).

The KMOD function should only be used immediately after a KEY, KEY$, GET or GET$ statement.

The value returned by KMOD has one binary bit set for each modifier key used. To see which modifier keys were held down the bits that are set can be tested using the logical operator AND on the value returned by KMOD.

For example:

PROC modifier:
LOCAL k%,mod%
  PRINT Press a key
  k% = GET
  CLS
  mod% = KMOD
  PRINT You pressed ,k%, with
  IF mod% = 0
    PRINT no modifier
  ENDIF
  IF mod% AND 2
    PRINT Shift down
  ENDIF
  IF mod% AND 4
    PRINT Control down
  ENDIF
  IF mod% AND 16
    PRINT Caps Lock on
  ENDIF
  IF mod% AND 32
    PRINT Fn down
  ENDIF
ENDP

If KMOD returns 48 (i.e. 32+16) to mod%, the expression mod% AND 32 returns 32, that is logical TRUE, so Fn down is displayed; mod% AND 2 returns 0, so Shift down is not displayed.


ESCAPE OFF/ON

ESCAPE OFF
ESCAPE ON

Stop Ctrl-Esc being used to break out of the program when it is running, (ESCAPE OFF). The ESCAPE ON command re-enables this feature.

ESCAPE OFF takes effect only in the program in which it occurs. The Ctrl-Esc hotkey is automatically enabled again when you run another program.

Note:

If your program enters a loop that has no logical exit, and ESCAPE OFF has been used, you cannot exit the program. The only way to kill the program is to use the Ctrl-Shift-Fn-K key combination.


OFF, ER5

OFF
OFF seconds%

Switch the machine off.

When the machine is switched on again, the statement following the OFF command is executed, for example:

OFF :PRINT Back on again

By specifying an integer, seconds%, between 3 and 16383, the machine can be switched off for that number of seconds and then automatically turns back on and continues with the next line of the program (16383 seconds is about 4½ hours). The machine can be turned on before the expiry of this period with a normal switch-on keypress.  The minimum time to switch off is 5 seconds. EPOC32 also prevents switch off if there's an absolute timer outstanding and due to go off in less than 5 seconds.

Warning:

Take care with the use of the OFF command. If, due to a programming mistake, a program uses OFF in a loop, the user may find it impossible to switch the Psion back on, and may have to reset the computer.

The OFF command is fairly brutal. Don't use it if there could be other processes running which aren't expecting the computer to suddenly or repeatedly switch off. This is almost always the case, so use OFF with care.

Note (ER6):

ER6 based devices do not turn ‘off’ in the same way as previous ER5-based devices. Instead they have a more complex system of phased power-down for items such as the screen. Currently, the OFF keyword does not support these new power-down features and so should not be used in OPL programs. If your code does call OFF then you will receive a Not Supported (KErrNotSupported%) error.


Files


File management

COPY

Copy files

DELETE

Delete files

RENAME

Rename files

EXIST

Check if certain files exist

DIR$

Find out what files exist

PARSE$

Generate a full filename specification and get information on the components

SPACE

Find out how much free space there is on a device


COPY

COPY source$,dest$

Copy the file source$, which may be of any type, to the file dest$. Any existing file with the name dest$ is deleted. You can copy from one device to another.  Use the appropriate file extensions to indicate the type of file, and wild cards if you wish to copy more than one file at a time:

To copy all the OPL files from the root directory of c: to d:\backup\, for example:

COPY C:\*.OPL , D:\BACKUP\

If source$ contains wildcards, dest$ may specify either a filename similarly containing wildcards or just the device and directory to which the files are to be copied under their original names.

Example: To copy all the files from internal memory (in \OPL) to D:\ME\:

COPY “C:\OPL\*”,“D:\ME\”

Note:

Remember the final backslash on the directory name.


DELETE

DELETE file$

Deletes any type of file.

You can use wild cards - for example, to delete all the OPL files in C:\

DELETE C:\OPL\*.OPL

See DELETE under Data files for deleting a table from an database.


RENAME

RENAME file1$,file2$

Renames file1$ to file2$.

Any type of file can be renamed, but the names may not include wild cards.

Renaming across directories, for example:

RENAME \dat\x.odb , \n\x.odb

is valid. If you're renaming across directories, you can leave out the destination filename.

The source filename will be used by default.

For example:

PRINT Old name: :INPUT a$
PRINT New name: :INPUT b$
RENAME a$,b$


EXIST

e% = EXIST(filename$)

Check to see that a file or directory exists – see note below.

Returns -1 (true) if the file exists and 0 (false) if it doesn't.

Use this function when creating a file to check that a file of the same name does not already exist, or when opening a file to check that it has already been created:

...
IF NOT EXIST( CLIENTS )
  CREATE CLIENTS ,A,nm$
ELSE
  OPEN CLIENTS ,A,nm$
ENDIF
...

Note:

Always include the file extension in the file name.


DIR$

file$ = DIR$(spec$) then
file$ = DIR$( )

Lists filenames, including subdirectory names, matching a file specification. You can include wild cards in the file specification. If spec$ is just a directory name, include the final path delimiter on the end - for example, M:\TEMP\ with trailing backslash on a DOS-type filing system, such as the Series 3a. Use the function like this:

To list all the .DBF files in D:\DAT\, for example:

PROC dir:
LOCAL d$(128)
  d$=DIR$( D:\DAT\*.DBF )
  WHILE d$
    PRINT d$
    d$=DIR$( )
  ENDWH
  GET
ENDP


PARSE$

p$ = PARSE$(file$,rel$,var off%())

Return a full file specification from the filename file$.

Any missing information is filled in from rel$.

The offsets to the various file specification components in the returned string are returned in off%() which must be declared with at least 6 integers:

off%(1)

filing system offset (1 always)

off%(2)

device offset

off%(3)

path offset

off%(4)

filename offset

off%(5)

file extension offset

off%(6)

flags for wild cards in the returned string

For example, after this call:

p$=PARSE$( datafile , B:\ , off%())

the string p$ might be set to B:\datafile.dat. The contents of off%(4) in this case would be 4, because the filename starts at character position 4 in p$.  The flag values in off%(6) are given below.

off%(6)

meaning

0

no wild cards

1

wildcard in filename

2

wildcard in file extension

3

wildcard in both

If rel$ is not itself a complete file specification, the current filing system, device and or path are used as necessary to fill in the missing parts. It is essential that file$ and rel$ should be separate string variables.

Note that the filename extension is considered to start at, and include, the full stop. For example:

p$=PARSE$(“NEW”,“C:\Documents\*.MBM”,x%()) sets p$ to

C:\Documents\NEW.MBM and x%() to (1,1,3,14,17,0).


SPACE

bytes = SPACE

Return the number of free bytes on the device on which the current (open) data file is held.

For example:

PROC stock:
  OPEN C:\stock ,A,a$,b%
  WHILE 1
    PRINT Item name: ;
    INPUT A.a$
    PRINT Number: ;
    INPUT A.b%
    IF RECSIZE SPACE
      PRINT Disk full
      CLOSE
      BREAK
    ELSE
      APPEND
    ENDIF
  ENDWH
ENDP


Directory management

MKDIR

Create directory

RMDIR

Remove directory

SETPATH

Set current directory

EXIST

See General file management above


MKDIR

MKDIR dir$

Create a new directory.

For example, MKDIR C:\MINE\TEMP creates the directory c:\mine\temp, also creating c:\mine if it does not already exist.


RMDIR

RMDIR dir$

Remove the directory specified by dir$.

If the directory is not empty, it is not removed and an error is raised.


SETPATH

SETPATH path$

Set the current directory for file access.

For example:

SETPATH C:\docs\

The LOADM command continues to use the directory of the initial module, but all other file access will be to the new directory.

Note:

Remember the final backslash on the directory name.


Database files

CREATE

Create a new data file

 

Open a data file

OPEN

to read or write data

OPENR

read only

USE

Use a different data file that has already been opened

APPEND

Make a new record

UPDATE

Change a record

 

Search for records containing a certain string

FIND

simple search

FINDFIELD

controlled search

ERASE

Erase a record

 

Move to a different record in a file

FIRST

first record

LAST

last record

NEXT

next record

BACK

previous record

POSITION

a specific record

COUNT

Count the records

CLOSE

Close a data file

EOF

Detects the end of file has been reached

POS

Get current record number

DELETE

Delete a table from a data file

INSERT

Insert a new blank record into a database.

MODIFY

Modify the current record without moving it.

PUT

Makes the database changes permanent.

CANCEL

Discards database changes made

BOOKMARK

Puts a bookmark at the current record

GOTOMARK

Make bookmarked record current

KILLMARK

Remove a bookmark from a record

BEGINTRANS

Begins a transaction on the current database

COMMITTRANS

Commits the database transactions

INTRANS

Finds out if the current view is in a transaction

ROLLBACK

Cancels transaction(s) on the current view

COMPACT

Compacts the database file

Notes:

For general file operations (I/O) on text or binary type files, see the later section on ‘I/O operations on files and devices’.

INSERT, PUT and CANCEL should be used in preference to APPEND and UPDATE, although APPEND and UPDATE are still supported.

Additionally, OPL has a database OPX that provides considerably more database functionality.


CREATE

CREATE tableSpec$,ID,f1,f2,...

Creates a table in a database. The database is also created if necessary. Immediately after calling CREATE, the file and view (or table) is open and ready for access.

tableSpec$ contains the database filename and optionally a table name and the field names to be created within that table. For example:

CREATE clients FIELDS name(40), tel TO phone , D, n$, t$

The filename is clients. The table to be created within the file is phone. The commaseparated list, between the keywords FIELDS and TO, specifies the field names whose types are specified by the field handles (i.e. n$, t$). The name field has a length of 40 bytes, as specified within the brackets that follow it. The tel field has the default length of 255 bytes. This mechanism is necessary for creating some indexes.

OPL16 compatibility

As in OPL16, the table specification may contain just the filename. In this case the table name will default to Table1 and the field names will be derived from the handles: “$” replaced by “s”, “%” by “i”, and “ ” by “a”. E.g. n$ becomes ns. Knowing this allow views to be opened on tables (called Table1) that were created with the OPL16 method.  However, it would be better to create the fields with proper names in the first place.

For example:

CREATE clients ,A,n$,t%,d

is a short version of

CREATE clients FIELDS ns,ti,da TO Table1 ,A,n$,t%,d

both creating Table1. The database clients is also created if it does not exist already.


OPEN

OPEN query$,ID,field1,field2...

Opens an existing table (or a ‘view’ of a table) from an existing database, giving it the logical view name ID and handles for the fields field1, field2..., etc. ID can be any letter in the range A to Z (i.e. up to 26 files open concurrently). query$ specifies the database file, the required table and fields to be selected.

For example:

OPEN clients SELECT name, tel FROM phone ,D,n$,t$

The database name here is clients and the table name is phone. The field names are enclosed by the keywords SELECT and FROM and their types should correspond with the list of handles (i.e. n$ indicates that the name field is a string).  Replacing the list of field names with * selects all the fields from the table.

query$ is also used to specify an ordered view and if a suitable index has been created, then it will be used. For example:

OPEN “people SELECT name,number FROM phoneBook ORDER BY name ASC, number DESC”,G,n$,num%

would open a view with name fields in ascending alphabetical order and if any names were the same then the number field would be used to order these records in descending numerical order.

OPL16 compatibility

As in OPL16, query$ may contain just the filename. In this case a table with the default name Table1 would be opened if it exists. The field names would then be unimportant, as access will be given to as many fields as there are supplied handles. The type indicators on the field handles must match the types of the fields.


OPENR

OPENR query$,ID,field1,field2..

This command works exactly like OPEN except that the opened file is read-only; OPL may not APPEND, UPDATE or PUT the records it contains.

Using OPENR, however, means that two or more separate programs, running at the same time, can share the same file.


USE

USE ID

Selects the data file with the ID A - Z.

The file must previously have been opened with OPEN, OPENR or CREATE and not yet be closed. All of the record handling commands (such as POSITION, UPDATE, and GOTOMARK, INSERT, MODIFY, CANCEL, and PUT) then operate on this file.


APPEND

APPEND

Add a new record to the end of the current data file (without affecting the current record).

The record added is made from the current values of the field variables A.field1$, A.field2$, and so on, of the current data file. If a field has not been assigned a value:

For example:

PROC add:
  OPEN M:\add ,A,f1$,f2$,f3$
  PRINT ADD NEW RECORD
  PRINT Enter name: ,
  INPUT A.f1$
  PRINT Enter street: ,
  INPUT A.f2$
  PRINT Enter town: ,
  INPUT A.f3$
  APPEND
  CLOSE
ENDP

To overwrite the current record with new field values, use UPDATE.

Note:

The database keywords INSERT and PUT should be used in preference to APPEND.


UPDATE

UPDATE

Erases the current record in the current data file and saves the current field values as a new record at the end of the file. This record, now the last in the file, remains the current record.

For example:

A.count=129
A.name$= Brown
UPDATE

Use APPEND to save the current field values as a new record.

Note:

The database keywords INSERT and PUT should be used in preference to UPDATE. Using UPDATE may produce a lot of erased records. COMPACT should be used to remove them, or alternatively use SETFLAGS to set auto-compaction on.


FIND

record% = FIND(string$)

Search the current data file for a record in which any string field matches string$. The search starts from the current record, so use NEXT to progress to subsequent records. FIND makes the next record containing string$ the current record and returns the number of the record found, (or zero if not found). The search is case-independent.

The following wild cards may be included:

? matches any single character

* matches any group of characters.

So to find a record with a field containing both Dr and either BROWN or BRAUN, use:

F% = FIND( *DR*BR??N* )

FIND( BROWN ) will find only those records with a field consisting solely of the string BROWN.

FIND may only be used to search string fields.

Problems with FIND

In early versions of OPL (Series 5) FIND may cause a 'User error 23' if used on a database with more than 16 fields.

Workaround

Use FINDFIELD instead which does not seem to suffer from this problem.


FINDFIELD

record% = FINDFIELD(string$,start%,no%,flags%)

Find a string in specified fields of a data file, make the record with this string the current record, and return the number of this record or zero if not found.  The string to look for is string$, as for FIND.

The number of the string field to start looking in is start% (1 for the first string field).  The number of string fields to search in is no%, (starting from the string field specified by the start%). If you want to search in all fields, use start%=1 and for no% use the number of fields you used in the OPEN/CREATE command.

The type of search is defined by the code in flags%, which adds together two values:

0

for a case independent match, where capitals and lower-case letters match

16

for a case dependent match.

0

to search backwards from the current record.

1

to search forwards from the current record.

2

to search backwards from the end of the file.

3

to search forwards from the start of the file.

For example, if a file is opened with:

OPEN fred ,a,i1%,s1$,i2%,i3%,s2$,s3$

Then the command:

FINDFIELD( x ,1,2,1)

tries to find the string x in the two fields s1$ and s2$.


ERASE

ERASE

Erase the current record in the current file.

The next record is then current. If the erased record was the last record in a file, then following this command all fields in the current record will be 0 or null strings, and EOF will return true.


FIRST

FIRST

Position to the first record in the current data file.


LAST

LAST

Positions to the last record in a data file.


NEXT

NEXT

Position to the next record in the current data file, and make it current. If NEXT is used after the end of a file has been reached, no error is reported but the current record is null and the EOF function returns true.


BACK

BACK

Make the previous record in the current data file the current record. If the current record is the first record in the file, then the current record does not change.


POSITION

POSITION record%

Makes record number record% the current record in the current data file. If record% is greater than the number of records in the file then the EOF function will return true.  Makes record number record% the current record in the current view.  By using bookmarks and editing the same table via different views, positional accuracy can be lost and POSITION x% could access the wrong record.

Accuracy can be restored by using FIRST or LAST on the current view. POS and POSITION still exist mainly for reasons of OPL16 compatibility and it is better to use bookmarks instead.

See also BOOKMARK, GOTOMARK, KILLMARK.


COUNT

reccnt% = COUNT

Return the number of records in the current data file. This number will be 0 if the file is empty.

Trying to count the number of records in a view while updating the view will raise an ‘Incompatible update mode’ error (This will occur between assignment and APPEND/UPDATE or between MODIFY/INSERT and PUT).


CLOSE

Close the current view on a database. If there are no other views open on the database then the database itself will be closed.

If some records have been deleted using ERASE, CLOSE recovers the memory taken up by the erased records, (provided that the file is held either in the internal memory drive C: or on a S5 Compact Flash disk).

See also SETFLAGS for details of how to set auto-compaction on closing files.


EOF

end% = EOF

Find out whether the end of a file has been reached. Returns -1 (true) if the end of the file has been reached, or 0 (false) if it hasn't.

When reading records from a file, you should test whether there are still records left to read, otherwise you may get an error.

For example:

PROC eoftest:
  OPEN myfile ,A,a$,b%
  DO
    PRINT A.a$
    PRINT A.b%
    NEXT
    PAUSE -40
  UNTIL EOF
  PRINT The last record
  GET
  RETURN
ENDP


POS

record% = POS

Returns the number of the current record in the current view. It is better to use bookmarks instead of POS.

The number of the current record may be greater than or equal to 65535 and hence values may need to be truncated to fit into p%, giving inaccurate results. It is better to use bookmarks when dealing with a large number of records. Note, however, that the value returned by POS can become inaccurate if used in conjunction with bookmarks and multiple views on a table. The accuracy can be restored by using FIRST or LAST on the current view.

See also BOOKMARK, GOTOMARK, KILLMARK.


DELETE

DELETE dbase$,table$

This deletes the table, table$, from the database, dbase$. All views of the database, and hence the database itself, must be closed.


INSERT

INSERT

Inserts a new, blank record into the current view of a database. The fields can then be assigned to before using PUT or CANCEL.


MODIFY

MODIFY

Allows the current record of a view to be modified without moving the record. The fields can then be assigned to before using PUT or CANCEL.


PUT

PUT

Marks the end of a database’s INSERT or MODIFY phase and makes the changes permanent.

See INSERT, MODIFY, CANCEL.


CANCEL

CANCEL

Marks the end of a database’s INSERT or MODIFY phase and discards the changes made during that phase.


BOOKMARK

b%=BOOKMARK

Puts a bookmark at the current record of the current database view. The value returned can be used in GOTOMARK to make the record current again. Use KILLMARK to delete the bookmark.


GOTOMARK

GOTOMARK b%

Makes the record with bookmark b%, as returned by BOOKMARK, the current record. b% must be a bookmark in the current view.


KILLMARK

KILLMARK b%

Removes the bookmark b%, which has previously been returned by BOOKMARK, from the current view of a database.

See BOOKMARK, GOTOMARK.


BEGINTRANS

BEGINTRANS

Begins a transaction on the current database; allow changes to a database to be committed in stages. Once a transaction has been started on a view (or table) then all database keywords will function as usual, but the changes to that view will not be made until COMMITTRANS is used.

See also COMMITTRANS, ROLLBACK, INTRANS.


COMMITTRANS

COMMITTRANS

Commits the database transactions on the current view.

See also BEGINTRANS, ROLLBACK, INTRANS.


INTRANS

i =INTRANS

Finds out whether the current view is in a transaction. Returns -1 if it is in a transaction or 0 if it is not.

See also BEGINTRANS.


ROLLBACK

ROLLBACK

Cancels the current transaction on the current view. Changes made to the database with respect to this particular view since BEGINTRANS was called will be discarded. 

See also BEGINTRANS, COMMITTRANS.


COMPACT

COMPACT file$

Compacts the database file$, rewriting the file in place. All views on the database and the hence the file itself should be closed before calling this command. This should not be done too often since it uses considerable processor power.  Compaction can also be done automatically on closing a file by setting the appropriate flag using SETFLAGS.


OPL program modules

LOADM

Load an OPL module so you can use the procedures in it

UNLOADM

Remove a module from memory


LOADM

LOADM module$

Load a translated OPL module file so that procedures in that module can be called. The module$ argument is a string containing the name of the OPO file.

Until a module has been loaded with LOADM, calling a procedure in that module will give an error.

LOADM uses the folder of the top-level module. It is not affected by the SETPATH command. Once LOADM has been called, procedures loaded stay in memory until the module is unloaded.

Notes:

Up to eight modules can be in memory at any one time; that includes the main program module. An error will occur on trying to LOADM a ninth module. Hence, in addition to the main program module, you may use LOADM seven times before having to use UNLOADM to remove a module from memory in order to load another one.

LOADM loads an index table containing the names and file addresses of the procedures; it does not load the whole module. The file is then left open. Each procedure is loaded only when it is called.

When a procedure is called, OPL searches the module indexes for the procedure name in the order that modules were LOADMed.


UNLOADM

UNLOADM module$

Remove from memory the OPL module module$, previously loaded with LOADM. The UNLOADM command also removes all procedures in the module from the cache. The module$ argument is a string containing the name of the translated module.

Once LOADM has been called, procedures loaded stay in memory until the module is unloaded. The procedures in an unloaded module cannot then be called by another procedure.

Note:

It is considered bad practice to unload a module containing procedures that are still running - e.g. for a procedure to unload its own module.


Memory management

 

Declare variables

GLOBAL

global

LOCAL

local

CONST

Declare a constant with global scope

DECLARE EXTERNAL

Allow detection of undefined variables or procedures

EXTERNAL

Declares variables or procedures as external

ALLOC

Allocate a heap cell

FREEALLOC

Free an allocated heap cell

REALLOC

Change the size of an allocated a heap cell

ADJUSTALLOC

Insert or delete a section of an allocated heap cell

LENALLOC

Get the length of an allocated heap cell

ADDR

Address of a variable in memory

BYREF

Pass a variable to an OPX by reference

UADD

Addition to a pointer - add an integer value

USUB

Subtraction from a pointer - subtract an integer value

POKE commands

Store a value in a specific place in memory

PEEK commands

Find out the value stored at a certain place in memory


Variable declaration

GLOBAL

GLOBAL variables

Declare variables to be used in the current procedure, in any procedures called by the current procedure, or procedures called by those procedures. In contrast, LOCAL declaration sets up variables that can only be used in the current procedure.

The variables may be of 4 types, depending on the symbol their name ends with:

Array variables have a number immediately following them in brackets which specifies the number of elements in the array. Array variables may of any type described above, for example: GLOBAL x(6),y%(5),f$(5,12),z (3)

When declaring string arrays, two numbers must be supplied, enclosed in brackets. The first declares the number of elements, the second declares the maximum length of each element. For example surname$(5,8) declares five elements, each up to 8 characters long.

Variable names may be any combination of up to 32 numbers, alphabetic letters and the underscore character. They must start with a letter or an underscore. The length includes the %, or $ sign, but not the () in string and array variables.  The case (upper or lower) of characters in variable names is ignored.  More than one GLOBAL or LOCAL statement may be used, but they must be on separate lines, after the procedure name and before any executable code.


LOCAL

LOCAL variables

Declare variables that can be referenced only in the current procedure.  Any procedure may create a variable with the same name as one declared elsewhere by means of LOCAL. Use GLOBAL to declare variables that may be referenced in all called procedures.

The naming and types of LOCAL variables are as for GLOBAL variables above.


CONST

CONST KConstantName=value

Declares constants that are treated as literal values, and are not stored as data. CONST declarations must be made outside any procedure, usually at the beginning of the module.

KConstantName uses the normal type-specifiers (%, , $ or non for floating-point values) as for variables. CONST values have global scope, and are not overridden by local or global variables with the same name: in fact the translator will not allow the declaration of a local or global variable with the same name. By convention, all constants are usually named with a leading K to distinguish them from variables.

Note:

It is not possible to define constants with values -32768 (for integers) and -214748648 (for long integers) in decimal notation, but hexadecimal notation may be used instead (i.e. values of $8000 and 80000000 respectively).

See INCLUDE, EXTERNAL.


DECLARE EXTERNAL

DECLARE EXTERNAL

Causes the translator to report an error if any variables or procedures are used before they are declared. It should be used at the beginning of the module to which it applies, before the first procedure. It is useful for detecting ‘Undefined externals’ errors at translate-time rather than at runtime.

For example, without ‘DECLARE EXTERNAL’, the following example code would raise an error, “Undefined externals, i ” at run-time. Including the declaration as shown ensures the error is detected at translate-time.

DECLARE EXTERNAL
PROC main:
LOCAL i%
  i%=10
  PRINT i REM i used by mistake instead of i%
  GET
ENDP

If DECLARE EXTERNAL is used, all subsequent variables and procedures used in the module will have to be declared using EXTERNAL.

See EXTERNAL.


EXTERNAL

EXTERNAL variable REM must be used inside each procedure body
EXTERNAL prototype REM must be used outside of any procedure body

Required if DECLARE EXTERNAL is specified in the module.

The first version above declares a variable as external. For variables you must use EXTERNAL inside the body of each procedure that uses that variable, in similar way to the use of LOCAL and GLOBAL statements. For example:

DECLARE EXTERNAL
EXTERNAL myProc:
PROC main:
GLOBAL var%
  ...
  myProc:
  PRINT var%
ENDP

PROC myProc:
EXTERNAL var%
  var%=1
ENDP

The second version above declares the prototype of a procedure (prototype includes the final : and the argument list). The procedure may then be referred to before it is defined.  This allows the procedures parameters to be type-checked at translate-time rather than at runtime, and also provides the necessary information for the translator to coerce (automatically convert) numeric argument types.

A header file should be ‘included’ that declares prototypes of all the procedures. The header file is ‘included’ at the beginning of the module that defines the declared procedures, it is also be ‘included’ in any other modules that call the procedures.  DECLARE EXTERNAL is used at the beginning of modules that ‘include’ the header file so that the translator can ensure that the procedures are called with correct parameter types or types which can be coerced.

For example:

DECLARE EXTERNAL
EXTERNAL myProc%:(i%,l )
REM or INCLUDE “myproc.oph” that defines all your procedures
PROC test:
LOCAL i%,j%,s$(10)
  REM j% is coerced to a long integer as specified by the prototype.
  myProc%:(i%,j%)
  REM translator ‘Type mismatch’ error:
  REM string can’t be coerced to numeric type
  myProc%:(i%,s$)
  REM wrong argument count gives translator error
  myProc%:(i%)
ENDP
PROC myProc%:(i%,l )
  REM Translator checks consistency with prototype above
  ...
ENDP

See also DECLARE EXTERNAL.


Memory, dynamic allocation

ALLOC

pcell = ALLOC(size )

Allocates a cell on the heap of the specified size in bytes (size ). A pointer to the cell is returned or zero if there is not enough memory. Note that the new cell is not initialised.

Cells are allocated lengths that are the smallest multiple of four greater than the size requested. An error will be raised if the cell address argument is not in the range known by the heap.


FREEALLOC

FREEALLOC pcell

Free a previously allocated heap cell at pcell .

See also SETFLAGS if you require the 64K limit to be enforced. If the flag is set to restrict the limit, pcell is guaranteed to fit into a short integer.


REALLOC

pcelln = REALLOC(pcell ,size )

Change the size of a previously allocated cell at pcell to size , returning the new cell address or zero if there is not enough memory. If out of memory, the old cell at pcell is left as it was. If the size of pcell is being decreased, pcell and pcelln will be the same.  Cells are allocated lengths that are the smallest multiple of four greater than the size requested. An error will be raised if the cell address argument is not in the range known by the heap.


ADJUSTALLOC

pcelln = ADJUSTALLOC(pcell ,offset ,amount )

Open or close a gap in a memory cell.

The gap is at offset offset within the allocated cell pcell . The offset is zero for the first byte in the cell. The gap is opened if the amount (amount ) is positive, and closed if it is negative. The function returns the new cell address in pcelln , or zero if out of memory.

Cells are allocated lengths that are the smallest multiple of four greater than the size requested. An error will be raised if the cell address argument is not in the range known by the heap.


LENALLOC

lencell = LENALLOC(pcell )

Return the length of the previously allocated heap cell at pcell .  Cells are allocated lengths that are the smallest multiple of four greater than the size requested. An error will be raised if the cell address argument is not in the range known by the heap.


Memory, addresses pointer arithmetic

Note:

UADD and USUB should not be used for pointer arithmetic in OPL unless SETFLAGS has been used to enforce the 64K memory limit. Long integer arithmetic should be used for pointer arithmetic.


ADDR

pvar = ADDR(variable)

Return the address at which the variable is stored in memory.

The values of different types of variables are stored in bytes starting at ADDR(variable).

See the PEEK functions for details.

The ADDR function may be used to find the address of the first element in an array, as in ADDR(x%()). It is also possible to find the address of a specific element of the array, for example ADDR(x%(2)).

This command is principally useful for passing variables to procedures that need to modify them. To pass a variable by reference rather than by value, you need to pass a pointer - ADDR returns a pointer to its argument.

In the case of strings, the address pointed to by pvar holds the length-byte prefix.

See SETFLAGS for enforcing the 64K limit.

See also UADD and USUB, and the PEEK functions.


BYREF

BYREF variable

BYREF, is used to indicate that variable will be passed by reference (typically to an OPX procedure) i.e. to pass the address of the variable to allow the called procedure to modify the variables contents.


UADD

i% = UADD(val1%,val2%)

Add val1% and val2%, as if both were unsigned integers with values from 0 to 65535.

Using this function prevents integer overflow for pointer arithmetic, e.g.:

UADD(ADDR(text$),1)

should be used instead of

ADDR(text$)+1

One argument would normally be a pointer and the other an offset expression.

See also USUB and ADDR.


USUB

i% = USUB(val1%, val2%)

Subtract val2% from val1%, as if both were unsigned integers with values from 0 to 65535.

Using this function prevents integer overflow for pointer arithmetic, e.g.:

USUB(ADDR(text$),1)

should be used instead of

ADDR(text$)-1

One argument would normally be a pointer and the other an offset expression.

See also UADD and ADDR.


Memory, reading and writing

The various POKE commands are able to store different data types into memory locations, usually into a memory location of a previously declared variable.

Note:

Casual use of the POKE commands can result in the loss of data in your machine.  The various PEEK commands are able to read different data types from memory locations, usually from the location of a previously declared variable. See the corresponding PEEK functions for more details of how the different variable types are stored in memory.

The ADDR function is used to find out the address of a particular variable in memory, it may also be used to find the address of the first element in an array, as in ADDR(x%()). It is additionally possible to find the address of a specific element of the array, for example ADDR(x%(2)).


Poke commands

POKEB

POKEB address ,intv%

Store the integer value intv% (less than 256) in the single byte at address .


POKEF

POKEF address ,floatv

Store the floating-point value floatv in bytes starting at address .


POKEL

POKEL address ,long

Store the long-integer long in bytes starting at address .


POKEW

POKEW address ,int%

Store the integer int% across two consecutive bytes, with the least significant byte in the lower address, that is address .


POKE$

POKE$ address ,string$

Store the string string$ in bytes starting at address .


Peek commands

PEEKB

intval% = PEEKB(address )

Return the integer value of the byte at address .


PEEKF

float = PEEKF(address )

Return the floating-point value at address .

Floating-point numbers are stored in IEEE format for doubles, across eight bytes. PEEKF automatically reads all eight bytes and returns the number as a floating-point value. For example, if var=1.3 then PEEKF(ADDR(var)) returns 1.3.


PEEKL

long = PEEKL(address )

Return the long integer value at address .

Long integers are stored in four bytes, the least significant first and the most significant last, for example:

$01 $00 $00 $00 = 1

$00 $00 $01 $00 = 65536


PEEKW

int% = PEEKW(address )

Return the integer at address .

Integers are stored in two bytes, the first of which is the least significant, so that:

$01 $00 = 1

$00 $01 = 256

The ADDR function returns the address of the first (least significant) byte.


PEEK$

string$ = PEEK$(address )

Return the string at address .

For example, if var$= ABC , then PEEK$(ADDR(var$)) would return the string ABC .  In ER5 strings are stored as one character per byte, with a leading byte containing the string length e.g. the length byte is 3 in the example below. Each letter is stored as its character code (that is, A is stored as 65, B as 66, and so on). Thus:

03 65 66 67

represents the string ABC .

In ER6 strings are stored as two characters per byte, with a leading byte containing the string length following by a zero byte. The representation of the string “ABC” in ER6 is therefore:

03 00 65 00 66 00 67 00.

The byte value prior to the length byte, i.e. 12 is the maximum declared size of the string.

For example in:

LOCAL var$(12)

Note:

ADDR(var$) returns the address of the length byte and USUB(ADDR(vars$),1) gives the address of the maximum string length.


Printing

LOPEN

Prepare a device or file to print to

LCLOSE

Close the print device or file opened with LOPEN

LPRINT

Print to an attached device or file


LOPEN

LOPEN port$
LOPEN file$

Open the port or file to which LPRINTs are to be sent.

No LPRINTs can be sent until a port or file has been LOPENed.

You can open any of these devices:

LOPEN C:\BAK\MEMO.TXT

Any existing file of the same name will be overwritten when you print to it.  Only one device may be open at any one time. Use LCLOSE to close the device (if left open it is closed automatically when a program finishes running).

Note:

All the I/O calls, e.g. IOW() can be passed a handle of -1 to use the LOPENed device, for example:

IOW(-1,FREAD,...)

Note (ER6):

On ER6 the variant of LOPEN that takes the name of a text file will now create a Unicode text file by default and not an ASCII one as with ER5.

Unicode text files on Symbian OS conform to the Unicode standard of having the hex bytes 0xFEFF (or 0xFFEF depending on the endianness) written at the start of them. LOPEN now automatically writes these bytes for you.

The end-of-line delimiter for Unicode text files on Symbian OS is still the same as ASCII, i.e. CR LF . There are CONSTs provided for these in CONST.OPH (see Appendix C).

Note, however, that you can force LOPEN to output ASCII files. To do this, specify the new SETFLAGS value of KAlwaysWriteAsciiTextFiles

See also SETFLAGS.


LCLOSE

LCLOSE

Close the device or file opened with LOPEN. The device or file is also closed automatically when a program ends.


LPRINT

LPRINT list

Prints a list of items, in the same way as PRINT, except that the data is sent to the file or device most recently opened with LOPEN.

The list of items may be quoted strings, variables, or the evaluated results of expressions.  The punctuation of the LPRINT statement (commas, semi-colons and new lines) determines the layout of the printed text, in the same way as PRINT statements.  An error is raised if no device has been opened with LOPEN.


Numeric functions


Trigonometric functions

COS, SIN, TAN,

Cosine, Sine, Tangent,

ACOS, ASIN, ATAN

Arccosine, Arcsine, Arctangent

Note: All trig function arguments are in radians

 

Convert angles

RAD

from degrees to radians

DEG

from radians to degrees


COS

cosine = COS(radians)

Return the cosine of radians, an angle in radians.


SIN

sine = SIN(radians)

Return the sine of radians, an angle expressed in radians.


TAN

tangent = TAN(radians)

Return the tangent of radians, an angle expressed in radians.


ACOS

radians = ACOS(x)

Return the arc cosine, or inverse cosine (COS-1) of x.

The value of x must be in the range -1 to +1. The number returned is an angle in radians.


ASIN

radians = ASIN(x)

Return the arc sine, or inverse sine (SIN-1) of x.

The value of x must be in the range -1 to +1. The number returned is an angle in radians.


ATAN

radians = ATAN(x)

Return the arc tangent, or inverse tangent (TAN-1) of x.

The number returned is an angle in radians.


RAD

radians = RAD(degrees)

Convert from degrees to radians.

All the trigonometric functions assume angles are specified in radians, but it may be more convenient to enter angles in degrees and then convert with RAD. For example:

PROC xcosine:
LOCAL angle
  PRINT Enter angle in degrees: ;
  INPUT angle
  PRINT COS of ,angle, degrees is ,
  angle=RAD(angle)
  PRINT COS(angle)
  GET
ENDP

The formula used is:

(PI*x)/180.

To convert from radians to degrees use DEG.


DEG

degrees = DEG(radians)

Converts from radians to degrees.

Returns radians, an angle in radians, as a number of degrees, degrees. The formula used is:

radians*180/PI

All the trigonometric functions (SIN, COS, etc.) work in radians, not degrees. You can use DEG to convert an angle returned by a trigonometric function back to degrees. For example:

PROC xarctan:
LOCAL arg,angle
  PRINT Enter argument: ;
  INPUT arg
  PRINT ARCTAN of ,arg, is
  angle=ATAN(arg)
  PRINT angle, radians
  PRINT DEG(angle), degrees
  GET
ENDP

To convert from degrees to radians, use RAD.


General numeric functions

EXP

Raise the number e to a power

 

Logarithms

LN

natural (base e)

LOG

decimal (base 10)

PI

Pi as a constant (π)

SQR

Square root

 

Use random numbers

RND

generate a random floating point number (0 ≤ x 1)

RANDOMIZE

set a seed for random number generation


EXP

e = EXP(x)

Returns ex - that is, the value of the arithmetic constant e (2.71828...) raised to the power of x.


LN

a = LN(x)

Return the natural (base e) logarithm of x. Use LOG to return the base 10 logarithm of a number.


LOG

a = LOG(x)

Return the base 10 logarithm of x. Use LN to find the base e (natural) logarithm.


PI

p = PI

Return the value of π (3.14159265358979... ).


SQR

s = SQR(x)

Returns the square root of x, which must be greater than or equal to zero.


RND

random = RND

Return a random floating-point number in the range 0 (inclusive) to 1 (exclusive).  To produce random numbers between 1 and n - e.g. between 1 and 6 for a dice - use the following statement: f%=1+INT(RND*n)

The RND function produces a different random number every time it is called within a program. A fixed sequence can be generated by using RANDOMIZE. Alternatively, RANDOMIZE could be supplied with an argument generated from, for example, MINUTE and SECOND to seed the sequence differently each time.

For example:

PROC rndvals:
LOCAL i%
  PRINT Random test values are:
  DO
    PRINT RND
    i%=i%+1
    GET
  UNTIL i%=10
ENDP

Note:

In very early versions of OPL (Series 5) the first call to RND produced an unreliable value. Workaround – call the RANDOMIZE function to set the random seed (usually during program initialisation) and immediately follow it with a call to RND to dump the first value. For example:

RANDOMIZE second+1+minute+1+hour+1
RND


RANDOMIZE

RANDOMIZE seed

Set the 'seed' (start-value) for RND to seed .

Successive calls of the RND function produce a sequence of pseudo-random numbers. If RANDOMIZE is used to set the seed back to what it was at the beginning of the sequence, the same sequence will be repeated.

To seed the sequence differently each time, you could begin by using RANDOMIZE with an argument generated from MINUTE and SECOND. In a game program you would typically use RANDOMIZE in this way, but only once, e.g. when the game first initialises.

The same set of 'random' values might be needed to test new versions of a procedure. To do this, precede the set of RND statements with the statement RANDOMIZE value . Then to repeat the sequence, use RANDOMIZE value again, using the same value.  For example:

PROC seq:
LOCAL g$(1)
  WHILE 1
    PRINT S: set seed to 1
    PRINT Q: quit
    PRINT other key: continue
    g$=UPPER$(GET$)
    IF g$= Q
      BREAK
    ELSEIF g$= S
      PRINT Setting seed to 1
      RANDOMIZE 1
      PRINT First random no:
    ELSE
      PRINT Next random no:
    ENDIF
    PRINT RND
  ENDWH
ENDP

See also RND.


Statistical numeric functions

MAX

Find the greatest value in the list

MIN

Find the smallest value in the list

MEAN

Average the list

SUM

Add up the list

STD

Find the standard deviation

VAR

Find the variance


MAX

m = MAX(list_of_numbers)
m = MAX(array(),count%)

Return the greatest of a list of numeric items.

The list can be either:

When operating on an array, the first argument must be the array name followed by (). The second argument count%, separated from the first by a comma, is the number of array elements you wish to operate on - for example m=MAX(arr(),3) would return the value of the largest of elements arr(1), arr(2) and arr(3).


MIN

m = MIN(list_of_numbers)
m = MIN(array(),count%)

Return the smallest of a list of numeric items.

The list can be either:

When operating on an array, the first argument must be the array name followed by (). The second argument count%, separated from the first by a comma, is the number of array elements you wish to operate on - for example m=MIN(arr(),3) would return the minimum of elements arr(1), arr(2) and arr(3).


MEAN

m = MEAN(list_of_numbers)
m = MEAN(array(),count%)

Return the arithmetic mean (average) of a list of numeric items.

The list can be either:

When operating on an array, the first argument must be the array name followed by (). The second argument count%, separated from the first by a comma, is the number of array elements you wish to operate on - for example m=MEAN(arr(),3) would return the average of elements arr(1), arr(2) and arr(3).

This example displays 15.0:

arr(1) = 10
arr(2) = 15
arr(3) = 20
PRINT MEAN(arr(),3)


SUM

s = SUM(list_of_numbers)
s = SUM(array(),count%)

Return the sum of a list of numeric items.

The list can be either:

When operating on an array, the first argument must be the array name followed by (). The second argument count%, separated from the first by a comma, is the number of array elements you wish to operate on - for example m=SUM(arr(),3) would return the sum of elements arr(1), arr(2) and arr(3).


STD

s = STD(list_of_numbers)
s = STD(array(),count%)

Return the sample standard deviation of a list of numeric items. The list can be either:

When operating on an array, the first argument must be the array name followed by (). The second argument count%, separated from the first by a comma, is the number of array elements you wish to operate on - for example m=STD(arr(),3) would return the standard deviation of elements arr(1), arr(2) and arr(3).

This function gives the sample standard deviation using the formula:

SQR(∑((xi-(∑xi/count%))2/(count%-1))

where count% is the number of elements in the list. To convert to population standard deviation, multiply the result by SQR((count%-1)/count%).


VAR

v = VAR(list)
v = VAR(array(),count%)

Return the sample variance of a list of numeric items. The list can be either:

When operating on an array, the first argument must be the array name followed by (). The second argument count%, separated from the first by a comma, is the number of array elements you wish to operate on - for example m=VAR(arr(),3) would return the variance of elements arr(1), arr(2) and arr(3).

This function gives the sample variance, using the formula:

∑(xi-(∑xi/count%))2/(count%-1)

where n is the number of elements in the list.

To convert to population variance, multiply the result by (count%-1)/count%.


Numeric conversion

 

Convert negative number to positive

ABS

floating point or integer, returning a floating point

IABS

integer or long integer, returning a long integer

 

Take floating point number, removing any fractional part

INT

returning a long integer

INTF

returning a floating point number

FLT

Convert an integer into floating-point

HEX$

Convert an integer into hexadecimal string

 

Convert a number into a string (with controlled justification)

FIX$

fixed decimal places/maximum length

GEN$

fixed maximum length

NUM$

as a rounded integer, fixed maximum length

SCI$

scientific format, fixed decimal place /maximum length


ABS

absval = ABS(float)

Return the absolute value of a floating-point expression. That is, negative numbers are converted to positive.

For example, ABS(-10.099) returns 10.099.

If x is an integer, no error is returned, but the result will is converted to floating point. For example ABS(-6) returns 6.0.

Use IABS to return the absolute value as a long integer.


IABS

i = IABS(x )

Return the absolute value of an integer or long integer expression x . That is, negative numbers are converted to positive.

For example IABS(-10) returns 10.

See also ABS, which returns the absolute value as a floating-point value.


INT

integer = INT(x)

Returns the integer (in other words the whole number part) of the floating-point expression x. The number is returned as a long integer.

Positive numbers are rounded down, and negative numbers are rounded up. This may be undesirable - for example INT(-5.9) returns -5 and INT(2.9) returns 2. If you want to round a number to the nearest integer, add 0.5 to it (or subtract 0.5 if it is negative) before you use INT.

See also INTF.


INTF

float = INTF(x)

Used in the same way as the INT function, but the value returned is a floating-point number. This may be needed in cases where a calculation is required to have an integer result, but the value could exceed normal range for integers.  For example, INTF(1234567890123.4) returns 1234567890123.0

See also INT.


FLT

float = FLT(x )

Convert an integer expression (either integer or long integer) into a floating-point number.

For example:

PROC gamma:(v)
LOCAL c
  c = 3E8
  RETURN 1/SQR(1-(v*v)/(c*c))
ENDP

This procedure could be called as:

gamma:(FLT(a%))

to pass it the value of an integer variable without having first to assign the integer value to a floating point variable.

See also INT and INTF.


HEX$

h$ = HEX$(x )

Return a string containing the hexadecimal (base 16) representation of integer or long integer x .

For example HEX$(255) returns the string FF .

Notes:

To enter integer hexadecimal constants (16 bit) put a $ in front of them. For example $FF is 255 in decimal. (Don't confuse this use of $ with string variable names).  To enter long integer hexadecimal constants (32 bit) put an in front of them. For example FFFFF is 1048575 in decimal, and 10000 is 65536. Counting in hexadecimal is as follows:

0 1 2 3 4 5 6 7 8 9 A B C D E F 10 ...

The hexadecimal digit A stands for decimal 10, B for decimal 11, C for decimal 12 ... up to F for decimal 15. After F comes 10, which is equivalent to decimal 16. To understand numbers greater than hexadecimal 10, again compare hexadecimals with decimals.  Conventional algebraic notation is used for the following examples - 102 means 10x10, 103 means 10x10x10 and so on.

253 in decimal is: (2x102)+(5x101)+(3x100) - that is:

(2x100)+(5x10)+(3x1) in other words: 200+50+3.

By analogy, 253 in hexadecimal is:

( 2x162)+( 5x161)+( 3x160)

= (2x256)+(5x16)+(3x1)

= 512+80+3

= 595 in decimal.

Similarly, A6B in hexadecimal is:

( Ax162)+( 6x161)+( Bx160)

= (10x256)+(6x16)+(11x1)

= 2560+96+11

= 2667 in decimal.

You may also find this table useful for converting between hex and decimal:

hex.

decimal

1

1 = 160

10

16 = 161

100

256 = 162

1000

4096 = 163

For example,

20F9 is (2x 1000)+(0x 100)+(15x 10)+9 which in decimal is

(2x4096)+(0x256)+(15x16)+9 = 8441.

All hexadecimal constants are either of type integer (if preceded by $) or of type long (if preceded by ). So, arithmetic operations involving hexadecimal numbers behave in the usual way. For example, 3/ 2 returns 1, 3/2.0 returns 1.5, 3/$2 returns 1.


FIX$

float$ = FIX$(number,places%,width%)

Return a string representation of a number, number, to places% decimal places. The string will be up to width% characters long.

For example

f$=FIX$(123.456,2,7)

returns the string 123.46 in f$.

If width% is negative the string is right-justified, for example:

FIX$(1,2,-6) returns 1.00 where there are two spaces to the left of the 1.

If width% is positive the string is left-justified, for example FIX$(1,2,6) returns 1.00 .  If the number x will not fit in the width specified by width%, then the string will contain asterisks, for example:

FIX$(256.99,2,4) returns **** .

See also GEN$, NUM$ and SCI$.


GEN$

number$ = GEN$(number,width%)

Return a string representation of a number, (number). The string will be up to length% characters long.

For example GEN$(123.456,7) returns 123.456 and GEN$(243,5) returns 243 .

Also:

See also FIX$, NUM$ and SCI$.


NUM$

n$ = NUM$(x,length%)

Return a string representation of the integer part of the floating-point number x, rounded to the nearest whole number.

The string will be length% characters wide:

See also FIX$, GEN$ and SCI$.


SCI$

s$ = SCI$(number,places%,length%)

Return a string representation of the floating point expression number in scientific format, to places% decimal places in a string length% characters long. If length% is negative then the string is right-justified.

For example:

SCI$(123456,2,8) returns 1.23E+05

SCI$(1,2,8) returns 1.00E+00

SCI$(1234567,2,-9) returns 1.23E+06

If the number does not fit in the width specified then the returned string contains asterisks.

SCI$(1234567,1,6) returns ******

See also FIX$, GEN$, and NUM$.


String handling

 

Get characters from a string

LEFT$

from the left

MID$

from the middle

RIGHT$

from the right

REPT$

Repeat a string

LOWER$

Convert a string to all lower case

UPPER$

Convert a string to all upper case

LEN

Return the length of a string

SIZE

Return the size in bytes of a string (ER6)

ASC

Return the character code of the first character of a string

LOC

Locate a string is within another string

 

Convert a string into a number

VAL

string contains no functions/operators

EVAL

string contains functions/operators

CHR$

Get the character with a certain character code


LEFT$

leftchr$ = LEFT$(string$,length%)

Return the leftmost length% characters from the string string$.  For example if filen$ has the value mydoc.txt , then b$=LEFT$(filen$,5) assigns mydoc to b$.

See also MID$ and RIGHT$.


MID$

m$ = MID$(string$,start_position%,length%)

Return a string comprising length% characters of string$, starting with the character at position start_position%.

E.g. MID$( mydoc.txt ,6,4) would return the string .txt .

See also LEFT$ and RIGHT$.


RIGHT$

r$ = RIGHT$(string$,length%)

Return the rightmost length% characters of string$.

For example:

PRINT Enter name/reference ,
INPUT c$
ref$=RIGHT$(c$,4)
name$=LEFT$(c$,LEN(c$)-4)

See also LEFT$ and MID$.


REPT$

r$ = REPT$(string$,repeats%)

Return a string comprising of repeats% repetitions of string$.

E.g. if string$= ex then r$=REPT$(string$,5) returns exexexexex .


LOWER$

l$ = LOWER$(string$)

Convert any upper case characters in the string string$ to lower-case and returns the completely lower-case string.

E.g. LOWER$( PRICE ) returns the string price .

Use UPPER$ to convert a string to upper case.


UPPER$

u$ = UPPER$(string$)

Converts any lower case characters in string$ to upper-case, and returns the completely upper-case string. For example UPPER$( price ) returns PRICE.

For example:

...
PRINT Y to continue
PRINT or N to stop.
g$=UPPER$(GET$)
IF g$= Y
  nextproc:
ELSEIF g$= N
  RETURN
ENDIF
...

Use LOWER$ to convert to lower case.


LEN

length% = LEN(string$)

Return the number of characters in string$.

E.g. if addr$ has the value 10 Downing Street then LEN(address$) returns 17.  This function could be used, for example, to check that a data file string field is not empty before displaying it:

IF LEN(A.client$)
  PRINT A.client$
ENDIF


SIZE, ER6

length% = SIZE(string$)

Return the size of string$ in bytes.

For all phones based on Symbian OS v6.0 and newer, Unicode character sets are now used. This is a 16-bit text character representation, which replaces the previous 8-bit ASCII character set.

As a result of this system-wide change, OPL no longer supports an 8-bit text character, and all string functions and commands now use 16-bit Unicode characters.

E.g. if addr$ has the value 10 Downing Street then LEN(address$) returns 17 and SIZE(address$) returns 34. 


ASC

chcode% = ASC(a$)

Return the character code of the first character of a$. If a$ is a null string ( ) ASC returns the value 0. For example, ASC( hello ) returns 104, the code for 'h'.  Alternatively, use a statement such as: A%=%char to find the code for char - e.g. %X for 'X'.


LOC

pos% = LOC(string$,search$)

Return an integer showing the position in string$ where search$ occurs.

Zero is returned if search$ doesn't occur in string$. The search is case insensitive.

For example:

LOC( STANDING , AND )

would return the value 3, because the sub-string AND starts at the third character of the string STANDING .


VAL

v = VAL(nstring$)

Return the floating-point number corresponding to a numeric string.  The string must be a valid number - that is, not 5.6.7 or 196f , nor expressions like 45.6*3.1 . But scientific notation, such as 1.3E10 , is valid.

For example: VAL( 470.0 ) returns 470.0.

See EVAL for evaluating expressions.


EVAL

float = EVAL(expr$)

Evaluate the mathematical string expression expr$ and return the floating-point result.  The expr$ argument may include any mathematical function or operator (e.g. sin(x)/(2**3)). Note that floating-point arithmetic is always performed.

For example:

DO
  AT 10,5 : print Calc:
  TRAP INPUT n$
  IF ERR
    BREAK
  ENDIF
  AT 10,7
  ONERR badExp
  PRINT Res= ;EVAL(n$)
  ONERR OFF
  CONTINUE
badExp::
  ONERR OFF
  PRINT Bad expression
UNTIL 0 REM Loop forever

Note:

EVAL runs in the “context” of the current procedure, so globals and externals can be used in expr$, procedures in loaded modules can be called and the current values of gX and gY, can be used etc. LOCAL variables cannot be used in expr$.

See also VAL.


CHR$

char$ = CHR$(chrcode%)

Return the character with character code chrcode%. This function may be used to display characters not easily available from the keyboard. For example, the instruction:

PRINT CHR$(150) REM displays: û

Similarly the instruction:

PRINT CHR$(174) REM displays: ®


Date and time

DATIM$

Get the current date and time as a string

SECOND,> MINUTE, HOUR

Get the current time components

DAY, MONTH, YEAR

Get the current date components

DAYS

Get the number of days between two dates

DOW

Return what day of the week,

WEEK

or what week number, a certain date falls in

MONTH$

Return the month name for a month number

DAYNAME$

Return the day name for a day of the week number

DATETOSECS

Convert between time formats

SECSTODATE

 

DAYSTODATE

Convert number of days since 1/1/1900 to date string

Note:

Date OPX provides a large set of procedures for manipulating dates and for accurate timing.


DATIM$

datetim$ = DATIM$

Return the current date and time from the system clock as a string.

For example:

Tue 26 May 1992 13:01:44

The string returned always has this format - 3 mixed case characters for the day, then a space, then 2 digits for the day of the month, and so on.

See also DAY, MONTH, YEAR, SECOND, MINUTE, HOUR, DOW, gCLOCK.


SECOND

secs% = SECOND

Return the current ‘seconds’ component of the time from the system clock (0 to 59).

E.g. at 6:00:33, SECOND returns 33.

See also DAY, MONTH, YEAR, MINUTE, HOUR, DOW, gCLOCK.


MINUTE

minutes% = MINUTE

Return the current minute number from the system clock (0 to 59).

E.g. at 8.54 am, MINUTE returns 54.

See also DAY, MONTH, YEAR, SECOND, HOUR, DOW and gCLOCK for drawing an on-screen clock.


HOUR

h% = HOUR

Return the number of the current hour from the system clock as an integer between 0 and 23.

For example, at 8.54 am HOUR returns 8.

See also DAY, DATETOSECS, SECSTODATE, MONTH, YEAR, SECOND, MINUTE, DOW, gCLOCK.


DAY

daymth% = DAY

Return the current day of the month (1 to 31) from the system clock. For example, on the 23rd April 1996 DAY returns 23.

See also MONTH, YEAR, SECOND, MINUTE, HOUR, DOW, gCLOCK.


MONTH

mthnum% = MONTH

Returns the current month from the system clock as an integer between 1 and 12. E.g. on 12th March 1990, MONTH returns 3.

OPL constant

value

Kjanuary%

1

Kfebruary%

2

Kmarch%

3

Kapril%

4

Kmay%

5

Kjune%

6

Kjuly%

7

Kaugust%

8

Kseptember%

9

Koctober%

10

Knovember%

11

Kdecember%

12

See also DAY, YEAR, SECOND, MINUTE, HOUR, DOW.


YEAR

yearnum% = YEAR

Return the current year as an integer between 1900 and 2155 from the system clock. For example, on 9th April 1996, y%=YEAR assigns 1996 to y%.

See also DAY, MONTH, SECOND, MINUTE, HOUR, DOW, gCLOCK.


DAYS

days = DAYS(day%,month%,year%)

Return the number of days since 01/01/1900. For example, to find out the number of days between two dates:

PROC deadline:
LOCAL a%,b%,c%,deadlin
LOCAL today ,togo%
  PRINT Day? (1-31)
  INPUT a%
  PRINT Month?
  PRINT (1-12)
  INPUT b%
  PRINT Year?(19??)
  INPUT c%
  deadlin =DAYS(a%,b%,1900+c%)
  today =DAYS(DAY,MONTH,YEAR)
  togo%=deadlin -today
  PRINT togo%, days to go
  GET
ENDP

See also dDATE, SECSTODATE.


DOW

daynum% = DOW(day%,month%,year%)

Returns the day of the week number, 1 for Monday to 7 for Sunday, - given the date.

The day% argument must be between 1 and 31, month% from 1 to 12 and year% from 1900 to 2155.

For example:

D% = DOW(26,5,1996)

returns 7, meaning Sunday.

OPL constant

value

KMonday%

1

KTuesday%

2

KWednesday%

3

KThursday%

4

KFriday%

5

KSaturday%

6

KSunday%

7

See also DAY, MONTH, YEAR, SECOND, MINUTE, HOUR, gCLOCK.


WEEK

weeknum% = WEEK(day%,month%,year%)

Return the week number in which the specified day falls, as an integer between 1 and 53.  The day% argument must be between 1 and 31, month% between 1 and 12, and year% between 1900 and 2155.

For example on the 9th February 1995, w%=WEEK(9,2,1995) returns 6 in w%.

Each week is taken to begin on the 'Start of week' day, as specified in the Time application.  On machines without a Time application, Monday is taken to be the start of the week by default. When a year begins on a different day, it counts as week 1 if there are four or more days before the next week starts, (i.e. the first Thursday of each year is in week 1).

See also DAY, MONTH, YEAR, DAYS, DATIM$.


MONTH$

mthname$ = MONTH$(mthnum%)

Convert mthnum%, a number from 1 to 12, to the month name, expressed as a three-letter mixed case string. For example

MONTH$(1) returns the string Jan .

See also MONTH, DATIM$.


DAYNAME$

day$ = DAYNAME$(daynum%)

Convert daynum%, a number from 1 to 7, to the day of the week, expressed as a three letter string. E.g. d$ = DAYNAME$(1) returns Mon .

For example:

PROC Birthday:
LOCAL d ,m ,y ,dWk%
  DO
    Dinit
    dTEXT , Date of birth ,2
    dTEXT , eg 23 12 1963 ,$202
    dLONG d , Day ,1,31
    dLONG m , Month ,1,12
    dLONG y , Year ,1900,2155
    IF DIALOG=0 :BREAK :ENDIF
    dWk%=DOW(d ,m ,y )
    CLS :PRINT DAYNAME$(dWk%),
    PRINT d ,m ,y
    dINIT
    dTEXT , Again? ,$202
    dBUTTONS No ,%N, Yes ,%Y
  UNTIL DIALOG %y
ENDP

See also DOW, DAY, DATIM$.


DATETOSECS

Secs = DATETOSECS(year%,month%,day%,hour%,minute%,second%)

Return the number of seconds since 00:00 on 1 January 1970 at the date/time specified.

Raises an error for dates before 1 January 1970.

The value returned is an unsigned integer. (Values up to +2,147,483,647, which is 03:14:07 on 19/1/2038, are returned as expected. Those from +2,147,483,648 upwards are returned as negative numbers starting from -2,147,483,648 and increasing towards 0.)

See also SECSTODATE, HOUR, MINUTE, SECOND, DAYS, dDATE.


SECSTODATE

SECSTODATE s ,var year%,var month%,var day%,var hour%,var minute%,var second%,var yearday%

Set the variables, (year%, month%, day%, hour%, minute%, second%), to the date and time corresponding to s . The s argument is expressed as the number of seconds since 00:00 on 1 January 1970.

The yearday% variable is set to the day in the year (1-366).

The s argument is an unsigned long integer. To use values greater than +2,147,483,647, subtract 4,294,967,296 from the value.

See also DATETOSECS, HOUR, MINUTE, SECOND, dDATE, DAYS.


DAYSTODATE

DAYSTODATE days ,year%,month%,day%

This converts days , the number of days since 1/1/1900, to the corresponding date, returning the day of the month to day%, the month to month% and the year to year%. This is useful for converting the value set by dDATE, which also gives days since 1/1/1900.


Sound

BEEP

Sound the buzzer


BEEP

BEEP duration%,pitch%

Sound the buzzer. The beep lasts for duration%/32 seconds.

For a one second long beep make duration% = 32. The maximum is 3840 (2 minutes).

The pitch (frequency) of the beep is 512/(pitch%+1) KHz. The command:

BEEP 5,300

gives a short, comfortably pitched, beep.

If time% is made negative, BEEP first checks whether the sound system is in use (perhaps by another OPL program) and returns if it is. Otherwise, BEEP waits until the sound system is free. The following example gives a scale from middle C:

PROC scale:
LOCAL freq
LOCAL n%
  REM n% is key relative to middle A
  n%=3 REM start at middle C
  WHILE n% 16
    freq=440*2**(n%/12.0)
    REM middle A = frequency 440Hz
    BEEP 8,512000/freq-1.0
    n%=n%+1
    IF n%=4 OR n%=6 OR n%=9 OR n%=11 OR n%=13
      n%=n%+1 REM 1 extra for semi-tone
    ENDIF
  ENDWH
ENDP

If the batteries are low, BEEP may not produce the desired effect, the buzzer will be used instead and it produces a higher pitched sound. Buzzer sounds are generated using extra circuitry, via the same speaker, but with less drain on the batteries.  Alternatively, sound the buzzer with this statement: PRINT CHR$(7). This produces a click.

Note (ER6):

Although the BEEP command still functions in OPL on ER6, its usage is deprecated in favour of the new MediaServerOPX OPX interface. BEEP is not as flexible as the new Symbian OS MediaServer and some frequency ranges produce very quiet beeps on target hardware.


Graphics


Window and bitmap manipulation

gCREATE

Create a window

gSETWIN

Change size and position of window

gORDER

Set order to show windows

gRANK

Get order in which a window is shown

gVISIBLE ON

Make window visible

gVISIBLE OFF

Make window invisible

 

Get screen position of a window

gORIGINX

gap between left of screen and left of window

gORIGINY

gap between top of screen and top of window

gCREATEBIT

Create a bitmap

gLOADBIT

Load a bitmap from file

gSAVEBIT

Save window/bitmap to bitmap file

gCLOSE

Close window/bitmap

gUSE

Set which window/bitmap to use

 

Control the use of grey / colour mode

DEFAULTWIN

in the default window

gGREY

in the current window


gCREATE

id% = gCREATE(xpos%,ypos%,width%,height%,vis%)
id% = gCREATE(xpos%,ypos%,width%,height%,vis%,flags%)

Create a window with specified screen position (xpos%,ypos%), and dimensions (width%, height%) and make it both current and foreground. Set the current graphics cursor position to 0,0, its top left corner. If vis% is 1, the window will be visible immediately; if 0, it will be invisible (see gVISIBLE).

Returns id% (2-64), the drawable ID, which identifies this window for other keywords (the default window is 1). Note that 63 windows may be open at any time and it is recommended that you use many small windows rather than a few large ones.

flags% specifies the graphics mode to use and shadowing on the window. By default the graphics mode is 2-colour and there is no shadow. The least significant 4 bits of flags% gives the colour-mode as before 0 (2 colour-mode), 1 (4 colour-mode), 2 (16 colour-mode). The next 4 bits may be set to specify the shadowing on the window. If 0, the window has no shadow. The next 4 bits give the shadow height relative to the window behind it (a height of N units gives a shadow of N×2 pixels).  The components of the flags% argument are most easily specified as a combination of hexadecimal digits. For example:

flags%

description

$412

16 colour-mode ($2), shadowed window ($1), with height 4 units ($4) above the previous window with a shadow of 8 pixels.

$010

2 colour-mode (black and white) shadowed window at the same height as the previous window.

$101

4 colour mode window with no shadow (height ignored if shadow disabled).

$111

4 colour mode window with shadow of 1 unit above window behind, i.e. 2 pixel shadow.

Note (ER6):

The standard display mode for ER6 is 4096 (4K) color. To be in line with this, OPL defaults to the 4K color mode (KDisplayModeColor4K%) when started.

New constants for color modes have also been added to CONST.OPH.

See also gCLOSE, gGREY, DEFAULTWIN, gUSE, gORDER


gSETWIN

gSETWIN xpos%,ypos%,width%,height%
gSETWIN xpos%,ypos%

Change the position and, optionally, the size of the current window. Raises an error if the current drawable is a bitmap. The current cursor position is unaffected.  If this command is used on the default window, the SCREEN command must be used to ensure that the area in which PRINT commands display text is wholly contained within the default window.


gORDER

gORDER winId%,rank%

Set the window specified by the window ID winId% to the selected foreground/background position (rank%), and redraw the screen. Position 1 is the foreground window, position 2 is next, and so on. Any position greater than the number of windows is interpreted as specifying the end of the list. Raises an error if winId% is a bitmap.

On creation, a window is at position 1 in the list.

Note:

This only affects overlapping windows in the running OPL program and cannot be used to move the program to foreground.

See also gRANK, gUSE.


gRANK

rank% = gRANK

Return the current windows foreground/background position (that is the rank), from 1 to 8.  The rank is 1 for the foreground window. Raises an error if the current drawable is a bitmap.

See also gORDER.


gVISIBLE ON/OFF

gVISIBLE ON
gVISIBLE OFF

Make current window visible or invisible. Raises an error if the current drawable is a bitmap.


gORIGINX

leftgap% = gORIGINX

Return the gap in pixels between the left side of the screen and the left side of the current window. A negative value is returned if the left side of the window is to the left of the screen. Raises an error if the current drawable is a bitmap. 

See also gORIGINY.


gORIGINY

topgap% = gORIGINY

Return the gap in pixels between the top of the screen and the top of the current window.  A negative value is returned if the top of the window is above the top of the screen. Raises an error if the current drawable is a bitmap.

See also gORIGINX.


gCREATEBIT

id% = gCREATEBIT(width%,height%)
id% = gCREATEBIT(width%,height%,mode%)

Create a bitmap with specified dimensions width% and height%, and makes it the current drawable. Sets the current graphics cursor position to 0,0, its top left corner. Returns id%, the drawable ID, that identifies this bitmap for other keywords.  gCREATEBIT may be used with an optional third parameter which specifies the graphics mode of the bitmap to be created. The values of these are as given in gCREATE.  By default the graphics mode of a bitmap is 2-colour on ER5 and 4K-color on ER6.

See also gCLOSE, gLOADBIT, gSAVEBIT, gUSE.


gLOADBIT

id% = gLOADBIT(name$,write%,index%)
id% = gLOADBIT(name$,write%)
id% = gLOADBIT(name$)

Load a bitmap from the named bitmap file and makes it the current drawable. Sets the current graphics cursor position to 0,0, the top left corner. Returns id% that identifies the drawable for other keywords.

gLOADBIT does not add a default filename extension to the input argument name.

gLOADBIT loads EPOC32 picture files, in the same file format that is saved by gSAVEBIT. EPOC32 picture files can also be generated by exporting files created by the Sketch application. These are called multi-bitmap files (MBMs), though often containing just one bitmap as in the case of gSAVEBIT or Sketch files, and usually have an .MBM extension.

The bitmap is kept as a local copy in memory.

The optional write% argument specifies read/write access to the bitmap:

write%=0 For read-only access. Attempts to write to the bitmap in memory will be ignored, but the bitmap can be used by other programs without using more memory.

write%=1 Allows writing to and re-saving the bitmap; the default case.

For bitmap files that contain more than one bitmap, index% specifies which one to load.

For the first bitmap, use index%=0; the default value.

See also gCLOSE.


gSAVEBIT

gSAVEBIT name$,width%,height%
gSAVEBIT name$

Save the current drawable as the named bitmap file. If width% and height% are given, then only the rectangle of that size (in pixels) from the current cursor is copied.  A default file name extension is not supplied, but the convention is to use a .MBM filename extension.

See also gLOADBIT, gCREATEBIT.


gCLOSE

gCLOSE drawid%

Close the specified drawable (identified by its ID number, drawid%) that was previously opened by gCREATE, gCREATEBIT or gOPENBIT. If you close the current drawable, the default window (ID=1) becomes current. An error is raised if you try to close the default window.

See also gCREATE, gCREATEBIT  or gLOADBIT.


gUSE

gUSE drawid%

Make the drawable drawid% current. Graphics drawing commands will now use this drawable. The gUSE command does not bring the drawable to foreground (use gORDER 0 for this).


DEFAULTWIN

DEFAULTWIN grmode%

Change the default window (ID=1) to change the colour mode.

A side-effect of DEFAULTWIN is to clear the default window.

The default window uses 4-colour mode initially.

grmode%=0 changes to 2-colour mode (results in a mapping of greys to white or black) grmode%=1 just clears the screen, leaving the window in 4-colour mode.  grmode%=2 changes to 16-colour mode.

Using 4-colour mode uses more power than using 2-colour mode and 16-colour mode uses even more.

See also gGREY, gCREATE and gCOLOR.


gGREY

gGREY mode%

gGREY changes the pen colour between black and light grey (i.e. equivalent to the effect of using gCOLOR $aa,$aa,$aa).

All subsequent graphics drawing is determined by the value of mode%:

mode%

pen colour

0

Black pen

1

Light grey pen

2

Black – and all other values of mode%

See also DEFAULTWIN and gCREATE.


Window and bitmap characteristics

gLOADFONT

Load and unload user-defined fonts

gUNLOADFONT

 

gFONT

Set font to use

gSTYLE

Set style of text

gGMODE

Set graphics mode

gTMODE

Set text mode


gLOADFONT

fileId%=gLOADFONT(filename$)

Loads the user-defined fonts in the file filename$ and returns the fileId%, which is only used with gUNLOADFONT. The built-in fonts in ROM are automatically available, and do not need to be loaded.

A maximum of 16 font files may be loaded simultaneously. A set of published font UIDs are supplied with font files to enable the use of the loaded fonts with gFONT. Typically the UIDs are included from a header file e.g. CONST.OPH. For example:

fileId%=gLOADFONT(“Music1”)
gFONT KMusic1Font1
...
gUNLOADFONT fileId%

gFONT itself is very efficient, so all required fonts should normally be loaded at the start of the program.

Also see gUNLOADFONT, gFONT.


gUNLOADFONT

gUNLOADFONT fileId%

Unload a user-defined font that was previously loaded using gLOADFONT. Raises an error if the font has not been loaded. The built-in fonts are not held in memory and cannot be unloaded.

See also gLOADFONT.


gFONT

gFONT fontId

Set the font for the current drawable to fontId . The font may be one of the predefined fonts in the ROM or a user-defined font. User-defined fonts must first be loaded by gLOADFONT, which returns the font ID needed for gFONT.

In the table below, Swiss and Arial refer to fonts without serifs while Roman and Times fonts either have serifs (e.g. font 6) or are in a style designed for serifs, but are too small to show them. Courier is a mono-spaced font, i.e. has characters that are all the same width (and have their pixel size as width x height). With proportional fonts, each character can have a different width.

Initially Courier 8 is used.

Font

Name

Pixels WxH
or H only

Name

Pixels WxH
or H only

4

Mono

8x8

Courier

8

5

Roman

8

Times

8

6

Roman

11

Times

11

7

Roman

13

Times

13

8

Roman

16

Times

15

9

Swiss

8

Arial

8

10

Swiss

11

Arial

11

11

Swiss

13

Arial

13

12

Swiss

16

Arial

15

13

Mono

6x6

Tiny (mono)

3x4

The special font number $9a is set aside to give a machine's default graphics font; this is the font used initially for graphics text. This is font 12 (Arial 15). So gFONT 12 or gFONT 9a both set the standard font, which gPRINT normally uses.

Note:

Fonts are identified by a 32-bit UID, rather than by a 16-bit value representing the font position in the ROM as on OPL16 systems. However OPL does provide some mapping where possible between OPL16 font IDs and OPL font UIDs. A full list of the font IDs is provided in a header file CONST.OPH.

See also gLOADFONT, gSTYLE and FONT.


gSTYLE

gSTYLE style%

Set the style of text displayed in subsequent gPRINT, gPRINTB, gXPRINT and gPRINTCLIP commands on the current drawable.

style%

effect

OPL constant

0

Normal style

KgStyleNormal%

1

Bold

KgStyleBold%

2

Underlined

KgStyleUnder%

4

Inverse

KgStyleInverse%

8

Double height

KgStyleDoubleHeight%

16

Monospaced

KgStyleMonoFont%

32

Italic

KgStyleItalic%

These styles can be combined by ORing their symbolically defined constants - for example, to set underlined and double height, use:

gSTYLE 2 or 8

Alternatively add the style% values together. For example, to set bold underlined and double height use:

gSTYLE 11 (as 1+2+8=11)

Note that the Series 3 fonts 1 and 2 (see gFONT) are the normal and bold font versions of each other and bold i.e., style%=1 should not be used with them. Also mono i.e., style%=1 was designed for use with these two proportional fonts to change them to monospaced fonts algorithmically.

This command does not affect non-graphic commands, like PRINT.

See also gFONT, gTMODE.


gGMODE

gGMODE mode%

Set the graphics mode for the current drawable. This sets the effect of all subsequent drawing commands - gLINEBY, gBOX, etc. - on the current drawable.

mode%

pixels will be :

0

set

1

cleared

2

inverted

3

replaced (not in early versions of ER5)

By default, the drawing commands set the pixels in the drawable. Use gGMODE to change this. For example, if you have drawn a black background, you can draw a white box outline inside it with either:

...
gGMODE 1
gBOX
...

or:

...
gGMODE 2
gBOX
...

See also gBOX, gTMODE, gFILL


gTMODE

gTMODE mode%

Set the mode in which text is displayed for the current drawable. Subsequent gPRINT and gPRINTCLIP commands will draw in this mode.

mode%

pixels will be:

0

set

1

cleared

2

inverted

3

replaced

Before the first use of gTMODE in a program, mode% = 0, i.e. set. Graphics text commands cause a pixel to be set in the drawable for each dot in a character.  When mode% is 1 or 2, graphics text commands cause a pixel to be cleared (or inverted) for each dot in a character. When mode% is 3, entire character 'boxes' are displayed in the drawable; character pixels are set, and the background 'box' is cleared.  This command does not affect GIPRINT, gPRINTB, gXPRINT and the non-graphics commands, like PRINT.

See also gMODE, gSTYLE, gFONT.


Window and bitmap information

gIDENTITY

Get identity of current window/bitmap

 

Get graphics cursor position

gX

x position

gY

y position

gWIDTH

Get width or height of window/bitmap

gHEIGHT

 

gINFO

Get general information about current drawable

gINFO32

Get general information about current drawable

gCOLORINFO

Get information about color support (color devices only)

Note:

If used on the default window at program start up, gWIDTH and gHEIGHT can give useful information about the particular machine that a program is running on.


gIDENTITY

drawid% = gIDENTITY

Return the ID of the current drawable. The default window has ID=1.


gWIDTH

width% = gWIDTH

Returns the width of the current drawable.


gHEIGHT

height% = gHEIGHT

Return the height of the current drawable.


gINFO

gINFO var i%()

Gets general information about the current drawable and about the graphics cursor (whichever window it is in). See also gINFO32.

The information is returned in the array i%() which must be at least 32 integers long. The information is about the drawable in its current state, so e.g. the font information is for the current font in the current style.

The following information is returned:

i%(1)

lowest character in font (changed when gFONT is used)

i%(2)

highest character in font (changed when gFONT is used)

i%(3)

height of font (changed when gFONT is used)

i%(4)

descent of font (changed when gFONT is used)

i%(5)

ascent of font (changed when gFONT is used)

i%(6)

width of zero character (changed when gFONT is used)

i%(7)

maximum character width (changed when gFONT is used)

i%(8)

flags for font (see below, changed when gFONT is used)

i%(9-17)

name of font (see below, set by gFONT)

i%(18)

current graphics mode (set by gGMODE)

i%(19)

current text mode (set by gTMODE)

i%(20)

current style (set by gSTYLE)

i%(21)

cursor state (ON=1,OFF=0, set by CURSOR ON/OFF)

i%(22)

ID of the window containing the cursor (-1 for text cursor)

i%(23)

cursor width (set by CURSOR)

i%(24)

cursor height (set by CURSOR)

i%(25)

cursor ascent (set by CURSOR)

i%(26)

cursor x position in window

i%(27)

cursor y position in window

i%(28)

1 if drawable is a bitmap

i%(29)

cursor effects (not used anymore, set by CURSOR)

i%(30)

gGREY settings (not use anymore)

i%(31)

Reserved (window server ID of drawable)

i%(32)

Reserved

If the cursor state if OFF, (i%(21)=0), or is a text cursor (i%(22)=-1), then i%(23) to i%(27) and i%(29) should be ignored. If the cursor state is ON, (i%(21)=1), it is visible in the window identified by i%(22).

Array element i%(29) has bit 0 set (i%(29) AND 1) if the cursor is obloid, bit 1 set (i%(29) AND 2) if not flashing, and bit 2 set (i%(29) AND 4) if grey.

i%(8) contains certain flags that can optionally be stored in the font by its designer. There is therefore no guarantee that these flags are meaningful. If the font designer has followed the conventions for the flags, then i%(8) specifies a combination of the following font characteristics:

1

Standard ASCII character set (32-126)

2

Contains Code Page 850 character set (128-255)

4

Font is bold

8

Font is italic

16

Font is serifed

Use PEEK$(ADDR(i%(9))) to read the name of the font as a string.

See also gGMODE, gTMODE, gSTYLE, gGREY.


gINFO32

gINFO32 var i ()

Gets general information about the current drawable and about the graphics cursor (whichever window it is in). This replaces gINFO because the information returned has changed. i () must have 48 elements. The same information is returned to the array elements as for gINFO except for the following,

i (1)

reserved

i (2)

reserved

i (9)

the font UID as used in gFONT

i (10-17)

unused

i (30)

graphics colour-mode of current window

i (31)

gCOLOR red% of foreground

i (32)

gCOLOR green% of foreground

i (33)

gCOLOR blue% of foreground

i (34)

gCOLOR red% of background

i (35)

gCOLOR green% of background

i (36)

gCOLOR blue% of background

i (37-48)

elements 37 to 48 are currently unused

Additionally note that i (8)=2 means that Code Page 1252 is used (rather than Code Page 850) and also that there is no obloid cursor, so bit 0 will never be set in i (29).

See also gINFO, gFONT, gCOLOR, gCREATE.


gCOLORINFO

gCOLORINFO var cInfo ()

Returns information on color support for the current device. The information is returned in the array cInfo ()which must be at least 7 long integers long.

The following information is returned:

cInfo (1)

Display mode (see below)

cInfo (2)

Number of colors

cInfo (3)

Number of grays

cInfo (4)

not used

cInfo (5)

not used

cInfo (6)

 not used

cInfo (7)

 not used

On return cInfo (1) has one of the following values:

0

None

1

2 grays (B/W)

2

4 grays

3

16 grays

4

256 grays

5

16 colors

6

256 colors

7

64K colors

8

16M colors

9

RGB mode

10

4K colors

Constants for the indexes and color modes are supplied in CONST.OPH.

Note:

This command is only implemented on devices that have color support. You can use this procedure to check if your program is running on a device that supports color:

INCLUDE CONST.OPH

PROC ColorAvailable:
LOCAL cInfo (7)
ONERR ErrorHandler::
  gCOLORINFO cInfo ()
  IF cInfo (gColorInfoANumColors%)
    RETURN KTrue%
  ENDIF
  RETURN KFalse%
ErrorHandler::
  ONERR OFF
  REM Illegal Opcode - gCOLORINFO not supported
  IF ERR=-96
    RETURN KFalse%
  ENDIF
  RAISE ERR
ENDP


Graphics ‘cursor’ positioning

gAT

Set absolute graphics cursor position

gMOVE

Move graphics cursor

gX

Get current graphics cursor position

gY

 


gAT

gAT xpos%,ypos%

Set the graphics cursor position for the current window, using absolute co-ordinates.

gAT 0,0 sets the cursor position to the top left of the current drawable.

See also gMOVE.


gMOVE

gMOVE dx%,dy%

Moves the current graphics cursor position dx% to the right and dy% down, in the current drawable. Negative dx% and dy% move left and up respectively.

See also gAT.


gX

xpos% = gX

Returns the current x position, the offset from the left side of the current drawable.


gY

ypos% = gY

Returns the current y position, the offset from the top of the current drawable.


Graphics text

gPRINT

Display a list of expressions

gPRINTCLIP

Display text neatly clipped in rectangle

gPRINTB

Clear a box and display text within it

gTWIDTH

Get width of text

gXPRINT

Display text neatly underlined/highlighted


gPRINT

gPRINT list

Display a list of expressions at the current graphics cursor position in the current drawable.  All variable types are formatted as for PRINT. Unlike PRINT, gPRINT does not end by moving to a new line. A comma between expressions is still displayed as a space, but a semi-colon has no effect. Without a list of expressions, gPRINT does nothing.  Text displayed with gPRINT will be shown in the current text mode (as set by gTMODE) and font (as set by gFONT).

See also gPRINTB, gPRINTCLIP, gTWIDTH, gXPRINT, GIPRINT.


gPRINTCLIP

dischrs% = gPRINTCLIP(text$,width%)

Display text$ at the current graphics cursor position, displaying only as many characters as will fit inside width% pixels. Returns the number of characters displayed. 

See also gPRINT, gPRINTB, gTWIDTH, gXPRINT, GIPRINT, gTMODE.


gPRINTB

gPRINTB text$,width%
gPRINTB text$,width%,align%
gPRINTB text$,width%,align%,top%
gPRINTB text$,width%,align%,top%,bottom%
gPRINTB text$,width%,align%,top%,bottom%,margin%

Display text text$ in a cleared box of width width% pixels. The current graphics cursor position is used for the left side of the box and for the baseline of the text.

The align% argument controls the alignment of the text in the box:

align%

effect

1

right aligned

2

left aligned

3

centered.

The top% and bottom% arguments are the clearances (in pixels) from the text to the top and bottom of the box. Together with the current font size, they control the height of the box. An error is raised if top% plus the font ascent is greater than 255.

The margin% argument controls the margins:

alignment

margin%

left

The offset (in pixels) from the left of the box to the start of the text

right

The offset (in pixels) from the right of the box to the end of the text

centered

The offset (in pixels) from the left or right of the box to the region in which to centre, with positive margin% meaning left and negative meaning right.

If values are not supplied for some arguments, the following defaults are used:

align%

left

top%

0

bottom%

0

margin%

0

gPRINTB is not affected by the text mode set using gTMODE.

See also gPRINT, gPRINTCLIP, gTWIDTH, gXPRINT.


gTWIDTH

width% = gTWIDTH(text$)

Return the width in pixels of text$ for the current font and style.

See also gPRINT, gPRINTB, gPRINTCLIP, gXPRINT.


gXPRINT

gXPRINT string$,flags%

Display string$ at the current graphics cursor position in the current drawable, with precise highlighting or underlining. The current font and style are still used, even if the style itself is inverse or underlined. Text mode 3 (replace) is used - both set and cleared pixels in the text are drawn.

The flags% argument has the following effect:

flags%

effect

0

normal, as with gPRINT

1

inverse

2

inverse, rounded (corner pixels not inverse)

3

inverse, thin

4

inverse, thin, rounded (corner pixels not inverse)

5

underlined

6

thin, underlined

Where lines of text are separated by a single pixel, the thin options maintain the separation between lines.

The gXPRINT command does not support the display of a list of expressions of various types - use NUM$, GEN$, FIX$ and SCI$ to convert numbers to strings first. The gXPRINT command is not affected by the current text mode set using gTMODE.

See also gPRINT.


Graphics drawing commands

gCLS

Clear current window/bitmap

 

Draw a line

gLINEBY

relative to the current cursor position

gLINETO

to a specific point

gBOX

Draw a box

gBORDER

Draw borders

gXBORDER

 

gPOLY

Draw a set of lines

gFILL

Fill a rectangle

gINVERT

Invert the pixels in a rectangle

gPATT

Fill a rectangle with a pattern

gCOLOR

Set pen drawing colour

gCOLORBACKGROUND

Set background color

gSETPENWIDTH

Set pen drawing width in pixels

gCOPY

Copy a rectangle

gPEEKLINE

Read a horizontal line from a window/bitmap/screen

gSCROLL

Scroll a window/bitmap (also see gSETWIN)

gBUTTON

Draw a 3-D button/key

gCIRCLE

Draw a circle

gELLIPSE

Draw an ellipse

gCLOCK

Display or remove a running clock – see variants


gCLS

gCLS

Clear the whole of the current drawable and set the current graphics cursor position to 0,0 i.e., the top left corner.


gLINEBY

gLINEBY dx%,dy%

Draw a line from the current graphics cursor position to the point dx% to the right and dy% down in the current mode. Negative dx% and dy% mean left and up respectively. The current cursor position moves to the end of the line drawn.

gLINEBY never draws the end point, so for gLINEBY dx%,dy%, point

gX+dx%,gY+dy% is not drawn. However, OPL specially plots the point when the start and end-point coincide.

gLINEBY 0,0 plots (sets) the pixel at the current cursor position.

See also gLINETO, gPOLY.


gLINETO

gLINETO xpos%,ypos%

Draw a line from the current graphics cursor position to the point xpos%,ypos%. The current cursor position moves to xpos%,ypos%.

gLINETO never draws the end point, so for gLINETO dx%,dy%, point x%,y% is not drawn. However, OPL specially plots the point when the start and end-point coincide.  To plot a single point, use gLINETO gX,gY (or gLINEBY 0,0).

See also gLINEBY, gPOLY.


gBOX

gBOX width%,height%

Draw a box from the current graphics cursor position to the pixel width% to the right and height% down. The current cursor position is unaffected.

In OPL versions that support the gCOLORBACKGROUND command, if gGMODE is set to 3 (replace), the box is filled with the background color.

See also gBORDER, and gXBORDER.


gBORDER

gBORDER flags%
gBORDER flags%,width%,height%

Draw a one-pixel wide border around the edge of the current drawable. If width% and height% are supplied, a border shape of this size is drawn, with the top left corner at the current cursor position for graphics. If they are not supplied, the border is drawn around the whole of the current drawable.

The flags% parameter controls three attributes of the border - a shadow to the right and beneath, a one-pixel gap all around, and the type of corners used:

flags%

effect

OPL constant

1

single pixel shadow

KbordSglShadow%

2

gap for single pixel shadow

KbordSglGap%

3

double pixel shadow

KbordDblShadow%

4

gap for double pixel shadow

KbordDblGap%

$100

one-pixel gap all around

KbordGapAllRound%

$200

more rounded corners

KbordRoundCorners%

Flag values may be combined to control the three different effects. For example, for rounded corners and a gap for a double pixel shadow, use: flags%=$204.  Set flags%=0 for no shadow, no gap and sharper corners.

To de-emphasise a previously emphasised border, for example, use gBORDER with the shadow turned off:

gBORDER 3 REM show border
GET
gBORDER 4 REM border off

Shadows on windows will not show in the same way as shadows on other objects such as dialogs and menu panes. To display such shadows on a window, you must specify them when using gCREATE. Hence you should use gCREATE (and gXBORDER) in preference to gBORDER.

See also gBOX and gXBORDER.


gXBORDER

gXBORDER type%,flags%,width%,height%
gXBORDER type%,flags%

Draws a border in the current drawable of a specified type. The border fits inside a rectangle of the specified dimensions (width%, height%), or has the size of the current drawable if no dimensions are specified. Two types of border are available:

type%

description

0

For drawing a Series 3 type border. flags% are as for gBORDER.

1

For drawing a Series 3a/c, Siena and Workabout 3-D grey and black border. A shadow or a gap for a shadow is always assumed.

flags%=1,2,3,4 are as for gBORDER.

When the shadow is enabled (1 or 3) only the grey and black parts of the border are drawn; you should pre-clear the background for the white parts.

When the shadow is disabled (2 or 4) the outer and inner border lines are drawn, but the areas covered by grey/black when the shadow is enabled are now cleared. This allows a shadow to be turned off simply by calling gXBORDER again.

2

For Series 5 type borders.

 

The following values of flags% apply to Series 5 border types:

flags%

effect

0

none

$01

single black

$42

shallow sunken

$44

deep sunken

$54

deep sunken with outline

$82

shallow raised

$84

deep raised

$94

deep raised with outline

$22

vertical bar

$2a

horizontal bar

The following values of flags% apply to all border types:

flags%

effect

OPL constant

0

normal corners

 

Add $100

leave 1 pixel gap around the border.

KbordGapAllRound%

Add $200

more rounded corners

KbordRoundCorners%

Add $400

loose a single pixel at each corner of the rectangle, making it look slightly rounded.

KbordLosePixel%

If both $400 and $200 are mistakenly supplied, $200 has priority.

See also gBORDER.


gPOLY

gPOLY a%()

Draw a sequence of lines as defined by the array a%(). The command is equivalent to gAT followed by multiple gLINEBY and gMOVE commands, but it is quicker and more efficient.

The array is set up as follows:

a%(1)

starting x position

a%(2)

starting y position

a%(3)

number of pairs of offsets

a%(4)

dx1%

a%(5)

dy1%

a%(6)

dx2%

a%(7)

dy2% etc.

Elements a%(4) onwards specify pairs of offsets and the operation to be performed. Each pair specifies the amount by which to move. Positive dx% and dy% values indicate to the right and down respectively: negative values indicate to the left and up.

The dx% value also indicates the operation:

The current graphics cursor position is left at the start x, y position.  For example, to draw two horizontal lines 50 pixels long and 30 pixels apart starting at position 20,10:

a%(1)=20 : a%(2)=10 REM start x,y
a%(3)=3 REM 3 operations
a%(4)=50*2 : a%(5)= 0 REM draw right 50
a%(6)=0*2+1 : a%(7)=30 REM move down 30
a%(8)=-50*2 : a%(9)= 0 REM draw left 50
gPOLY a%()


gFILL

gFILL width%,height%,mode%

Fill the rectangle of the specified dimensions (width%, height%) from the current graphics cursor position, according to the graphics mode (mode%) specified. The current cursor position is unaffected.

mode%

pixels are:

0

set

1

cleared

2

inverted

See also gBOX, gPATT.


gINVERT

gINVERT width%,height%

Invert the rectangle width% to the right and height% down from the current graphics cursor position, except for the four corner pixels.


gPATT

gPATT pattid%,width%,height%,mode%

Fill the rectangle of the specified size from the current graphics cursor position, with repetitions of the drawable pattid%. Set pattid%=-1 to use a pre-defined grey pattern.  As with gCOPY, this command can copy both set and clear pixels, so the same modes are available as when displaying text:

mode%

pixels are:

0

set

1

cleared

2

inverted

3

replaced

If mode% is 3, the entire source drawable is copied, with set and clear pixels. For mode% values of 0, 1 and 2 only the pixels which are set in the pattern are acted on.  The cursor position is unaffected.

See also gFILL.


gCOLOR

gCOLOR red%,green%,blue%

Sets the pen colour of the current window. The red%,green%,blue% values specify a colour which will be mapped to white, black or one of the greys on non-colour screens.  Note that if the values of red%, green% and blue% are equal, then a pure grey results, ranging from black (0) to white (255). The exact effect will depend upon the grey levels set when the window is created. For example:

gCOLOR 0,0,0 REM now draw in solid black


gCOLORBACKGROUND

gCOLORBACKGROUND red%,green%,blue%

Sets the background colour of the current window. The red%,green%,blue% values specify a colour which will be mapped to white, black or one of the greys on non-colour screens.  Note that if the values of red%, green% and blue% are equal, then a pure grey results, ranging from black (0) to white (255). The exact effect will depend upon the grey levels set when the window is created. For example:

gCOLORBACKGROUND 255,255,255 REM default backcolor

Note:

This command is not available on early versions of OPL for ER5.


gSETPENWIDTH

gSETPENWIDTH width%

Sets the pen drawing width in the current drawable to width% pixels. The valid range is from 0 to 32767. A value of 2 gives a distinct line. Touching a single point on the screen with a value of 10 will give an approximately round spot.


gCOPY

gCOPY drawid%,xpos%,ypos%,width%,height%,mode%

Copy a rectangle of the specified dimensions (width%,height%) from the point

xpos%,ypos% in drawable drawid%, to the current cursor position for graphics in the current drawable. As this command can copy both set and clear pixels, the same modes are available as when displaying text.

mode%

pixels are:

0

set

1

cleared

2

inverted

3

replaced

Replace copies the entire rectangle, with set and clear pixels. The other modes act only on set pixels in the source pattern.

The current cursor position is not affected in either drawable.

gCOPY is affected by the setting of gGREY (in the current window) as follows:

gGREY

effect

0

copies black to black

1

copies grey to grey, or black to grey if source is black only

2

copies grey to grey and black to black, or black to both if source is black only.

Note:

It is inadvisable to use gCOPY to copy from windows as it is very slow. It should only be used for copying from bitmaps to windows or other bitmaps. 

See also gSCROLL.


gPEEKLINE

gPEEKLINE drawid%,xpos%,ypos%,var data%(),width%
gPEEKLINE drawid%,xpos%,ypos%,var data%(),width%,mode%

Read a horizontal line from the drawable drawid%, starting at xpos%,ypos%, with width% specifying the number of pixels to be read. The leftmost 16 pixels are read into data%(1), with the first pixel read into the least significant bit. The array data%() must be long enough to hold the data. The number of integers required is given by the (integer division) formula (length%+15)/16.

If width% is not a multiple of 16, data%() will contain some random values. For example, if width% is 1, as in this case:

gPEEKLINE drawid%,xpos%,ypos%,data%(),1

bit 0 of data%(1) will be meaningful, and the other 15 bits will not.

gPEEKLINE has an extra optional parameter mode% to specify the colour mode:

mode%

colour mode

colour of pixel which sets bits

-1

black and white

black

0

black and white

white

1

4-colour mode

white

2

16-colour mode

white

The default mode% is -1. For 4 and 16-colour modes, 2 and 4 bits per pixel respectively are used. This is to enable the colour of the pixel to be ascertained from the bits that are set. White results in all 2 or 4 bits being set, while black sets none of them. For example, in a 4-colour window, with the colour set by gCOLOR 16,16,16 a pixel of a line would peek as 0001 in binary. Similarly, a pixel of a line with the colour set to gCOLOR 80,80,80 would result in the value 0101 in binary when peeked.

Note:

If the optional parameter mode% is used, the array size allowed must be adjusted accordingly: it must be at least twice as long as the array needed for black and white if the line you wish to peek in 4-colour mode and four times as long in 16-colour mode.


gSCROLL

gSCROLL dx%,dy%
gSCROLL dx%,dy%,xpos%,ypos%,width%,height%

Scroll the pixels within the current drawable by offset dx%,dy%. Positive dx%,dy% indicate right and down respectively. The drawable itself does not change position and the current cursor position is unaffected.

If a rectangle within the current drawable is specified, at xpos%,ypos% with dimensions width%,height%, (in pixels), only this rectangle is scrolled.

The gSCROLL command may be viewed as providing the capability to move a rectangle to a new position within the same drawable. The region left behind by the scroll is cleared, so if you are using gSCROLL to perform vertical text scrolling for example, you must display the appropriate line in the cleared region yourself.

If there is only a small amount of text in a window it may be more appropriate to  use gSETWIN to move the whole window, containing all the text, up and down relative to the screen.

Pixels that scroll off the screen are lost. If you want to be able to scroll back, use gSETWIN.

See also gSETWIN.


gBUTTON

gBUTTON text$,ty%,width%,height%,st%,bitmapId
gBUTTON text$,ty%,width%,height%,st%,bitmapId ,maskId
gBUTTON text$,ty%,width%,height%,st%,bitmapId ,maskId ,layout%

Draw a 3-D black and grey button.

This is a key, not an application button. It is drawn at the current position in a rectangle of size width%, and height%, which fully encloses the button in all its states. The label text$ specifies up to 64 characters to be drawn in the button in the current font and style.

You must ensure that the text will fit in the button.

To draw a Series 3 style button use ty%=0, to draw a Series 3a/c type button use ty%=1, use ty%=2 for a Series 5 type button.

The meaning of st% varies according to ty%:

button type

ty%

OPL constant

button state

st%

OPL constant

S3 style

0

KButtS3%

raised button

0

KbuttS3Raised%

S3 style

0

KButtS3%

depressed (flat) button.

1

KbuttS3Pressed%

S3a/c style

1

KButtS3a%

raised button

0

KbuttS3aRaised%

S3a/c style

1

KButtS3a%

semi-depressed (flat) button

1

KbuttS3aSemiPressed%

S3a/c style

1

KButtS3a%

fully-depressed (sunken) button.

2

KbuttS3aSunken%

S5 style

2

KButtS5%

raised button

0

KbuttS5Raised%

S5 style

2

KButtS5%

semi-depressed (flat) button

1

KbuttS5SemiPressed%

S5 style

2

KButtS5%

fully-depressed (sunken) button

2

KbuttS5Sunken%

There is added support so that bitmaps may be used on buttons. Three extra optional arguments can be passed which give the bitmap ID, the mask ID and the layout for the button respectively. maskId% can be 0 to specify no mask.

The following constants should be used for layout% to specify relative positions of the text and icon on a button,

position of text

layout%

right

0

bottom

1

top

2

left

3

The following constants can be added to the values above to specify how a button’s excess space is to be allocated,

share

0

to text

$10

to picture

$20

When the layout is such that the text is at the top or the bottom, then text and picture are centred vertically and horizontally in the space allotted to them. If the layout has text to the left or right, then the text is left aligned in the space allotted to it and the picture is right or left aligned respectively. Both text and picture are centred vertically in this case.

Examples:

layout%

description

$13

a button with text on the left and left aligned in any excess space.

$20

a button with text on the right and the picture left aligned in any excess space.

$10

a standard toolbar button, putting the text on the right.

For a picture only with no text use text$=“”.

An ‘Invalid arguments’ error is raised if you use the ID of a window with gBUTTON.  Read-only bitmaps may also be loaded using the Bitmap OPX.


gCIRCLE

gCIRCLE radius%
gCIRCLE radius%,fill%

Draws a circle with the centre at the current position in the current drawable. If the value of radius% is negative then no circle is drawn.

If fill% is supplied and if fill% 0 then the circle is filled with the current pen colour. If fill% is not supplied or fill%=0 and gGMODE is set to 3, the circle is filled with the current background color.

See gELLIPSE, gCOLOR, gCOLORBACKGROUND.


gELLIPSE

gELLIPSE hRadius%,vRadius%
gELLIPSE hRadius%,vRadius%,fill%

Draws an ellipse with the centre at the current position in the current drawable. hRadius% is the horizontal distance in pixels from the centre of the ellipse to the left (and right) of the ellipse. vRadius% is the vertical distance from the centre of the ellipse to the top (and bottom). If the length of either radius is less than zero, then no ellipse is drawn. 

If fill% is supplied and if fill% 0 then the circle is filled with the current pen colour. If fill% is not supplied or fill%=0 and gGMODE is set to 3, the circle is filled with the current background color.

See gCIRCLE, gCOLOR, gCOLORBACKGROUND.


gCLOCK

gCLOCK ON
gCLOCK ON,mode%
gCLOCK ON,mode%,offset
gCLOCK ON,mode%,offset ,format$
gCLOCK ON,mode%,offset ,format$,font
gCLOCK ON,mode%,offset ,format$,font ,style%
gCLOCK OFF

Display or remove a running clock showing the system time. The clock is drawn at the current graphics cursor position in the current window. Only one clock may be displayed in each window. In order to replace a clock with a new type, you first need to call gCLOCK OFF.

The mode% argument controls the type of clock.

The offset% argument specifies an offset in minutes from the system time to the displayed time. This allows you to display a clock showing a time other than the system time (e.g. the time in another country).

The defaults are: mode% = 1, and offset% = 0.

Notes:

Do not use gSCROLL to scroll the region containing a clock. When the time is updated, the old position would be used. The whole window may, however, be moved using gSETWIN.  On systems with a grey plane it is possible to draw clocks that include grey in windows created without a grey plane.

An offset of up to a whole day can be specified.

mode%

clock type

6

Black and grey medium, system setting

7

Black and grey medium, analog

8

Second type medium, digital, automatically displays of day of week and day of month below the time

9

Black and grey extra large, automatically displays a second hand

11

Formatted digital (described below) replaces mode%=10 in OPL16.

You can OR the value of mode% with $100 to allow offset to be specified in seconds

format

effect

%%

Insert a single % character in the string

%*

Abbreviate following item, e.g. %*1. Omits leading zeros, or truncates names to three characters.

%:n

Insert a system time separator character. n is an integer between zero and three that indicates which time separator character is to be used. For European time settings, only n=1 and n=2 are used, giving the hours/minutes separator and minutes/seconds separator respectively.

%/n

Insert a system date separator character. n is an integer between zero and three that indicates which date separator character is to be used. For European time settings, only n=1 and n=2 are used, giving the day/month separator and month/year separator respectively.

%1

Insert the first component of a three component date (i.e. day, month and year) where the order of the components is determined by the system settings. The possibilities are: dd/mm/yyyy, (European), mm/dd/yyyy (American), yyyy/mm/dd (Japanese).

%2

Insert the second component of a three component date where the order has been determined by the system settings. See %1.

%3

Insert the third component of a three component date where the order has been determined by the system settings. See %1.

%4

Insert the first component of a two component date (i.e. day and month only) where the order has been determined by system settings. The possibilities are: dd/mm, (European), mm/dd (American), mm/dd (Japanese).

%5

Insert the second component of a two component date where the order has been determined by the system settings. See %4.

%A

Insert am or pm according to the current language and time of day. Text is printed even if 24 hour clock is in use. May be placed before or after the time, and a trailing or leading space as appropriate will be added. The abbreviated version (%*A) removes this space. Optionally, a minus or plus sign may be inserted between the % and the A. This operates as follows: %-A causes am/pm text to be inserted only if the system setting of the am/pm symbol position is set to display before the time. Similarly, %+A causes am/pm text to be inserted only if the system setting of the am/pm symbol is set to display after the time. No am/pm text will be inserted before the time if a + is inserted in the string. For example you could use, “%-A%H%:1%T%+A” to insert the am/pm symbol either before or after the time, according to the system setting. %+A and %-A cannot be abbreviated.

%B

As %A, except that the am/pm text is only inserted if the system clock setting is 12 hour. (This should be used in conjunction with %J. )

%D

Insert the two-digit day number in month (in conjunction with %1 etc.).

%E

Insert the day name. Abbreviation is language specific (3 letters in English).

%F

Use this at the beginning of a format string to make the date/time formatting independent of the system setting. This fixes the order of the following day/month/year component(s) in their given order, removing the need to use %1 to %5, allowing individual components of the date to be printed.

%H

Insert the two-digit hour component of the time in 24 hour clock format.

%I

Insert the two-digit hour component of the time in 12 hour clock format. Any leading zero is automatically suppressed, regardless of whether an asterisk is inserted or not.

%J

Insert the two-digit hour component of time in either 12 or 24 hour clock format depending on the corresponding system setting. When the clock has been set to 12 hour format, the hour’s leading zero is automatically suppressed regardless of whether an asterisk has been inserted between the % and J.

%M

Insert the two-digit month number (in conjunction with %1 etc.).

%N

Insert the month name (in conjunction with %1 etc.). When using system settings (i.e. not using %F) this causes all months following %N in the string to be written in words. When using fixed format (i.e. when using %F) %N may be used alone to insert a month name. Abbreviation is language specific (3 letters in English).

%S

Insert the two-digit second component of the time.

%T

Insert the two-digit minute component of the time.

%W

Insert the two-digit week number in year, counting the first (part) week as week 1.

%X

Insert the date suffix. When using system settings (i.e. not using %F), this causes a suffix to be put on any date following %X in the string. When using fixed format (i.e. using %F), %X following any date appends a suffix for that particular date. Cannot be abbreviated.

%Y

Insert the four digit year number (in conjunction with %1 etc.). The abbreviation is the last two digits of the year.

%Z

Insert the three digit day number in year.

Example format strings are as follows:

The example used is 1:30:05 pm on Wednesday, 1st January 1997, with the system setting of European dates and with am/pm after the time:

“%-A%I:%T:%S%+A” will print the time in 12 hour clock, including seconds, with the am/pm either inserted before or after the time, depending on the system setting. So the example time would appear as, 1:30:05 pm.

“%F%E %*D%X %N %Y” will print the day of the week followed by the date with suffix, the month as a word and the year. For example, Wednesday 1st January 1997.

“%E %D%X%N%Y %1 %2 %3” will use the locale setting for ordering the elements of the date, but will use a suffix on the day and the month in words. For example, Wednesday 01st January 1997.

“%*E %*D%X%*N%*Y %1 %2 '%3” will be similar to 3., but will abbreviate the day of the week, the day, the month and the year, so the example becomes “Wed 1st Jan 97”.

“%M%Y%D%1%/0%2%/0%3” will appear as 01/01/1997. This demonstrates that the ordering of the %D, %M and %Y is irrelevant when using locale-dependent formatting.  Instead the ordering of the date components is determined by the order of the %1, %2, and %3 formatting commands.

style% may take any of the values used to specify gSTYLE, other than 2 (underlined).

Note:

A ‘General Failure’ error will result if you attempt to use an invalid format. Invalid formats include using %: and %/ followed by 0 or 3 when in European locale setting (when these separators are without meaning) and using %+ and %- followed by characters other than A or B.


Menus

mINIT

Start a new set of menus

mCARD

Define a menu

mCARDX

Define a menu with icons (ER6)

mCASC

Define a cascade menu

MENU

Display menus

mPOPUP

Define and display a popup menu


mINIT>

mINIT

Cancel any existing menus, in preparation for the definition of new menus. Use mCARD and mCASC to define each menu, then MENU to display them.

It is incorrect to ignore mCARD and mCASC errors by having an ONERR label around an mCARD or mCASC call. If you do, the menu is discarded and a ‘Structure fault’ will be raised on using mCARD, mCASC or MENU without first using mINIT again - see MENU.


mCARD

mCARD title$,item1$,hotkey1%
mCARD title$,item1$,hotkey1%,item2$,hotkey2%...

Define a menu which has been initialised using mINIT. When all of the menus have been defined, MENU is used to display them.

The title$ argument is the name of the menu. A maximum number of 8 items on the menu may be defined.

Each menu item is specified by two arguments. The first is the item name, and the second the key code for a hot-key. This specifies a key which, when pressed together with the Ctrl key, will select the option. If the key code is for an upper case key, the hot-key will use both the Shift and Ctrl keys together.

Options can be divided into logical groups by displaying a grey line under the final option in a group. To do this, pass the negative value corresponding to the hot-key code for the final option in the group. For example, -%A specifies hot-key Ctrl-Shift-A and displays a grey line under the associated option in the menu.

The following menu features are supported:

The extra properties are controlled by adding the following bits to the shortcut key keycode.

effect

value

OPL constant

menu item dimmed

$1000

KmenuDimmed%

item has check-box

$0800

KmenuCheckBox%

start of an option button list

$0900

KmenuOptionStart%

middle of an option button list

$0A00

KmenuOptionMiddle%

end of an option button list

$0B00

KmenuOptionEnd%

checkbox/option button symbol on

$2000

KmenuSymbolOn%

checkbox/option button symbol indeterminate

$4000

KmenuSymbolIndeterminate%

The start, middle and end option buttons are for specifying a group of related items that can be selected exclusively (i.e. if one item is selected then the others are deselected). The number of middle option buttons is variable. A single menu card can have more than one set of option buttons and checkboxes, but option buttons in a set should be kept together.  For speed, OPL does not check the consistency of these items’ specification.  If a separating line is required when any of these effects had been added, you must be sure to negate the whole value, not just the shortcut key key-code.

In the example,

mCARD “Options”,“View1”,%A OR $2900,“View2”,-(%B OR $B00), “Another option”,%C

the second shortcut key key-code and its flag value is correctly negated to display a separating line.

A ‘Too wide’ error is raised if the menu title length is greater than or equal to 40. Shortcut values must be alphabetic character codes or numbers between the values of 1 and 32. Any other values will raise an ‘Invalid arguments’ error.

If any menu item fails to be added successfully, a menu is discarded. It is therefore incorrect to ignore mCARD errors by having an ONERR label around an mCARD call. If you do, the menu is discarded and a ‘Structure fault’ will be raised on using mCARD without first using mINIT again. See MENU for an example of this.

Note:

In ER6 OPL provides the ability for menu items to be ‘skipped’ as they are built. This is useful, for example, when building the ‘Send’ cascade where several different SendAs methods may be installed on a device but only a sub-set are suitable for your application.   

Any item specified on the mCARD/mCASC/mCARDX, which has a null (i.e. zero value) hotkey, will not actually be added to the menu. An example

PROC MenuTest:
  mINIT
  mCARD “Test”,”Item 1”,%a,”Item 2”,%b,”Item 3”,0,”Item 4”,%d,”Item 5”,0,”Item 6”,0,”Item 7”,%gMENU
ENDP

This will display a menu pane with the following items listed:

Test
  ----
  Item 1  Ctrl+A
  Item 2  Ctrl+B
  Item 4  Ctrl+D
  Item 7  Ctrl+G

Clearly, this can be enhanced in a “real world” application to use variables for the hotkey, which can be dynamically set to vary the menu items on show.

See also mINIT, MENU and mCASC for cascaded menu items.


mCARDX, ER6

mCARDX bitmapId , maskId , item1$, hotkey1%, item2$, hotkey2%,…

The mCARDX keyword is essentially the same as mCARD but with the difference that instead of supplying a string caption for the menu card, you supply a bitmap and bitmap mask instead.

The recommended size for these bitmaps is 25x20 pixels in 256 colors (i.e. specify the /c8 flag when using the BMCONV tool provided on all Symbian OS SDKs).

Note:

In ER6 OPL provides the ability for menu items to be ‘skipped’ as they are built. This is useful, for example, when building the ‘Send’ cascade where several different SendAs methods may be installed on a device but only a sub-set are suitable for your application.   

Any item specified on the mCARD/mCASC/mCARDX, which has a null (i.e. zero value) hotkey, will not actually be added to the menu. An example

PROC MenuTest:
  mINIT
  mCARD “Test”,”Item 1”,%a,”Item 2”,%b,”Item 3”,0,”Item 4”,%d,”Item 5”,0,”Item 6”,0,”Item 7”,%gMENU
ENDP

This will display a menu pane with the following items listed:

Test
  ----
  Item 1  Ctrl+A
  Item 2  Ctrl+B
  Item 4  Ctrl+D
  Item 7  Ctrl+G

Clearly, this can be enhanced in a “real world” application to use variables for the hotkey, which can be dynamically set to vary the menu items on show.


mCASC

mCASC title$,item1$,hotkey1%,item2$,hotkey2%

Creates a cascade for a menu, on which less important menu items can be displayed. The cascade must be defined before use in a menu card. For example, a ‘Bitmap’ cascade under the File menu of a possible OPL drawing application could be defined like this:

mCASC “Bitmap”,”Load”,%L,”Merge”,%M
mCARD “File”,“New”,%n,”Open”,%o,”Save”,%s,”Bitmap ”,16,”Exit”,%e

The trailing character specifies that a previously defined cascade item is to be used in the menu at this point: it is not displayed in the menu item. A cascade has a filled arrow head displayed along side it in the menu. The cascade title in mCASC is also used only for identification purposes and is not displayed in the cascade itself. This title needs to be identical to the menu item text apart from the . For efficiency, OPL doesn’t check that a defined cascade has been used in a menu and an unused cascade will simply be ignored.  To display a in a cascaded menu item, you can use .

Shortcut keys used in cascades may be added to the appropriate constant values as for mCARD to enable checkboxes, option buttons and dimming of cascade items.

As is typical for cascade titles, a shortcut value of 16 is used in the example above. This prevents the display or specification of any shortcut key. However, it is possible to define a shortcut key for a cascade title if required, for example to cycle through the options available in a cascade.

Note:

In ER6 OPL provides the ability for menu items to be ‘skipped’ as they are built. This is useful, for example, when building the ‘Send’ cascade where several different SendAs methods may be installed on a device but only a sub-set are suitable for your application.   

Any item specified on the mCARD/mCASC/mCARDX, which has a null (i.e. zero value) hotkey, will not actually be added to the menu. An example

PROC MenuTest:
  mINIT
  mCARD “Test”,”Item 1”,%a,”Item 2”,%b,”Item 3”,0,”Item 4”,%d,”Item 5”,0,”Item 6”,0,”Item 7”,%gMENU
ENDP

This will display a menu pane with the following items listed:

Test
  ----
  Item 1  Ctrl+A
  Item 2  Ctrl+B
  Item 4  Ctrl+D
  Item 7  Ctrl+G

Clearly, this can be enhanced in a “real world” application to use variables for the hotkey, which can be dynamically set to vary the menu items on show.

See mCARD, MENU, mINIT.


MENU

val% = MENU(var init%)

Displays the menus defined by mINIT, mCARD and mCASC, and waits for you to select an item. Returns the hot-key key code of the item selected, as defined in mCARD, in lower case. If the menu is cancelled by pressing Esc, MENU returns 0.  If init% is passed it sets the initial menu pane and item to be highlighted. The init% argument should be 256*(menu%)+item%; for both menu% and item%, 0 specifies the first, 1 the second and so on. If init% is 517 (=256*2+5), for example, this specifies the 6th item on the third menu.

MENU writes back to init% the value for the item that was last highlighted on the menu. You can then use this value when calling the menu again.  In OPL16, you only need to use this technique if you have more than one menu in your program, maintaining one variable for each menu.

It is necessary to use MENU(init%), passing back the same variable each time the menu is opened if you wish the menu to reopen with the highlight set on the last selected item.

It is incorrect to ignore mCARD and mCASC errors by having an ONERR label around an mCARD or mCASC call. If you do, the menu is discarded and a ‘Structure fault’ will be raised on using mCARD, mCASC or MENU without first using mINIT again.

The following bad code will not display the menu:

mINIT
ONERR errIgnore1
mCARD “Xxx”,”ItemA”,0 REM bad shortcut
errIgnore1::
ONERR errIgnore2
mCARD “Yyy”,”” REM ‘Structure fault’ error (mINIT discarded)
errIgnore2::
ONERR OFF
MENU REM ‘Structure fault’ again

Note (ER6):

In all previous Symbian OS releases, C++ applications would store the last used menu position even when the user cancelled the menu with the Escape key but (for Opl1993 compatibility) OPL applications did not. This has been changed in ER6 and OPL applications now behave like C++ ones in this respect.

However, for compatibility a new SETFLAGS option has been provided. There is a CONST for this listed in CONST.OPH. The new menu operation is in operation by default. To return to the old style of OPL menu simply call:

SETFLAGS KMenuCancelCompatibility

See also mCARD, mINIT and SETFLAGS.


mPOPUP

mPOPUP(x%,y%,posType%,item1$,hotkey1%,item2$,hotkey2%,...)

Presents a popup menu. mPOPUP returns the value of the keypress used to exit the popup menu, this being 0 if Esc is pressed.

mPOPUP defines and presents the menu itself, and should not and need not be called from inside the mINITMENU structure. posType% is the position type controlling which corner of the popup menu x%,y% specifies and can take the values,

posType%

corner

OPL constant

0

top left

KMPopupPosTopLeft%

1

top right

KMPopupPosTopRight%

2

bottom left

KMPopupPosBottomLeft%

3

bottom right

KMPopupPosBottomRight%

item$ and key% can take the same values as for mCARD, with key% taking the same constant values to specify checkboxes, option buttons and dimmed items. However, cascades in popup menus are not supported.

For example:

mPOPUP (0,0,0,“Continue”,%c,“Exit”,%e)

specifies a popup menu with 0,0 as its top left-hand corner with the items ‘Continue’ and ‘Exit’, with the shortcut keys Ctrl+C and Ctrl+E respectively. 

See also mCARD.


Dialogs

dINIT

Start a new dialog

dPOSITION

Position a dialog

dTEXT

Define text for dialog

dEDIT

Define a text edit box for dialog

dEDITMULTI

Define a multi-line text edit box for dialog

dXINPUT

Define a secret edit box for a dialog

dFILE

Define a filename edit box for a dialog

dCHOICE

Define a choice list for a dialog

dFLOAT

Define a floating point numeric edit box for a dialog

dLONG

Define a long numeric edit box for a dialog

dDATE

Define a date edit box for a dialog

dTIME

Define a time edit box for a dialog

dBUTTONS

Define exit keys for a dialog

dCHECKBOX

Define a check box for a dialog

DIALOG

Display a dialog

ALERT

Display a simple alert dialog

Notes:

dINIT

dINIT
dINIT title$
dINIT title$,flags%

Prepare for the definition of a dialog, cancelling any existing one.  Use dTEXT, dCHOICE, etc. to define each item in the dialog, then DIALOG to display the dialog. If title$ is supplied, it will be displayed at the top of the dialog, centred and with a line across the dialog below it.

The maximum number of lines of text that the dialog can have is 9.

flags% can be any ORed combination of the following:

flags%

effect

OPL constant

1

buttons on right rather than at bottom

KDlgButRight%

2

no title, any title in dINIT is ignored

KDlgNoTitle%

4

use the full screen

KDlgFillScreen%

8

don’t allow dialog box to be dragged

KDlgNoDrag%

16

pack dialog densely (not buttons) for more lines

KDlgDensePack%

Dialogs without titles cannot be dragged regardless of value of flags%.

Note:

Errors that occurred when adding items to a dialog, cause dINIT to fail.  If such errors occur, the dialog will be deleted a ‘Structure fault’ error is raised, and dINIT will have to be called again.


dPOSITION

dPOSITION posx%,posy%

Position a dialog.

Use dPOSITION at any time between dINIT and DIALOG. The dPOSITION command uses two integer values. The first, posx%, specifies the horizontal position, and the second, posy%, the vertical position.

For example:

command

dialog screen position

OPL constants

dPOSITION –1,-1

top left

KDPositionLeft%, KDPositionLeft%

dPOSITION 1,1

bottom right

KDPositionRight%, KDPositionRight%

dPOSITION 0,0

central, the default position for dialogs.

KDPositionCentre%, KDPositionCentre%

dPOSITION 1,0

right-hand edge, and centered half way up the screen.

KDPositionRight%, KDPositionCentre%


dTEXT

dTEXT prompt$,body$
dTEXT prompt$,body$,format%

Define a line of text to be displayed in a dialog.

The prompt, prompt$, will be displayed on the left side of the line, and body$ on the right side. If you only want to display a single string, use a null string ( ) for prompt$, and pass the desired string in body$. It will then have the whole width of the dialog to itself.

An error is raised if body$ is a null string. The text in body$ is normally displayed left aligned (although usually in the right column). You can override this by specifying format%:

format%

effect

OPL constant

0

left align body$

KDTextLeft%

1

right align body$

KDTextRight%

2

centre body$

KDTextCentre%

Alignment of body$ is only supported when prompt$ is null, with the body being left aligned otherwise. In addition, you can add any or all of the following three values to format%, for these effects:

format%

effect

OPL constant

$200

draw a line below this item

KDTextLineBelow%

$400

allow prompt$ item to be selected

KDTextAllowSelection%

$800

specify this item as a text separator

KDTextSeparator%

Setting format% = $400 allows only the prompt, and not the body, to be selected.  Bold dialog text is not supported. You can display a line separator between any dialog items by setting the flag $800 on an item where prompt$ and body$ are null. (If prompt$ and/or body$ are not null, then the flag is ignored and no separator is drawn.)

The separator counts as an item in the value returned by DIALOG. OPL still supports OPL16’s underlining of dTEXT items by setting format% = $200. Setting format% = $400 allows the only the prompt, but not the body, to be selected.

See also dEDIT.


dEDIT

dEDIT var string$,prompt$
dEDIT var string$,prompt$,width%

Define a string edit box, to go in a dialog.

The prompt, prompt$, will be displayed on the left side of the line. The string variable to edit is string$. Its initial contents will appear in the dialog. The length used when string$ was defined is the maximum length you can type in. On exiting the dialog, the string$ variable will hold the value entered by the user.

The value width%, if supplied, gives the width (in pixels) of the edit box (allowing for widest possible character in the font). The string will scroll inside the edit box, if necessary. If width% is not supplied, the edit box is made wide enough for the maximum width string$ could possibly be.

See also dTEXT, dXINPUT.


dEDITMULTI

dEDITMULTI ptrdata ,prompt$,width%,lines%,maxlen%,
dEDITMULTI ptrdata ,prompt$,width%,lines%,maxlen%,readonly% - ER6

Defines a multi-line edit box to go into a dialog. Normally the resulting text would be used in a subsequent dialog, saved to file or printed using the Printer OPX.

ptrdata

Holds the address of the buffer for the text.

prompt$

Displayed on the left side of the edit box.

width%

Specifies the width of the edit box within which the text is wrapped, using a notional average character width. The actual number of characters that will fit will depend on the character widths.

lines%

Specifies the number of full lines displayed. Any more lines will be scrolled.

maxlen%

The length in bytes of the buffer excluding the bytes used to store the length.

Note that the edit box uses any Enter key pressed when it has the focus, so Enter can’t be used to exit the dialog. Another item is needed that can take the focus without using the Enter key. For example, a button that does not use the Enter key to exit a dialog whenever it contains a multi-line edit box. The Enter key is used by a multi-line edit box that has the focus before being offered to any buttons. However, the Esc key will always cancel a dialog, even when it contains a multi-line edit box.

ptrdata is the address of a buffer to take the edited data. It could be the address of an array as returned by ADDR, or of a heap cell, as returned by ALLOC (see ADDR and ALLOC).  The buffer may not be specified directly as a string, and may not be read as such; it should be peeked, byte by byte. It is convenient to use a long integer array as the buffer, with at least 1+(maxlen%+3)/4 elements. The leading 4 bytes at ptrdata contains the initial number of bytes of data following. The first four bytes are set by dEDITMULTI to the actual number of bytes edited. Hence the first element of the array should specify the initial length.

If an allocated cell is used (probably because more than 64K is required), the first 4 bytes of the cell must be set to the initial length of the data. If this length is not set then an error will be raised. For example if a 100000 byte cell is allocated, you would need to poke a zero long integer in the start to specify that there is initially no text in the cell. For example:

ptrdata =ALLOC(100000)
POKEL ptrdata ,0 REM Text starts at ptrdata + 4

On ER6 the dEDITMULTI command can accept an optional 6th short-integer parameter. This parameter is used to tell the editor to be read-only or editable. If the parameter is not specified or if KFalse% is specified the multi-line editor will not be read-only (i.e. users can edit the contents). If KTrue% is specified then the contents of the editor will not be editable.

A number of special characters (defined in CONST.OPH) may appear in the buffer:

A paragraph delimiter marks the end of a paragraph. A line break is a new line that does not signify a new paragraph. Non-breaking characters guarantee that no line break will occur at the point they are inserted. A potential hyphen marks the place where a hyphen may be inserted if the word occurs on the break of a line. A visible space character is the character that is displayed when spaces are set to be visible.

Example (ER5):

The following example presents a three-line edit box that is about 10 characters wide and allows up to 399 characters:

CONST KLenBuffer%=399
PROC dEditM:
LOCAL buffer (101) REM 101=1+(399+3)/4 in integer arithmetic
LOCAL pLen ,pText
LOCAL i%
LOCAL c%
  pLen =ADDR(buffer (1))
  pText =ADDR(buffer (2))
  WHILE 1
    dINIT “Try dEditMulti”
    dEDITMULTI pLen ,”Prompt”,10,3,KLenBuffer%
    dBUTTONS “Done”,%d REM button needed to exit dialog
    IF DIALOG=0 :BREAK :ENDIF
    PRINT “Length:”;buffer (1)
    PRINT “Text:”
    i%=0
    WHILE i% buffer (1)
      c%=PEEKB(pText +i%)
      IF c% =32
        PRINT CHR$(c%);
      ELSE
        PRINT “.”; REM just print a dot for special characters
      ENDIF
      i%=i%+1
    ENDWH
  ENDWH
ENDP

Example (ER6):

To do: example for ER6 with Unicode strings.


dXINPUT

dXINPUT var string$,prompt$
dXINPUT var string$,prompt$,seed% - ER6

Define a secret string edit box, such as for a password, to go in a dialog. The prompt, prompt$, will be displayed on the left side of the line. The string$ parameter is the string variable to take the string that the user types in.

Initially the dialog does not show any characters for the string; the initial contents of string$ are ignored. A special symbol will be displayed for each character you type, to preserve the secrecy of the string.

On ER6 the dXINPUT command can accept an optional 3rd short-integer parameter. This parameter can be used to govern if the contents of the secret editor should be ‘seeded’ with the contents of the string you supply in the first parameter. If the new parameter is not specified or if KFalse% is specified the secret editor will behave as in ER5 and will not be seeded with any text. If KTrue% is specified then the contents of the editor will be set to the contents of the string specified in the first parameter.

Note:

string$ must be less than 16 characters long (OPL identifier KDXInputMaxLen%).


dFILE

dFILE file$,prompt$,flags%
dFILE file$,prompt$,flags%,Uid1=0,Uid2=0,Uid3=0

Defines a filename edit box or selector, to go in a dialog. A ‘Folder’ and ‘Disk’ selector are automatically added on the following lines.  file$ must be declared to be 255 bytes long, since file names may be up to this length, and if it is shorter an error will be raised. The prompt, prompt$, will be displayed on the left side of the line. By default no prompts are displayed for the file, folder and disk selectors. A comma-separated prompt list should be supplied.

For example, for a filename editor with the standard prompts use:

dFILE file$, File,Folder,Disk ,1

The type of file editor is controlled by flags%, and the kind of input allowed. You can add (OR) together any of the following values:

flags%

meaning

OPL constant

1

use an edit box

KDFileEditBox%

2

allow folder names

KDFileAllowFolders%

4

folder names only

KDFileFoldersOnly%

8

disallow existing files

KDFileEditorDisallowExisting%

16

query existing files

KDFileEditorQueryExisting%

32

allow null string input

KDFileAllowNullStrings%

64

not S5 (don't display extension) file name, extensions are not significant

 

128

obey/allow wildcards

KDFileAllowWildCards%

256

to allow ROM files to be selected

KDFileSelectorWithRom%

512

to allow files in the System folder to be selected

KDFileSelectorWithSystem%

ER6 additionaly defines the following flags

1024

to allow new folders to be created from the dialog

KDFileSelectorAllowNewFolder%

2048

to allow hidden files to be selected

KDFileSelectorShowHidden%

The first of the list is the most important. Adding 1 into flags% will present a file edit box, as when creating a new file. If you do not add 1, a 'matching file' selector is presented, i.e. for choosing an existing file.

If performing a 'copy to' operation, you might use 1+2+16, to specify a file edit box for the target file, (in which you can type the name of a folder to copy to), and which will produce a query if you type the name of an existing file. If asking for the name of a folder to remove, you might use 4, to allow an existing folder name only. 'Query existing' is ignored if 'disallow existing' is set. These two, as well as 'allow null string input', only work with file edit boxes, not 'matching file' selectors.

The string variable to edit is file$. Its initial contents always control the initial drive and folder used. For a file edit box, any filename part of file$ is shown. For a 'matching file' selector, you can use wildcards in the filename part (such as *.tmp) to control which filenames are matched. To do this, you must add 128 to flags%. Adding 128 also allows wildcard specifications to be entered (returned in file$), for both 'matching' and 'new file' selectors. You can always press Tab to produce the full file selector with a dFILE item.  UIDs are used to identify files in the system for many purposes. The System screen uses Uid2 to distinguish between applications of various types and documents:

Uid3 is used by the System screen to identify particular applications.

For file selectors, dFILE supports file restriction by UID, or by type from the user’s point of view. Documents are identified by three UIDs which identify which application created the document and what kind of file it is. Specifying all three UIDs will restrict the files as much as is possible, and specifying fewer will provide less restriction. You can supply 0 for uid1 and uid2 if you only want to restrict the list to uid3 . This may be useful when dealing with documents from one of your own applications: you can easily find out the third UID as it will be the UID you specified in the APP statement. Note that UIDs are ignored for file name editors.

Here are some OPL-related UID constants:

OPL constant

value

KuidOPLInterpreter

268435816

KuidOPLApp

268435572

KuidOPLDoc

268435573

KuidOPO

268435571

KuidOPLFile

268435594

KuidOpxDll

268435549

To do: check the UID’s for ER6

For example, if the application is UID KUidMyApp , then the following will list only application-specific documents:

dFILE file$,prompt$,flags%,0,KUidOplDoc ,KUidMyApp

See also dEDIT.


dCHOICE

dCHOICE var choice%,prompt$,list$
dCHOICE var choice%,prompt$,list$+”,...”
dCHOICE var choice%,prompt$,list$,incremental% - ER6
dCHOICE var choice%,prompt$,list$+”,...”,incremental% – ER6

Define a choice list to go in a dialog.

The prompt, prompt$, will be displayed on the left side of the line. The string list$ should contain the possible choices, separated by commas, for example:

Yes,No

One of these will be displayed on the right side of the line, and the LEFT and RIGHT arrow keys can be used to move between the choices. The choice% parameter must be a LOCAL or a GLOBAL variable. It specifies which choice should initially be shown: 1 for the first choice, 2 for the second choice, and so on. When you finish using the dialog, choice% is given a value indicating which choice was selected - again, 1 for the first choice, and so on.

dCHOICE supports an unrestricted number of items (up to memory limits).

To extend a dCHOICE list, add a comma after the last item on the line followed by “...” (three full-stops), as shown in the usage above. choice% must be the same on all the lines, otherwise an error is raised.

For example, the following specifies items i1, i2, i3, i4, i5, i6:

dCHOICE ch%,prompt$, i1,i2,...
dCHOICE ch%, , i3,i4,...
dCHOICE ch%, , i5,i6

On ER6 dCHOICE supports an optional 4th short-integer parameter. This parameter is used to tell the choice list to turn incremental matching on or not. If the parameter is not specified or if KFalse% is specified the ‘traditional’ choice list will be built. If KTrue% is specified then the user will be able to locate items in the choice list by entering characters (e.g. entering “T” would take you to the first item beginning with “T”, then entering “e” would take you to the closest item beginning with “Te” and so on).


dFLOAT

dFLOAT var float,prompt$,min,max

Define an edit box for a floating-point number, to go in a dialog.

The prompt, prompt$, will be displayed on the left side of the line. The min and max parameters give the minimum and maximum values that are to be allowed. An error is raised if min is higher than max. The floating-point variable float must be a LOCAL or a GLOBAL variable. It specifies the value to be shown initially. When you finish using the dialog, the value you entered is returned in float.


dLONG

dLONG var long ,prompt$,min ,max

Defines an edit box for a long integer, to go in a dialog.

The prompt prompt$ will be displayed on the left side of the line.  The min and max parameters give the minimum and maximum values which are to be allowed. An error is raised if min is higher than max .

The variable long must be a LOCAL or a GLOBAL variable. It specifies the value to be shown initially. When the user finishes using the dialog, the value they entered is returned in long .


dDATE

dDATE var disdays ,prompt$,mindays ,maxdays

Define an edit box for a date, to go in a dialog.

The prompt, prompt$, will be displayed on the left side of the line. The LOCAL or a GLOBAL variable, disdays , specifies the date to be shown initially. Although it will appear on the screen like a normal date, for example 15/03/92 , disdays must be specified as days since 1/1/1900 . The mindays and maxdays parameters specify the minimum and maximum values which are to be allowed. Again, these are in days since 1/1/1900. An error is raised if mindays is higher than maxdays . When the user has finished using the dialog, the date entered is returned in disdays , in days since 1/1/1900. The system setting determines whether years, months or days are displayed first.

Note:

The day number of 1 January 1970 is 25567. This is required when converting from a dialog date to a system date/time, e.g.:

system_time = (dialog_date-25567)*86400+(seconds_from_start_of_day)

If you're collecting a date/time from a dialog, it's a good idea to set the minimum input date to this (25567) figure. Use DAYSTODATE which converts a number of days since 1/1/1900, to the corresponding date.

See also DAYS, SECSTODATE, DATETOSECS, DAYSTODATE.


dTIME

dTIME var disecs ,prompt$,type%,minsecs ,maxsecs

Define an edit box for a time, to go in a dialog.

The prompt, (prompt$), will be displayed on the left side of the line.

The disecs parameter, which must be a LOCAL or a GLOBAL variable, specifies the time to be shown initially. Although it will appear on the screen like a normal time, for example 18:27, the value of disecs must be specified as seconds after 00:00. A value of 60 means one minute past midnight; 3600 means one o'clock, and so on.  The minsecs and maxsecs parameters give the minimum and maximum values which are to be allowed. Again, these are in seconds after 00:00. An error is raised if minsecs is higher than maxsecs .

When the user has finished using the dialog, the time that they entered is returned in disecs , in seconds after 00:00.

The type% parameter specifies the type of display required, as follows:

type%

time display

OPL constant

0

absolute time, no seconds

KDTimeAbsNoSecs%

1

absolute time with seconds

KDTimeWithSeconds%

2

duration, no seconds

KDTimeDuration%

3

duration with seconds

KDTimeDurationWithSecs%

4

time displayed without hours

KDTimeNoHours%

8

time displayed in 24 hour format

KDTime24Hour%

For example, 03:45 represents an absolute time while 3 hours 45 minutes represents a duration. Absolute times always display am or pm as appropriate, unless 24 hour clock is specified. Duration’s never display am or pm. Note, however, that if you use the type% KDTimeNoHours% then the am/pm symbol will be displayed and the type% KDTimeDuration% must be ORed in if you wish to hide it.

See also dDATE.


dBUTTONS

dBUTTONS prompt1$,keycode1%,…
dBUTTONS prompt1$,keycode1%,prompt2$,keycode2%,…

Define exit keys to go at the bottom of a dialog (ER5) or on the CBA (ER6)

One or more exit keys may be defined. Each pair of prompt$ and keycode% specifies an exit key; prompt$ being the text to be displayed above it, while keycode% is the key code of the key.

The DIALOG function returns the key code of the key pressed (in lower case for letters).  For alphabetic keys, use the % sign: %A means the code of A ', and so on. The shortcut key is then Ctrl+alphabetic key. If you use the code for keys such as Tab or Enter, its name (e.g. 'Tab', or 'Enter') will be shown in the picture of the key.

The following effects may be obtained by adding the appropriate constants to the shortcut key key-code:

constant

effect

OPL identifier

256

display a button with no shortcut key label underneath it

KDButtonNoLabel%

512

use the key alone (without the Ctrl modification) as the shortcut key

KDButtonPlainKey%

These constants have no meaning on ER6. See the note on the usage of dBUTTONS on ER6 below.

If you use a negative value for a keycode% argument, that key is a 'Cancel' key. The corresponding positive value is used for the key to display and the value for DIALOG to return, but if you do press this key to exit, the var variables used in commands like dEDIT, dTIME, etc. will not be set. When using a negative shortcut to specify the cancel button, you must negate the shortcut together with any added flags.  The Esc key will always cancel a dialog box, with DIALOG returning 0. If you want to show the Esc key as one of the exit keys, use -27 as the keycode% argument (its key code is 27) so that the var variables will not be set if Esc is pressed.  The dBUTTONS item must be the last dialog command you use before DIALOG itself.

On ER5 the buttons take up two lines on the screen. The dBUTTONS item may be used anywhere between dINIT and DIALOG; where it is used will not affect the position of the buttons in the dialog.

Some key presses cannot be specified.

This example presents a simple query, returning TRUE for Yes, or FALSE for No.

PROC query:
  dINIT
  dTEXT , FORGET CHANGES ,2
  dTEXT , Sure? ,$202
  dBUTTONS No ,%N, Yes ,%Y
  RETURN DIALOG=%y
ENDP

dButtons on ER6:

Under ER6 dialogs do not have a row of buttons added to them at either the bottom or side of the dialog itself as per ER5. Rather, the CBA becomes method for manipulating a buttons the dialog. The following important changes should be noted:

Examples:

The following will produce a CBA arrangement which has a ‘Change’ button at the top (underlined to indicate it is the default action) and a ‘Close’ button at the bottom. The ‘Change’ button comes from the dCHOICE and does not therefore appear in the dBUTTONS definition. The ‘Close’ button provided by the dBUTTONS is automatically moved to the bottom CBA position as described above.

dINIT
dCHOICE Ch%,”Do this”,”No,Yes”
dBUTTONS “Close”,KdBUTTONEnter%
LOCK ON :Dia%=DIALOG :LOCK OFF

Similar to the above example, the following code CBA arrangement which has a ‘Change’ button at the top and a ‘Cancel’ button at the bottom. The ‘Cancel’ is automatically moved to the bottom CBA position as described above.

dINIT
dCHOICE Ch%,”Do this”,”No,Yes”
dBUTTONS “Cancel”,KdBUTTONEsc%
LOCK ON :Dia%=DIALOG :LOCK OFF

The following will produce a CBA arrangement which has a blank top button (dTEXT does not make use of the top CBA button in the same way, for example, dCHOICE does), a ‘Test’ second CBA button, a blank third CBA button and a ‘Cancel’ bottom CBA button:

dINIT
dTEXT “”,”A line of text”,KdTEXTCenter%
dBUTTONS KdBUTTONBlank$,KdBUTTONBlank%,“Test”,KdBUTTONTab%,KdBUTTONBlank$, KdBUTTONBlank%,“Cancel”,KdBUTTONEsc%
LOCK ON :Dia%=DIALOG :LOCK OFF

The following will produce the same CBA arrangement as above (illustrating how supplied captions for blank buttons are ignored):

dINIT
dTEXT “”,”A line of text”,KdTEXTCenter%
dBUTTONS “Button!”,KdBUTTONBlank%,“Test”,KdBUTTONTab%,”Another!”, KdBUTTONBlank%,“Cancel”,KdBUTTONEsc%
LOCK ON :Dia%=DIALOG :LOCK OFF

See also ALERT.


dCHECKBOX,ER5

dCHECKBOX chk%,prompt$

Creates a dialog checkbox entry with two states i.e. the tick is either on or off. The state of the checkbox is maintained across calls to the dialog. Initially you should set the live variable chk% to 0 to set the tick symbol off and to any other value to set it on. chk% is then automatically set to 0 if the box is unchecked or -1 if it is checked when the dialog is closed.

Note (ER6):

Crystal does not make use of checkboxes anywhere in its user interface. The dCHECKBOX command was therefore removed from ER6 OPL to prevent incompatibilities. Developers who previously made use of dCHECKBOX are advised to do what other ER6 applications have done and use a No/Yes choice list. This can be achieved using dCHOICE.

Example workaround

Previously:

dCHECKBOX Flag%,”Do this option”

Would become:

dCHOICE Flag%,”Do this option”,”No,Yes”

Depending on how you handled the Flag% variable previously, it may also be necessary to add some extra code-checking on the result of dialogs, which allow Flag% to be altered. For example, if KTrue% or KFalse% are the only values you expect for Flag% in other parts of your application you may like to do:

Flag%= KNoYesChoiceNo%
IF Flag%=KTrue%
  Flag%= KNoYesChoiceYes%
ENDIF

before the dialog is displayed, and similarly:

IF Flag%=KNoYesChoiceNo%
  Flag%=KFalse%
ELSE
  Flag%=KTrue%
ENDIF

after the dialog has been confirmed.

 

See also dINIT.


DIALOG

n% = DIALOG

Present the dialog prepared by dINIT and commands such as dTEXT and dCHOICE.

If the user completes the dialog by pressing Enter, the settings are stored in the variables specified in dTEXT, dCHOICE, etc., although the developer can prevent this with dBUTTONS.

If dBUTTONS was used when preparing the dialog, the key code that ended the dialog is returned. Otherwise, DIALOG returns the line number of the item that was current when Enter was pressed. The top item (or the title line, if present), has line number 1.  If the user cancels the dialog by pressing Esc, the variables are not changed, and 0 is returned (OPL constant KDlgCancel%).


ALERT

ret% = ALERT(msg1$)
ret% = ALERT(msg1$,msg2$)
ret% = ALERT(msg1$,msg2$,caption1$)
ret% = ALERT(msg1$,msg2$,caption1$,caption2$)
ret% = ALERT(msg1$,msg2$,caption1$,caption2$,caption3$)

Present an alert, (a simple dialog), with the messages and key captions specified, and wait for a response. The message to be displayed on the first line is msg1%. The message to be displayed on the second line is msg2%. If this is not supplied or is a null string then the second message line is left blank. Up to three keys may be used out of Esc, Enter and Space:

The strings to be displayed on screen over the key legends are:

caption1$

Esc

caption2$

Enter

caption3$

Space

If no key captions are supplied then the word CONTINUE is used above an Esc key legend.

The key return values are:

key press

return value

OPL identifier

esc

1

KAlertEsc%

enter

2

KAlertEnter%

space

3

KAlertSpace%

See also BUSY, dBUTTONS and GIPRINT.


Screen messages

BUSY

Display busy message in a screen corner

GIPRINT

Display general information text for ~2 seconds in a screen corner


BUSY

BUSY message$
BUSY message$,c%
BUSY message$,c%,delay%
BUSY OFF

Display or cancel a 'Busy' message in a corner of the screen.  This is used to indicate to the user periods when an OPL program is going to be temporarily unresponsive to key presses. To display a message in the bottom left of the screen use BUSY message$. To cancel the message use BUSY OFF.  The string to display, message$, may be up to 80 characters long (KBusyMaxText% = 80). Only one message can be displayed at a time.

If c% is given, it controls the corner in which the message appears:

c%

corner

OPL constant

0

top left

KBusyTopLeft%

1

bottom left

KbusyBottomLeft%

2

top right

KBusyTopRight%

3

bottom right (default)

KBusyBottomRight%

A delay time (in half seconds) before the message is displayed, can be specified using delay%. This may be used to prevent 'Busy' messages from continually appearing very briefly on the screen.

See also GIPRINT.


GIPRINT

GIPRINT string$
GIPRINT string$,c%

Display an general information message (string$) for about two seconds, in the bottom right (or other specified) corner of the screen. For example:

GIPRINT Not found

displays:

Not found

The string specified (string$) can be up to 64 characters. If a string is too long for the screen, it will be clipped. Only one message can be shown at a time. The message can be cleared - for example, when a key is pressed - with GIPRINT . GIPRINT is not affected by the text mode set using gTMODE.

If c% is given, it controls the corner in which the message appears:

c%

corner

OPL constant

0

top left

KbusyTopLeft%

1

bottom left

KbusyBottomLeft%

2

top right

KbusyTopRight%

3

bottom right (default)

KbusyBottomRight%

See also BUSY, ALERT.


Context sensitive help (ER6)

SETHELPUID

Set the UID of the help file to display

SETHELP

Set the current help topic

SHOWHELP

Show the Help application

ER6 supports the concept of context-sensitive help provided by a dedicated Help application. OPL for ER6 also provides an interface to this. Further details of how to construct Help files compatible with the Help Viewer can be found in the OPL SDK. From an OPL point of view the following is important to note:


SETHELPUID, ER6

SETHELPUID Uid

In ER6 help files are identified by UID. The SETHELPUID keyword can be used to set the UID of the Help file you wish to display.

To set the UID of your Help file so the Help Viewer application knows which file to display (this assumes the Help file has the same UID as your application), you could use:

SETHELPUID KApplicationUid

See also SETHELP, SHOWHELP.


SETHELP, ER6

SETHELP mode%,topic%

Sets the current help topic. This associates a topic with a section of OPL code.

The mode% parameter allows you to associate a help topic with the current view/state of an application, a specific dialog or a specific menu. There are CONSTs to correspond to each of these “modes” defined in CONST.OPH.

To show the help for the current view/state of your application (in the main event-handler):

IF (Key =KKeyHelp32 ) AND (Mods =0)
  IF View%=KMainView%
    SETHELP KHelpView%,KMyHelpMainView$
  ELSEIF View%=KOtherView%
    SETHELP KHelpView%,KMyHelpOtherView$
  ELSE
    SETHELP KHelpView%,KMyHelpQuickStart$  
  ENDIF
  SHOWHELP
ENDIF

To ensure that a given topic is displayed if the Help key is pressed while a dialog is on display (you cannot ‘trap’ the key itself while the dialog is on show - OPL does this for you):

SETHELP KHelpDialog%,KMyHelpSettingsDialog$
dINIT “Settings”
..other dialog controls, etc. as normal..
Dia%=DIALOG

To ensure that a given topic is displayed if the Help key is pressed while a menu is on display (again, OPL will ‘trap’ the key for you):

SETHELP KHelpMenu%,KMyHelpMainMenu$
mINIT
mCARD “File”,..etc....other menu controls, etc. as normal..
Menu =MENU(LastMenuValue%)

See also SETHELPUID, SHOWHELP


SHOWHELP, ER6

SHOWHELP

Open the Help application showing the topic set with SETHELP from the file set with SETHELPUID.

See also SETHELP, SETHELPUID.


OPL applications (OPAs)

APP

Start an OPA definition; code that follows defines an OPA

CAPTION

Define the name of an application for specific languages

FLAGS

Define a file or non file based application

ICON

Define name of bitmap file containing the icon for an OPA

ENDA

End an OPA definition; code that precedes defines an OPA

CMD$

Get command-line information, usually on start up

GETCMD$

Return new command line arguments to a running OPA

SETDOC

Set a file as a document and update system screen task list,

GETDOC$

Returns the name of the current application document

LOCK

Lock/unlock an OPA


APP

APP pname,uid

Begins the definition of an application (OPA).

The public name of the OPA, as used by the system screen, is given by pname. Note that the pname string does not have surrounding quote marks and may be up to 250 characters.  The name supplied in pname is the applications’ name in its default language – see the keyword CAPTION for other languages.

The APP command must be used in conjunction with ENDA for example:

APP pname,uid
  ...
ENDA

uid is the application’s unique identifier or UID. For distributed applications, official reserved UIDs must be used. These can be obtained by contacting Symbian at uid@symbiandevnet.com.

The APP line may be followed by the keywords ICON and FLAGS. The arguments to any of the keywords between APP and ENDA must be constants and not expressions. All information included in the APP…ENDA structure will be used to generate an AIF file that specifies the applications caption (possibly in various languages), its icons for use on the System screen and its setting of FLAGS.

See CAPTION, ICON, FLAGS.


CAPTION

CAPTION pname$,language%

Specifies an OPA’s public name (or caption) for a particular language, which will appear below its icon on the Extras bar and in the list of ‘Programs’ in the ‘New File’ dialog (assuming the setting of FLAGS allows these) when the language is that used by the machine. CAPTION statements may only be used inside an APP...ENDA construct.  The language code specifies the language variant of each pname$, so that the application name need not be changed when used on a different language machine. If used, CAPTION causes the default name given in the APP declaration to be discarded. Therefore CAPTION statements must be supplied for every language variant, including the language of the machine on which the application is originally developed. The maximum length of pname$ is 255 characters. However, a name longer than about 8 characters will not fit neatly below the application’s icon on the Extras bar.

See APP.


FLAGS

FLAGS flags%

Constants for flags are supplied in CONST.OPH; possible values for flags% are:

flags% = 1 for applications that can create files. Your application will then be included in the list of applications offered when the user creates a new file from the System screen.

flags% = 2 to prevent the application from appearing in the Extras bar. It is not usual to set flags% to this value.

This can only be used between APP and ENDA.


ICON

ICON name$

Give the name of the bitmap file to use as the icon for an OPA.  This can only be used between APP and ENDA.

Name$ is a multi-bitmap file (.MBM) that contains up to three bitmap/mask pairs for ER5 and two bitmap/mask pairs for ER6.


ENDA

ENDA

End of an OPA clause – see APP.


CMD$

command$ = CMD$(x%)

Return the command-line arguments passed when starting a program.  Null strings may be returned. The x% parameter should be from 1 to 3. The argument CMD$(2) is only for OPAs (OPL applications).

The argument returned by CMD$(1), is the full path name used to start the running program. This will usually be the full path name of the image file used to run the OPL process. The second argument, returned by CMD$(2), is the full path name of the file to be used by an OPA.

The third argument, returned by CMD$(3), may be 'C' for Create file or 'O' for Open file . If the OPA is being run with a new filename, this will be 'C'. This happens when the OPA is run for the first time and whenever a new filename is used to run it. Otherwise the OPA is being run with the name of an existing file, and CMD$(3) will return 'O'.  ‘R’ is returned if the application has been run from the Program editor or has been selected via the ‘Extras bar’, and not by the selection or creation of one the applications’ documents from the system screen. If the CMD$(3)=’R’, a default filename, including path, is passed in CMD$(2).

Note (ER6):

This change is not specific to OPL but applies to all applications launched from the Extras bar or other Application Groups such as Internet and Office under ER6. When an application was launched from Extras on ER5, the letter ‘R’ was passed as the value of CMD$(3). The standard behaviour when your application was launched in this fashion was to try and open the last used document. If that that did not exist or could not be opened for some reason a new document with a default name would be created in the default folder - this was normally passed in CMD$(2).

Under ER6, applications launched from Extras will receive the letter ‘C’ for Create as the value of CMD$(3). The standard behaviour for document based applications under Crystal is to create a new, empty document each time the application is run from Extras.

When documents of your application are launched from other applications (such as File Manager) the command line parameters of ‘Open’ will be used. For this reason it is still essential for document based applications that you properly check the CMD$() variables and act accordingly depending on what has been passed to your application.

To mimic the standard Crystal document-based applications it is advised that you do something along these lines:

See also the GETCMD$ function.


GETCMD$

arg$ = GETCMD$

Returns new command-line arguments to a running OPA, after a “change files” or “shut down” event have occurred.

The first character has the following meaning:

C

Close down the current file, and create the specified new file.

O

Close down the current file, and open the specified existing file.

X

Close down the current file (if any) and quit the OPA.

U

Letter unknown

F

Application brought the the foreground (ER6 only)

If it is C or O , the rest of the string is a filename. You can only call GETCMD$ once for each system message.

See also CMD$, GETEVENT, TESTEVENT.


SETDOC

SETDOC file$

Sets the file file$ to be a document. This command should be called immediately before the creation of file$ if it is to be recognised as a document. SETDOC may be used with the commands CREATE, gSAVEBIT and IOOPEN.

The string passed to SETDOC must be identical to the name passed to the following CREATE or gSAVEBIT otherwise a non-document file will be created - see note below.

Example of document creation:

SETDOC “myfile”
CREATE “myfile”,a,a$,b$

SETDOC should also be called after successfully opening a document to allow the System screen to display the correct document name in its task list.

In case of failure in creating or opening the required file, you should take the following action:

Database documents, created using CREATE, and multi-bitmap documents, created using gSAVEBIT, will automatically contain your application UID in the file header. For binary and text file documents created using IOOPEN and LOPEN, it is the programmer’s responsibility to save the appropriate header in the file.

Warning (ER5):

On ER5 using SETDOC “” (i.e. SETDOC with an empty string) will cause a USER-21 panic. A workaround is to use a space (i.e. SETDOC “ ”) instead.

Note:

To ensure the application's UID is incorporated into the document header, you are strongly advised to use the PARSE$ function on the file name before using it with the SETDOC and subsequent CREATE commands.


GETDOC$

doc$=GETDOC$

Returns the name of the current application document.

See also SETDOC.


LOCK

LOCK ON
LOCK OFF

Mark an OPA or OPO program as locked or unlocked.

When an OPA is locked with LOCK ON, the System screen will not send it events to change files or shut down. If you move to the task list or the document name in the system screen try to stop the OPA by using the ‘Close file’ button or Ctrl+E respectively, a message appears indicating that the program is busy.  You should use LOCK ON if your OPA uses a command that waits for a user response - e.g. EDIT, DIALOG, GET, or ALERT. When one of these commands is waiting, the OPA can't respond to System Screen messages, so use LOCK ON to make sure you don't get any. You might also use it when the OPA is about to go busy for a considerable length of time, or at any other point where a clean exit is not possible. Use LOCK OFF as soon as possible afterwards.

Don't use LOCK ON before a call to GETEVENT.

'Foreground', 'Background' and 'Machine on' events may still occur while the OPA is accessing the keyboard, and will be discarded.

An OPA or OPO program is initially unlocked.


Event handling

TESTEVENT

Test whether an event has occurred

GETEVENT

Wait until an event occurs and return event information

GETEVENT32

Wait until an event occurs and return event information

GETEVENTA32

Asynchronous version of GETEVENT32

GETEVENTC

Cancel previous call to GETEVENTA32

POINTERFILTER

Selectively filters pointer type events

Important note:

You should always use GETEVENT32 rather than using GETEVENT. All events are sensed by GETEVENT, but it cannot supply the pointer event information and is supported only for backward compatibility.

Date change events are not detected.


TESTEVENT

t% = TESTEVENT

Test whether an event has occurred. Returns -1 (true) if an event has occurred, otherwise returns 0 (false).

Note:

Use TESTEVENT with caution; for example, placing it inside loops can prevent a machine from switching off, and may lead to very high power consumption. Events are detected but not read by TESTEVENT - use functions such as GETEVENT or GETEVENT32 to read them.


GETEVENT

GETEVENT var ev%()

Waits for an event to occur. Returns with ev%() specifying the event.  The array ev%() (or string of integers) must be at least 6 integers long. Although only two elements of ev%() are currently used, the other four are reserved for future expansion.  The GETEVENT command passes control to the operating system, which waits for an event to occur. When it gets one, it puts the details into ev%() and returns control to the application. The data returned in ev%() depends on the type of event that occurred.

There are two classes of events: keypress events and system events. On a keypress event,

ev%(1) contains the key code. Modifier keys and auto-repeat count are returned in ev%(2). On a system event (foreground, background, switch-on, change files, exit, or date change), ev%(1) contains a code specifying the event.

If the event is a keypress, the expression:

(ev%(1) AND $400)

is guaranteed to be zero. For any other events this expression is guaranteed to be non-zero.

If a key has been pressed, the values in ev%() are:

ev%(1)

key code (as for GET)

ev%(2) AND $00ff

modifier (as for KMOD)

ev%(2)/256

auto-repeat count (ignored by GET)

You can't use KMOD after GETEVENT to find out what the keypress modifiers were, because GETEVENT returns the modifier in the array passed to it and doesn't store the value for later retrieval using KMOD.

The table below gives the actual value of array item ev%(1) after a system event.

event description

value in ev%(1)

Application has moved to foreground

$401

Application has moved to background

$402

The machine has switched on

$403

If the system wants an OPA to change files or exit (use GETCMD$ to determine which)

$404

Future versions of OPL may add other event numbers, so you should not raise an error if the event number is not one of the currently known ones, but should ignore that unknown type of event.

Note:

If a non-key event such as 'foreground' occurs while a keyboard keyword such as GET, GET$, EDIT, INPUT, MENU or DIALOG is being used, the event is discarded. So GETEVENT must be used exclusively if both key and non-key events need to be monitored. If you need to use the above keywords in OPAs, use LOCK ON / LOCK OFF around them. See the LOCK command for more details.

See also TESTEVENT, GETEVENT32, GETCMD$.


GETEVENT32

GETEVENT32 var ev ()

Waits for and returns all event types, including pointer (pen) events.  Returns with ev () specifying the event, ev () must have at least 16 elements. All events return a 32-bit time-stamp. GETEVENT32 returns more information than GETEVENT, as listed below:

If a key has been pressed: (ev (1) AND 400)=0

ev (1)

key code

ev (2)

time stamp

ev (3)

scan code

ev (4)

modifier e.g. Shift, see below

ev (5)

Repeat

Unlike the key repeat for GETEVENT, the repeat for GETEVENT32 is strictly that, i.e. if there is only one keypress, then the repeat value in ev (5) = 0.

For all the other event types, ev (1) is greater than 400:

event description

ev (1)

ev (2)

application to foreground

$401

time stamp

application to background

$402

time stamp

machine has switched on

$403

time stamp

application to change files or exit

$404

time stamp

By default the machine switch on event is not enabled, the appropriate flag should be set to enable it - see SETFLAGS. If the change files / exit event is received, GETCMD$ should be called to find out what action should be taken.

If a key is pressed down: ev (1)= 406

ev (2)

time stamp

ev (3)

scan code

ev (4)

modifiers e.g. Shift, see below

If a key is released: ev (1)= 407

ev (2)

time stamp

ev (3)

scan code

ev (4)

modifiers e.g. Shift, see below

If a pen event occurs: ev (1)= 408

ev (2)

time-stamp

ev (3)

window ID, as returned by the gCREATE keyword.

ev (4)

pointer type, 0 = pen down, 1 = pen up, 6 = pen drag

ev (5)

modifiers e.g. Shift, see below

ev (6)

x-co-ordinate

ev (7)

y-co-ordinate

ev (8)

x-co-ordinate relative to parent window

ev (9)

y-co-ordinate relative to parent window

If a pen enters contact with the screen: ev (1)= 409

ev (2)

time stamp

ev (3)

window ID

If a pen exits contact with the screen: ev (1)= 40A

ev (2)

time stamp

ev (3)

window ID

Modifiers, in ev (4) for key presses and in ev (5) for pointer (pen) events, have values as follows:

modifier

value

OPL constant

shift

2

KKmodShift%

control

4

KKmodControl%

caps

16

KKmodCaps%

fn

32

KKmodFn%

Each even type has an OPL constant that may be used to make your code more readable, their names are as follows.

OPL event type

constant value

KEvNotKeyMask

400

KEvFocusGained

401

KEvFocusLost

402

KEvSwitchOn

403

KEvCommand

404

KEvDateChanged

405

KEvKeyDown

406

KEvKeyUp

407

KEvPtr

408

KEvPtrEnter

409

KEvPtrExit

40A

Notes:

Some events; such as pointer events, pointer enters and pointer exits, can be filtered out to avoid being swamped by unwanted event types. See POINTERFILTER.  For other unknown events, ev (1) contains 1400 added to the code returned by the window server. ev (2) is the timestamp and ev (3)is the window ID, and the rest of the data returned by the window server is put into ev (4), ev (5), etc.

If a non-key event such as 'foreground' occurs while an entry keyword such as GET, GET$, EDIT, INPUT, MENU or DIALOG is being used, the event is discarded. So GETEVENT32 must be used exclusively if both key and non-key events need to be monitored. If you need to use the above keywords in OPAs, use LOCK ON/OFF around them so that the System screen won’t send messages to switch files or shutdown while the application cannot respond. See the LOCK command for more details.

See also GETEVENT, GETEVENTA32, GETCMD$.


GETEVENTA32

GETEVENTA32 var status%,var ev ()

Asynchronous version of GETEVENT32, returns the same information to the array ev () as GETEVENT32.

See also GETEVENTC, GETEVENT32, GETEVENT.


GETEVENTC

GETEVENTC(var stat%)

Cancels a previous call to the GETEVENTA32 function, with status stat%. Note that GETEVENTC consumes the signal (unlike IOCANCEL), so IOWAITSTAT should not be used after GETEVENTC.


POINTERFILTER

POINTERFILTER filter%,mask%

Allow filtering of pointer events in the current window.

Some events; such as pointer events, pointer screen enter and pointer screen exit, can be filtered in or out to avoid being swamped by unwanted event types. By default pointer events are not filtered out. Add the following values together to achieve the desired filter% and mask%:

pointer event

value

none

0

enter/exit

1

drag

4

The bits set in filter% specify the settings to be used, 1 to filter out the event and 0 to remove the filter. Only those bits set in mask% will be used for filtering. This allows the current setting of a particular bit to be left unchanged if that bit is zero in the mask. (i.e. mask% dictates what to change and filter% specifies the setting to which it should be changed). For example,

mask%=5 REM =1+4 - allows enter/exit and drag settings to be changed
POINTERFILTER 1,mask% REM filters out enter/exit, but not dragging
...
POINTERFILTER 4,mask% REM filters out drag and reinstates enter/exit

See also GETEVENT32, GETEVENTA32.


I/O operations on files and devices

IOOPEN

Open any type of file or device

IOREAD

Read from a file or device opened with IOOPEN

IOWRITE

Write to a file or device opened with IOOPEN

IOCLOSE

Close a file opened with IOOPEN

IOSEEK

Position within a file opened with IOOPEN

IOA

Perform an asynchronous I/O operation

IOC

Perform an asynchronous I/O operation with guaranteed completion

IOCANCEL

Cancel an asynchronous I/O function

IOYIELD

Allow I/O wait handlers to complete requests and update status words

IOWAIT

Wait for completion of any asynchronous operation by IOA or IOC

IOWAITSTAT

Wait for completion of a specific asynchronous operation by IOA or IOC

IOWAITSTAT32

Wait for completion of a specific asynchronous operation by IOA or IOC

IOSIGNAL

Signal completion of an I/O operation

IOW

Perform a synchronous I/O operation

KEYA

Perform an asynchronous keyboard read

KEYC

Cancel a KEYA

Notes:

In OPL, the I/O keywords provide the same access to files as in OPL16, but only the OPL16 device drivers “TIM:”, “TTY:A”, “CON:” and “FIL:” are emulated. A handle of -1 for the LOPENed device or -2 for “CON:” can be used as in OPL16.  In OPL IOYIELD must always be called before polling status words, i.e. before reading a 16-bit status word, if IOWAIT or IOWAITSTAT have not been used first. This is because OPL needs to set the 16-bit status word based on the value of the actual EPOC32 32-bit status word.


IOOPEN

r% = IOOPEN(var h%,name$,mode%)

Create or open a file, or open an I/O device driver called name$.

Returns the handle of the file or device in h%, for use by subsequent I/O function calls. mode% specifies how to open the file.

For creation of a file with a unique name, use IOOPEN(var h%,address%,mode%) where address% is the address of a string, specifying only the path of the file to be created. The string must be at least 130 characters long, to take the unique full file name specification. Typically used to create a temporary file that will later be renamed or deleted.

The mode in which the file is to be opened is specified by mode%, formed by ORing together values which fall into the three following categories: Open mode, file format and access flags.

Open mode – select one value only

$0000

Open an existing file (or device). The initial current position is set to the start of the file.

$0001

Create a file (which must not already exist).

$0002

Replace a file (truncate it to zero length) or create it if it does not exist.

$0003

Open an existing file for appending. The initial current position is set to the end of the file. For text format files (see $0020 below) this is the only way to position to end of file.

$0004

Creates a file with a unique name. For this case, you must use addr%, the address of a string at least 130 characters long, (the maximum file specification), instead of name$. This string specifies only the path of the file to be created (any filename in the string is ignored). IOOPEN then sets the string to the unique filename generated (including the full path).

File format – select one value only

$0000

Binary. Up to 16K can be read from or written to the file in a single operation.

$0020

Text. Lines are terminated by any combination of the CR and LF ($0D, $0A) characters. The maximum record length is 256 bytes and Ctrl-Z ($1A) marks the end of the file.

Access flags – select any combination of one values

$0100

Update flag - Allows the file to be written to as well as read. If not set, the file is opened for reading only. You must use this flag when creating or replacing a file.

$0200

Random access flag – the file is opened for random access (not sequential access), using the IOSEEK function.

$0400

Share flag - the file can still be opened by any process. If not specified, the file is locked and cannot be opened again by any process until either the owning process exits, or the file is closed with IOCLOSE. If the file is opened for writing ($0100 above), this flag is ignored, since sharing is then not feasible.

Note

On ER6 the text-mode variant of IOOPEN will create a Unicode text file by default and not an ASCII one as with ER5.

Unicode text files on Symbian OS conform to the Unicode standard of having the hex bytes 0xFEFF (or 0xFFEF depending on the endianness) written at the start of them. Text-mode IOOPEN now automatically writes these bytes for you.

The end-of-line delimiter for Unicode text files on Symbian OS is still the same as ASCII, i.e. CR LF . There are CONSTs provided for these in CONST.OPH.

Note, however, that you can force the text-mode variant of IOOPEN to output ASCII files. To do this, specify the new SETFLAGS value of KAlwaysWriteAsciiTextFiles .

See also IOCLOSE, SETFLAGS.


IOREAD

r% = IOREAD(h%,addr ,length%)

Read from the file with the handle h%.

The addr argument is the address of a buffer large enough to hold a maximum of length% bytes. The buffer could be an array or even a single integer as required. No more than 16K bytes can be read at a time. If the value returned to r% is negative it is an error value, otherwise it is the actual number of bytes read.

For text files

If length% exceeds the current record length, data only up to the end of the record is read into the buffer; no error is returned and the file position is set to the next record.  If a record is longer than length%, the error value 'Record too large' (-43) is returned. In this case the data read is valid but is truncated to length length%, and the file position is set to the next record.

A string array buffer$(255) can be used for the buffer. Pass the address UADD(ADDR(buffer$),1) to IOREAD. You can then POKEB the first byte of the string with the length (returned to r%) so that the string conforms to normal OPL string format.  In this case, maxLen% should be 255 because the record length can be 256. If a 'Record too large' error is returned, you must read the extra byte separately. (Often you will know that the record length in your file will be not be greater than 255, in which case you don't need to check for this error).

In ER6, the above described method will no longer work as expected, because the code incorrectly assumes the string contents are one byte beyond the string header. From ER6 onwards the string contents begin two bytes from the start:

CONST KOplAligment%=1
pBuf =ADDR(Buffer$)
Len%=IOREAD(Handle%, pBuf +1+KOplAlignment%, MaxBytes%)
...
POKE pBuf ,Len%

where an extra byte is added to the pointer buffer.

Reading and writing text files in ER6:

Reading and writing strings to and from text files is a little more complicated in ER6 than it was in ER5 due to the introduction of Unicode in ER6 systems.

The following test code illustrates writing text files with the new Unicode changes in ER6:

 

DECLARE EXTERNAL
EXTERNAL IOReadString$:(aHandle%)
EXTERNAL IOReadASCIIString$:(aHandle%,aExcludeCRLF%)
INCLUDE CONST.OPH
INCLUDE CONVERT.OXH

PROC Main:
LOCAL h%,String$(KMaxStringLen%),ret%
  PRINT Symbian OS V6.0 OPL Text File Tests. Copyright (c) Symbian Ltd 2002
  PRINT REPT$( - ,67)
  PRINT Writing a Unicode text file using LPRINT...
  LOPEN C:\Documents\OPL_U_LPRINT.txt
  LPRINT Test String
  LPRINT Another test String!
  LCLOSE
  PRINT Done.
  PRINT Writing a Unicode text file using IOOPEN...
  rem Update access, Text format, Replace file
  IOOPEN(h%, C:\Documents\OPL_U_IOWRITE.txt ,$0122)
  String$= Test String +CHR$(KCarriageReturn )
  IOWRITE(h%,ADDR(String$)+1+KOplAlignment%,LEN(String$))
  String$= Another test String! +CHR$(KCarriageReturn )
  IOWRITE(h%,ADDR(String$)+1+KOplAlignment%,LEN(String$))
  IOCLOSE(h%)
  PRINT Done.
  PRINT Unicode writing tests complete. Press any key to continue.
  GET

  SETFLAGS KAlwaysWriteASCIITextFiles
  PRINT
  PRINT Writing an ASCII text file using LPRINT...
  LOPEN C:\Documents\OPL_A_LPRINT.txt
  LPRINT Test String
  LPRINT Another test String!
  LCLOSE
  PRINT Done.
  PRINT Writing an ASCII text file using IOOPEN...
  rem Update access, Text format, Replace file
  IOOPEN(h%, C:\Documents\OPL_A_IOWRITE.txt ,$0122)
  String$= Test String +CHR$(KCarriageReturn )+CHR$(KLineFeed )
  IOWRITE(h%,ADDR(String$)+1+KOplAlignment%,LEN(String$))
String$= Another test String! +CHR$(KCarriageReturn )+CHR$(KLineFeed )
  IOWRITE(h%,ADDR(String$)+1+KOplAlignment%,LEN(String$))
  IOCLOSE(h%)
  PRINT Done.
  PRINT ASCII writing tests complete. Press any key to continue.
  CLEARFLAGS KAlwaysWriteASCIITextFiles
  GET
 
  PRINT
  PRINT Reading back from Unicode LPRINT file...
  IOOPEN(h%, C:\Documents\OPL_U_LPRINT.txt ,$0020)
  String$=IOReadString$:(h%)
  PRINT LEFT$(1) on first string read = ;LEFT$(String$,1) rem Check Unicode flags are not read
  PRINT String$
  PRINT IOReadString$:(h%)
  PRINT IOReadString$:(h%)
  PRINT Done. Press any key to continue.
  IOCLOSE(h%)
  GET

  PRINT Reading back from Unicode IOWRITE file...
  IOOPEN(h%, C:\Documents\OPL_U_IOWRITE.txt ,$0020)
  String$=IOReadString$:(h%)
  PRINT LEFT$(1) on first string read = ;LEFT$(String$,1) rem Check Unicode flags are not read
  PRINT String$
  PRINT IOReadString$:(h%)
  PRINT IOReadString$:(h%)
  PRINT Done. Press any key to continue.
  IOCLOSE(h%)
  GET

  PRINT
  PRINT Attempting to reading back from ASCII LPRINT file (in TEXT mode)...
  ret%=IOOPEN(h%, C:\Documents\OPL_A_LPRINT.txt ,$0020)
  IF ret% 0
    PRINT FAILED: ;ERR$(ret%)
    PRINT NOTE: This is INTENDED behaviour in v6.0! We should use binary mode instead.
  ELSE
    String$=IOReadString$:(h%)
    PRINT LEFT$(1) on first string read = ;LEFT$(String$,1) rem Check nicode flags are not read
    PRINT String$
    PRINT IOReadString$:(h%)
    PRINT IOReadString$:(h%)
  ENDIF
  PRINT Done. Press any key to continue.
  IOCLOSE(h%)
  GET

  PRINT
  PRINT Attempting to reading back from ASCII LPRINT file (in BINARY mode)...
  IOOPEN(h%, C:\Documents\OPL_A_LPRINT.txt ,$0000)
  DO
    String$=IOReadASCIIString$:(h%,KTrue%)
    PRINT String$
  UNTIL String$=
  PRINT Done. Press any key to continue.
  IOCLOSE(h%)
  GET

  PRINT
  PRINT Tests complete. Press any key to continue.
  GET
ENDP

PROC IOReadString$:(aHandle%)
LOCAL Ret%,String$(KMaxStringLen%)
  Ret%=IOREAD(aHandle%,ADDR(String$)+1+KOplAlignment%,KMaxStringLen%)
  IF Ret% 0
    RETURN
  ENDIF
  POKEB ADDR(String$),Ret%
  RETURN String$
ENDP

PROC IOReadASCIIString$:(aHandle%,aExcludeCRLF%)
LOCAL Ret%,String$(KMaxStringLen%),_Buffer ,NextChar$(1)
  _Buffer =ALLOC(1)
  IF _Buffer =0
    RETURN
  ENDIF
  DO
    Ret%=IOREAD(aHandle%,_Buffer ,1)
    IF Ret% =0
      NextChar$=CVUnicode$:(_Buffer ,1)
      IF (((NextChar$=CHR$(KLineFeed )) OR NextChar$=CHR$(KCarriageReturn ))) AND aExcludeCRLF%)
        rem Do nothing
      ELSE
        String$=String$+NextChar$
      ENDIF
    ENDIF
  UNTIL (NextChar$=CHR$(KLineFeed )) OR (Ret% 0)
  FREEALLOC _Buffer
  RETURN String$
ENDP

 

For binary files

If you request more bytes than are left in the file, the number of bytes actually read (even zero) will be less than the number requested.

So if r% length%, end of file has been reached. No error is returned by IOREAD in this case, but the next IOREAD would return the error value 'End of file' (-36).


IOWRITE

r% = IOWRITE(h%,addr ,length%)

Write length% bytes from a buffer at addr to the file or device driver with the handle h%.

When a file is opened as a binary file, the data written by IOWRITE overwrites data at the current position. When a file is opened as a text file, IOWRITE writes a single record. The closing CR/LF is automatically added.

Note (ER6):

See the IOREAD command for a detailed example on how to read and write text files in ER6.


IOCLOSE

r% = IOCLOSE(h%)

Close the file or device driver with the handle h%. Returns zero if successful, otherwise an error code is returned.

See also IOOPEN.


IOSEEK

r% = IOSEEK(h%,mode%,var offset )

Seek to a position in the file with handle h% that has been opened for random access. The mode% argument specifies how offset is to be used. The offset parameter may be positive to move forwards or negative to move backwards. The values you can use for mode% are:

mode%

effect

1

Set position in a binary file to the absolute value specified in offset , with 0 for the first byte in the file.

2

Set position in a binary file to offset bytes from the end of the file.

3

Set position in a binary file to offset bytes relative to the current position.

6

Rewind a text file to the first record. offset is ignored, but you must still pass it as a argument, for compatibility with the other cases.

IOSEEK sets the variable offset to the absolute position set.

Note:

If you are using # to pass the value of the offset rather than have OPL use its address:

r% = IOSEEK(h%,mode%,#offset )

i.e. pass the long integer #offset .

See also IOOPEN


IOA

r% = IOA(h%,func%,var status%,var arg1,var arg2)

Get the device driver opened with handle h% to perform the asynchronous I/O function func% with the two further arguments, arg1 and arg2 as specified in the driver documentation.

The argument status% is set by the device driver when the function completes or fails.

The usual setting of status% will be -46, which means that the function is still pending.  When, at some later time, the function completes, status% is automatically changed. For this reason, status% should usually be global - if the program is still running, status% must be available when the request completes, or the program will probably crash.  If status% =0, the function completed without error. If status% 0, the function completed with error. The error number is specific to the device driver. At the same time, a signal is sent to the running OPL program.

In most cases, you cannot perform another I/O read/write function to this device until you first read the signal of this function's completion.

An IOWAIT or IOWAITSTAT must be performed for each IOA. If this is the only I/O device with a function pending, wait for the signal with IOWAITSTAT status%. If you have other functions pending on other devices, you must use IOWAIT and IOSIGNAL.  Alternatively, you can cancel the pending function with IOW(h%,4). The program will still receive a signal, which should be read with IOWAITSTAT or IOWAIT.

If an OPL program is ready to exit, it does not have to wait for any signals from pending IOA calls.

Note:

Using IOC is more convenient than IOA.


IOC

r% = IOC(h%,func%,var status%,var arg1,var arg2)

Make an I/O request with guaranteed completion. Gets the device driver opened with handle h% to perform the asynchronous I/O function func% with the two further arguments, arg1 and arg2 as specified in the driver documentation.

The IOC function allows you to assume that the request started successfully. Since the return value is always zero it can be ignored. Any error is always given in the status word status%. The argument status% is set by the device driver, when the function completes or fails.

An IOWAIT or IOWAITSTAT must be performed for each IOC. If there was an error, status% contains the error code and the next IOWAIT will return immediately as if the error occurred after completion.

There is seldom a requirement to know whether an error occurred on starting a function, and IOC should therefore be used in preference to IOA.


IOCANCEL

r% = IOCANCEL(h%)

Cancel any outstanding asynchronous I/O requests (made with IOA or IOC) on the channel specified by h%, causing them to complete. Zero is always returned, and can therefore be ignored.

The completion status word contains -48 (meaning I/O cancelled ) after IOCANCEL has been called.

Device drivers that support truly asynchronous services provide a cancel service. The detailed effect of the cancel depends on the device driver. However, the following general principles apply:

See also IOA, IOC.


IOYIELD

IOYIELD

Ensure that any asynchronous I/O functions, queued using IOA or IOC, are given a chance to run and their status words are updated.

The IOYIELD command is logically equivalent to:

IOSIGNAL : IOWAIT.

which returns immediately, but causes any asynchronous handlers to run.  Some devices are unable to perform an asynchronous request if an OPL program becomes computationally intensive, using no I/O (screen, keyboard etc.) at all. In such cases, the OPL program should use IOYIELD before checking the status% variables passed to IOC or IOA.


IOWAIT

IOWAIT

Wait for any asynchronous I/O function to signal completion.

If you've got an IOA or IOC request pending, use IOWAIT to await its completion.

Signals are generated (and thus IOWAIT returns) when any pending I/O request finishes, so you'll need to check whether this signal was meant for you or not.  To do this, look at the value of the status% variable you passed to IOA or IOC. If the signal wasn't for you, you'll need to call IOWAIT again.

The best way to handle 'wrong numbers' or 'stray signals' is to have a loop, like this:

loop
  call IOWAIT
  check status%
  is the signal for me?
until the signal is for me

You must keep count of the 'wrong numbers' you receive, because IOWAIT intercepted those signals before they ever got to their waiting processes. When you have got your signal, you will need to generate a fresh signal with IOSIGNAL for each 'wrong number' you received. If you don't do this, you will interfere with other processes' I/O.  If you have no other functions pending on different I/O handles, use IOWAITSTAT or IOWAITSTAT32 instead.


IOWAITSTAT

IOWAITSTAT var status%

Wait for the specific asynchronous I/O function (called with IOA or IOC) with status word status%, to signal completion.


IOWAITSTAT32

IOWAITSTAT32 var status

Similar to IOWAITSTAT but takes a 32-bit status word. IOWAITSTAT32 should be called only when you need to wait for completion of a request made using a 32-bit status word when calling an asynchronous OPX procedure. status will be 80000001 (KStatusPending32 ) while the function is still pending, and on completion will be set to the appropriate EPOC32 error code. For a 16-bit status word the ‘pending value’ is -46 (KErrFilePending%).


IOSIGNAL

IOSIGNAL

Signal an I/O function's completion.

See also IOWAIT.


IOW

r% = IOW(h%,func%,var arg1,var arg2)

Perform the synchronous I/O function func% using the device driver opened with handle h%, the two further arguments, arg1 and arg2, are as specified for the particular device driver.


KEYA

error% = KEYA(var status%,var key%())

This is an asynchronous keyboard read function.

The array key%() must be declared with at least two elements.

When the function completes, key%(1) contains the character code of the key pressed.

The least significant byte of key%(2) takes the key modifier. The most significant byte of key%(2) takes the count of keys pressed (0 or 1). Thus key%(2) AND $FF is the modifier, using the same codes as KMOD (2 for Shift-, 4 for Control- and so on). If a key was pressed key%(2)*256 is 1, or else 0.

The KMOD function cannot be used with KEYA.

The KEYA function needs an IOWAIT in the same way as IOA.  The KEYA function is included in OPL because the handle of the keyboard driver is unknown to the casual programmer.

Note that

KEYA(status%,key%(1))

is almost equivalent to

IOA(-2,status%,key%(1),#0)

where -2 specifies the Console device driver (which handles the OPL keyboard). The only difference is that any key pressed to exit from PAUSE (when called with a negative argument) is used up by KEYA but not by the above IOA call.  Cancel with KEYC.


KEYC

error% = KEYC(var status%)

Cancel the previously called KEYA function with status word status%.  After cancelling the request, IOWAITSTAT status% must still be called to consume the signal.

Note that

KEYC

is equivalent to

IOW(-2,FCANCEL,#0,#0)

where -2 specifies the Console device driver (which handles the OPL keyboard) and FCANCEL = 4.