Psion Proprietary File Format 1 MC/HC/Series 3 data files. The files used by the Personal Database and Diary applications on the MC400 and MC200 are OPL- compatible. That is, they can be created, opened, edited and appended to from within the users' own OPL programs. The files are EPROM-friendly in that they allow the deletion of records in a file stored on an EPROM device. The files consist of Type Length Value (TLV) records and are made up as follows: 1.1 A standard file signature header. This is the same for all OPL compatible files. It is made up as follows: The null-terminated string "OPLDatabaseFile" A file version number - e.g. 1.10f The offset to the start of the first record An OPL runtime version number - e.g. 1.10f 1.2 Field Structure Record. All TLV records start with a word containing: The record type in the most significant nibble. The length in the remaining three nibbles. This record must be the first record in the file. It specifies the number and types of the fields in the following records. The length of the record defines the number of fields allowed. The body of the record consists of a sequence of bytes specifying the type of each field. These types are: 0 OPL integer (WORD) 1 OPL long integer (LONG) 2 OPL floating point (DOUBLE) 3 OPL leading byte count string OPL and the Personal Database (but NOT the Diary) accepts short records, where one or more of the trailing fields are not present. The fields which are present must correspond, in order, with the sequence of types in the Field Structure Record. 1.3 Type 1 TLV records. There will be a sequence of these records containing the data. 1.4 Type 3 and above TLV records. There may be records of this type in the file (for example a voice record in a Diary file or the descriptive record in a Personal Database file). Records of this type are not documented here. 1.5 Database file example. The following is an example of how a Database file containing one entry would be held: File Signature 4f 50 4c 44 61 74 61 62 61 73 65 49 69 6c 65 00 (O P L D a t a b a s e F i l e Null) 10 0f file version 00 16 offset 10 0f OPL runtime version Field Structure Record 2020 field structure 03 OPL leading byte count string 03 OPL leading byte count string 03 OPL leading byte count string 03 OPL leading byte count string . . (up to 32 text fields) . 03 OPL leading byte count string 03 OPL leading byte count string Example Data Record 102d 0d 42 52 20 73 74 61 74 69 6f 6e 3a 20 20 ( B R s t a t i o n : ) 10 5a 6f 6e 65 3a 20 20 20 20 20 20 20 20 20 20 20 ( Z o n e : ) 0d 54 72 61 76 65 6c 20 72 6f 75 74 65 3a ( T r a v e l R o u t e :) 2 MC Diary files. The following is an example of how a Diary file containing one entry would be held: File Signature 4f 50 4c 44 61 74 61 62 61 73 65 49 69 6c 65 00 (O P L D a t a b a s e F i l e Null) 10 0f file version 00 16 offset 10 0f OPL runtime version Field Structure Record 2006 field structure 00 DAY NUMBER (WORD) 00 TIME/INDEX (WORD) 00 DURATION (WORD) 00 ALARM TIME (WORD) 00 FLAGS (WORD) 03 TEXT (STRING) Example Data Record 1016 diary record $016 bytes long 8087 1st February 1990 (a) 8258 10.00am (b) 003c 1 hour duration = $3c minutes 0249 09.45am (c) 0000 no alarm, no voice (d) 0b 66 69 72 73 74 20 65 6e 74 72 79 ( f i r s t e n t r y) byte counted = $0b Notes: a) The DAY NUMBER is days since 1/1/1900 (= day 0). The first legal day is 5/1/1970. The last is 3/6/2079. b) The top bit of the TIME field is set for timed entries and clear for untimed entries. The rest of the field is the start time in minutes or the index number of an untimed entry. c) The ALARM TIME is in minutes. It must be, sensibly, less than or equal to the TIME start time. The value is arbitrary if the alarm flag is clear. d) The second byte of the FLAGS field is unused and may contain random data. Bit 0 ($01) is set for an alarm. Bit 1 ($02) is used internally to temporarily disable an alarm. Bit 1 should be clear if bit 0 is set, but may have any value if bit 0 is clear. Bit 2 ($04) is set for voice. The remaining bits are not used. 2.1. Diary file access from OPL The following line of code will open the file for use in an OPL program with the logical name of 'A'. OPEN "LOC::M:\diary.dry",A,day%,time%,len%,alarm%,flags%,txt$ Loading the individual fields with appropriate values and then executing an UPDATE or APPEND will allow you to edit existing records (Diary entries) and add new ones. Records deleted with the OPL ERASE command will be removed from the Diary file. All of the OPL file handling commands such as FIRST, NEXT, LAST, FIND, etc will apply. It should be noted that the fields such as DAY NUMBER are stored as unsigned words. When OPENed as integers, the values will be represented as large negative numbers due to the top bit of the word being set. When loading the fields with values to be written to the file, users may encounter problems when trying to load a field such as the DAY NUMBER field with a large positive number of days i.e. a number of days over 32767. One approach in this circumstance is to use the following method: tdays& = 39000 /* too large for an integer */ A.days% = PEEKW(ADDR(tdays&)) . . rest of code . UPDATE CLOSE . . . etc. 3 Series 3 Agenda files Series 3 Agenda files are very similar indeed to MC Diary files. However, the following differences apply: 3.1 Field Structure Record. 2005 field structure 00 DAY NUMBER (WORD) 00 DURATION (WORD) 00 TIME (WORD) 00 ALARM TIME (WORD) 03 TEXT (STRING) 3.2 Timed and untimed items. - The DAY NUMBER is the number of days since the 1/1/1900 (=day 0). The first legal day is 1/1/1980, the last legal day is the 31/12/2049. - DURATION, TIME AND ALARM TIME are all stored in minutes. - The MSB of TIME (i.e. $8000) is a flag that indicates whether the item is timed or untimed. If the flag is set then the item is untimed, if clear then the item is timed. - To extract the time from the TIME field it must be ANDed with $7fff to remove the MSB. - The LSB of DURATION (i.e. $1) is a flag that indicates whether the item has an alarm attached. If the flag is set then the item has no alarm attached, if clear then the item has an alarm attached. - To extract the duration from the DURATION field, divide by 2 which removes the LSB and shifts down the duration. - If the item is untimed then the TIME field contains the day note slot number (i.e. 1 to n and its MSB must be set). The DURATION field contains 0 if an alarm is attached or 1 if no alarm is attached. - The end time of a timed item (i.e time + duration) must be less than 24 * 60 = 1440 minutes. - For timed items, the ALARM TIME is an alarm pre time and is calculated as follows: Pre time to Agenda internal alarm format: (23 * 60 + 59) + alarm pre time - TIME Agenda internal alarm format to pre time: TIME - (23 * 60 + 59) + ALARM TIME - For untimed items, the ALARM TIME is calculated as follows: Pre time to Agenda internal alarm format: (days previous*(24*60))-((23*60+59)-ALARM TIME) Agenda internal alarm format to days previous: ALARM TIME / (24 * 60) Agenda internal alarm format to alarm time: (23 * 60 + 59) - (ALARM TIME modulus (24*60)) - If the item does not have an alarm, the ALARM TIME field should contain -1. - The TEXT field is stored as a leading byte count string and its length must be less than 64 characters. 3.3 Todo items. - Todo items have a DAY NUMBER OF $ffff and must be stored as timed items. As such, the MSB of the TIME field must be clear. - The TIME field contains the item priority (i.e. 1 to 9). - The DURATION field contains a secondary key which orders Todo items within priority. - Todo items cannot have alarms attached. 3.4 Repeat items. - Timed and untimed repeat items are stored in exactly the same way as normal timed and untimed items, except that they have a DAY NUMBER of $fffe. - The specific repeat details are stored at the end of the TEXT field and have the following format: TYPE (BYTE) INTERVAL (BYTE) START DAY NUMBER (WORD) END DAY NUMBER (WORD) - The TYPE field can take the following values: repeat yearly = 0 repeat monthly by date = 1 repeat monthly by day = 2 repeat weekly = 3 repeat daily = 4 repeat workdays = 5 - The START DAY NUMBER and END DAY NUMBER are stored as the number of days since 1/1/1900 (=day 0). - Setting the END DAY NUMBER field to 0 means the item will repeat forever.