EPOC   SDK Home Glossary   Previous Next Up

OPL applications


Contents

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.


Defining an application

To make an application, your OPL file should begin with the APP keyword, followed by a name for the app in the machine’s 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 application’s documents will have the wrong icon and selecting these will run the other application, or the other application’s 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 don’t 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 application’s documents on the System screen. The multi-bitmap file can contain up to three bitmaps of sizes 2424, 3232 and 4848 pixels respectively, but each must be paired with a mask. Each bitmap should be followed by its mask in the multi-bitmap file, so that bitmaps and masks occur alternately. The pixels which are set in the mask specify pixels in the bitmap which are to be used. Pixels which are clear in the mask specify pixels that are not to be used from the bitmap, allowing the background to be displayed in these pixels. Only pixels which are set in the mask are drawn in the final icon.

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 application’s 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 APPENDA 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 APPENDA 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.


Running the application

Once you’ve 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 application’s 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 application’s 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).


How the EPOC device talks to an application

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 don’t 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.


System screen compliance

A well-behaved application should obey the following important guidelines:

          p$=PARSE$("NEW",LEFT$(CMD$(1),LEN(CMD$(1)-4),x%())

Launching help 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 application’s 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 application’s 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 program’s 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

Example applications

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.


When an application cannot respond

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.

EPOC       SDK Home Glossary   Previous Next Up