You can make an OPL program appear as an icon in the system screen, and behave like the other icons there, by converting it into an OPL application.
There are two settings for applications which are set using the FLAGS command:
Once created, OPL applications may be used in the same way as the built in applications: new document files may be created from the System screen using New File if the flag 1 is set and/or from the Extras bar if the flag 2 is not set. Existing files may be opened by selecting them on the System screen as usual. You can stop a running app by using the Task list.
To make an application, your OPL file should begin with the APP keyword, followed by a name for the app in the machines default language and its UID. The name may be up to 250 characters. (Note that it does not have quote marks.) If the CAPTION command is used, however, this default name will be discarded (see below).
The UID specifies the UID of the application. For applications that are to be distributed, UIDs are reserved by contacting Symbian. These official UIDs are guaranteed to be unique to the application and have values of &10000000 and above. To obtain a reserved UID you should contact Symbian in one of the following ways:
For applications developed for personal use there is no need to reserve official UIDs, and any UID between &01000000 and &0fffffff may be selected. However, if the UIDs of two different applications did clash, then either your applications documents will have the wrong icon and selecting these will run the other application, or the other applications documents will seem to belong to your application.
The APP line may be followed by any or all of the keywords CAPTION, ICON and FLAGS. Finally, use ENDA, and then the first procedure may begin as in a normal OPL file. Here is an example of how an app might start:
APP Expenses,&20000000 REM !!! Should be a reserved UID !!! FLAGS 1 ICON "icon.mbm" CAPTION "Expenses",1 REM English name CAPTION "Expenses",10 REM American name ENDA
Here is another example:
APP Picture,&30000000 REM !!! Should be a reserved UID !!! FLAGS 2 ICON "picicon.mbm" ENDA
FLAGS takes an integer argument of 1 or 2. The meanings of these are outlined above. If you dont specify the flags, none are set.
ICON gives the name of a multi-bitmap file (MBM), also known as an EPOC Picture file, which contains the icons for an OPL application. These icons are used on the Extras bar and for the applications documents on the System screen. The multi-bitmap file can contain up to three bitmaps of sizes 24
The different sizes of bitmaps are used for the different zoom levels in the System screen. The sizes are read from the MBM and the most suitable size is zoomed if the exact sizes required are not provided or if some are missing.
You can use ICON more than once within the APP...ENDA construct. The translator only insists that all icons are paired with a mask of the same size in the final ICON list. This allows you to use MBMs containing just one bitmap, as produced by the Sketch application. Icons may also be created on a PC (if the appropriate tools are available), or of course by another OPL program or application.
CAPTION specifies an applications public name (or caption) for a particular language, which is the name 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 that is the language used by the machine. This name is also used as the default document name for documents launched using the Extras bar. The maximum length of the caption is 255 characters. However, note that a caption no longer than around 8 letters will look best on the Extras bar. If any CAPTION statement is included in the APP…ENDA structure, then the default caption provided by the APP declaration will be discarded. Therefore as many statements of CAPTION as are necessary to cover all the languages required, including the language of the machine on which the application is originally developed, should be used. The constants for the language codes are supplied in Const.oph
. See Including header files.
Applications can declare themselves capable of handling files of a particular MIME content type. See OPL and MIME for more information on this.
On creation of an application, a folder specifically for the application is also created. For example, if the application has the name AppXxx
the folder created will be \System\Apps\AppXxx\
. The .app
file itself (the translated OPL module) and the application information file (AIF) which contains three icon and mask pairs and the application caption and flags, are created in this folder. For example, the AIF for AppXxx.app
would be \System\Apps\AppXxx\AppXxx.aif
. The AIF file will be generated based on all the information contained in the APP…ENDA construct, but if any information is missing defaults will be used. These are:
The arguments to any of the keywords between APP and ENDA must be constants and not expressions.
Once youve successfully translated the OPL file, the applications icon will automatically appear on the Extras bar and/or on the Program list in the New File dialog (as specified by the FLAGS setting). The new documents of the application may then be created and existing ones opened as with other EPOC applications.
The first thing a file-based application should do is to get the name of the file to use, and check whether it is meant to create it or open it. CMD$(2) returns the full name of the file to use; CMD$(3) returns C for Create, O for Open, R for Run or X for Exit.
All document-based apps should handle all of these cases; for example, if a Create fails because the file exists already, or an Open fails because it does not, OPL raises the error, and the application should take suitable action. Note however, that in general the System screen will not allow such events to occur and therefore they are unlikely to happen.
R means that your application has been run from the OPL Program editor or has been selected via the applications icon on the Extras bar, and not by the selection or creation of one of its documents from the system screen. A default filename, including path, is passed in CMD$(2). When R is passed, an application should always try to open the last-used document. This is the document that was in use when the application was last closed, not the document that was most recently opened. The name of this document should be stored in a .ini
file with the same name and in the same folder as your application but always on drive C:
. So for example, AppXxx.app
would have .ini
file C:\System\Apps\AppXxx\AppXxx.ini
. If the .ini
file does not exist or cannot be opened for any reason, or if the document listed there no longer exists, you should create the document named in CMD$(2). CMD$(2) is a default name provided by the System based on your applications caption. If the .ini
file is corrupt it should be deleted before going on to create CMD$(2). No error message should be displayed in this case.
Constants for the array indices of CMD$ and the return values of CMD$(3) are supplied in Const.oph
(see Including header files).
When the EPOC device wants an app to exit or to switch files, it sends it a System message, in the form of an event. For example, this would happen if the Close file option in the Task list were used to stop a running app.
TESTEVENT and GETEVENT32 (synchronous) and GETEVENTA32 (asynchronous) check for certain events, including both keypresses and System messages. All types of application must use these keywords to check for both keypresses and System messages; keyboard commands such as GET, KEY and KEYA cause other events to be discarded.
GETEVENT32 waits for an event whereas TESTEVENT simply checks whether an event has occurred without getting it. If TESTEVENT returns non-zero, an event has occurred, and can be read with GETEVENT32. However, it is recommended that you use either GETEVENT32 or GETEVENTA32 without TESTEVENT as the machine will switch off only when waiting on an event. If the program just runs around a loop using TESTEVENT to decide when there is something to do, it will simply consume the battery power for no purpose. GETEVENT32 may be used if you only wish to pick up window server events, but otherwise you should use the asynchronous GETEVENTA32 together with any other asynchronous requests which you require. TESTEVENT should generally only be used when polling while doing something else in background.
GETEVENT32 and GETEVENTA32 both take one argument: the name of a long integer array, for example, GETEVENT32 ev&(). The array should contain at least 16 long integers.
For example, if the event is a keypress (ev&(1) AND &400) = 0 and,
For non-key events (ev&(1) AND &400) will be non-zero. On the EPOC platforms with a pen, these include pointer events. For an application, it may be suitable to filter out certain pointer events. This may be done using the POINTERFILTER command. POINTERFILTER takes two arguments: a filter and a mask. Each of the bits in these two arguments represents a certain pointer event, allowing a flag to be set to say whether that event should be filtered out. The bits which are set in the mask specify bits in the filter which are to be used. Bits which are clear in the mask specify bits that are not to be used from the filter. This makes it possible to filter out some pointer events, filter back in some others and leave the settings of some alone all in one call to POINTERFILTER. To set or clear flags you would set and clear them in the filter and set all the flags that require changing in the mask. To leave some bits in the filter alone just dont set the bits in the mask. See the Keyword Reference for more details of POINTERFILTER and the values returned to ev&() by GETEVENT32 and GETEVENTA32.
If the event is a System message to change files or quit, ev&(1)=&404. You should then use GETCMD$ to find the action required.
GETCMD$ returns a string, whose first character is "C", "O" or "X".
You can only call GETCMD$ once for each event. You should do so as soon as possible after reading the event. Assign the value returned by GETCMD$ to a string variable so that you can extract its components.
If you have c$=GETCMD$, the first character, which you can extract with LEFT$(c$,1), has the following meaning:
Again with c$=GETCMD$, MID$(c$,2,255) is the easiest way to extract the filename.
Note that events are ignored while you are using keywords which pause the execution of the program GET, GET$, EDIT, INPUT, PAUSE, MENU and DIALOG. If you need to use these keywords, use LOCK ON / LOCK OFF (described later) around them to prevent the System screen from sending messages.
A well-behaved application should obey the following important guidelines:
Toolbar.opo
is supplied in the ROM and provides the set of procedures required for this support. See Toolbars.You can find out the full file specification of external files by using PARSE$. For example, in:
p$=PARSE$("NEW",LEFT$(CMD$(1),LEN(CMD$(1)-4),x%())
CMD$(1) gives the device and the path of the OPL application and the name of the file.
By default the system screen hides the System folder and its subfolders. Use the Preferences option in the Tools menu of the System screen and check the checkboxes for both Show hidden files and Show System folder to show all applications and their files.
It is possible to write your own Help for your own application, which should be created in the Data application. The file should be similar to the built-in help, using two labels only for each entry to give a title and the explanation itself. The file should be stored in the applications folder with the filename extension .hlp
. The procedure RunApp&: in System.opx
(see About OPXs for more details) may then be used to launch Data and open the application help file. For example, if you want to run a help file called Myapp.hlp
, the help file for your own application called Myapp
, you should use:
drv$=LEFT$(CMD$(1),2) RunApp&:("Data",drv$+"\System\Apps\Myapp\Myapp.hlp","",0)
You should make it possible for users of your application to launched your help file from the applications menus. Following the EPOC Style Guide, the Help item should appear on the Tools menu at the bottom of the section above Infrared, so it will be followed by a separating line. The shortcut key should be Ctrl+Shift+H.
Only one copy of the help file should be shown at a time, and the help file should be closed when the application exits. This can be done by creating a global variable called Help_Thread& in the programs main procedure, and by calling the Help: procedure below to display the help file:
PROC Help: IF EXIST(MyHelpFile$) IF Help_Thread&<>0 REM Is Data running? ONERR NoLongerOpen:: SetForegroundByThread&:(Help_Thread&,0) REM Switch Data to fore ELSE NoLongerOpen:: ONERR OFF Help_Thread&=RunApp&:("Data",MyHelpFile$,"",0) REM Start Data and record its thread ID. ENDIF ELSE GIPRINT "Help not found", KBusyTopRight% ENDIF ENDP
This Exit: procedure should then be called when your program shuts down (either when the user selects "Close" or Ctrl+E, or when it receives a message from the System to close, as for in example the case of a backup these different events should be trapped in your main event loop):
PROC Exit: ONERR HelpClosed:: IF Help_Thread&<>0 EndTask&:(Help_Thread&,0) ENDIF HelpClosed:: ONERR OFF STOP ENDP
Here is an application which just prints the keys you press. It is not a document-based application (like Calc, but unlike Word which is document-based) so it uses FLAGS 0. The keyboard procedure getk&: returns the key pressed, as with GET, but jumps to a procedure endit: if a System message to close down is received. (apps with flags set to 0 do not receive "change file" messages.)
CONST KUidAppMyApp0&=&40000000 REM !!! Should be a reserved UID!!! APP myapp0,KUidAppMyApp0& CAPTION "Get Key",1 ICON "myapp0.mbm" ENDA PROC start: GLOBAL a&(10),k& FONT 11,16 PRINT "Q to Quit" PRINT " or select Close file" PRINT " from the Task List" DO k&=getk&: PRINT CHR$(k&); UNTIL (k& AND &ffdf)=%Q REM Quick way to do uppercase ENDP PROC getk&: DO GETEVENT32 a&() IF a&(1)=&404 IF LEFT$(GETCMD$,1)="X" endit: ENDIF ENDIF UNTIL a&(1)<256 RETURN a&(1) ENDP PROC endit: STOP ENDP
Here is a similar document-based application It does the same as the previous example, but System messages to change files cause the procedure fset: to be called. The relevant files are opened or created. A proper application with a toolbar would call TBarSetTitle: to change its title. See Friendlier interaction.
CONST KUidAppMyApp1&=&50000000 REM !!! Should be a reserved UID!!! APP myapp1,KUidAppMyApp1& FLAGS 1 CAPTION "Get Key Doc",1 ICON "myapp1.mbm" ENDA PROC start: GLOBAL a&(10),k&,w$(255) FONT 11,16 :w$=CMD$(2) fset:(CMD$(3)) PRINT "Q to Quit" PRINT "use the Task list" PRINT "to create/switch files" DO k&=getk&: PRINT CHR$(k&); UNTIL (k& AND &ffdf)=%Q ENDP PROC getk&: LOCAL t$(1) DO GETEVENT32 a&() IF a&(1)=$404 w$=GETCMD$ t$=LEFT$(w$,1) w$=MID$(w$,2,255) IF t$="X" endit: ELSEIF t$="C" OR t$="O" TRAP CLOSE IF ERR GIPRINT ERR$(ERR) CONTINUE ENDIF fset:(t$) ENDIF ENDIF UNTIL a&(1)<256 RETURN a&(1) ENDP PROC fset:(t$) LOCAL p&(6) IF t$="C" TRAP DELETE w$ SETDOC w$ TRAP CREATE w$,A,A$ ELSEIF t$="O" SETDOC w$ TRAP OPEN w$,A,A$ ENDIF IF ERR CLS :PRINT ERR$(ERR) REM should revert to old file if possible GET :STOP ENDIF ENDP PROC endit: STOP ENDP
You should, as in both these examples, be precise in checking for the System message; if in future the GETCMD$ function were to use values other than "C", "O" or "X", these procedures would ignore them.
If you need to check the modifier keys for the returned keypress, use a&(4) instead of KMOD.
SETDOC called just before the creation of the file ensures that the created file is a document, i.e. that the file launches its associated application when selected. The strings passed to SETDOC and CREATE (or gSAVEBIT) should be exactly the same, otherwise a non-document file will be created. SETDOC should also be called when opening a document to allow the System screen to display the correct document name in its task list. OPL explicitly supports database and multi-bitmap files as documents.
To be strict, whenever creating a file, an application should first use PARSE$ to find the disk and directory requested. It should then use TRAP MKDIR to ensure that the directory exists.
The LOCK command marks an app as locked or unlocked. When an app is locked with LOCK ON, the System will not send it events to change files or quit. If, for example, you attempt to close down the app from the Task list, a message will appear, indicating that the app cannot close down at that moment.
You should use LOCK ON if your app uses a keyword such as MENU, DIALOG and EDIT which pauses the execution of the program. You might also use it when the app is about to go busy for a considerable length of time, or at any other point where a clean exit is not possible. Do not forget to use LOCK OFF as soon as possible afterwards.
An application is initially unlocked.