############################################################################ # # File: abkform.icn # # Subject: Procedures to process HP95LX appointment books # # Author: Robert J. Alexander # # Date: May 2, 2001 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # Procedures set to read and write HP95LX appointment book (.abk) files. # # # Notes: # # 1. Files created by the Appointment Book application may contain # some padding following the last field of some data records. Hence, # the RecordLength field must be used to determine the start of the # next record. Appointment book files created by other programs need not # have any padding. # # 2. ApptState has several bit fields. Only bit 0 is meaningful to software # processing an appointment book file. Bit 0 being set or cleared # corresponds to the alarm being enabled or disabled, respectively. # Programs creating Appointment book files should clear all bits, except # perhaps bit 0. # # 3. ToDoState has two one-bit bit fields. Bit 0 being set or cleared # corresponds to carry forward being enabled or disabled for this todo # item, respectively. Bit 1 being set or cleared corresponds to the doto # being checked off or not checked off, respectively. # # 4. Appointment and ToDo texts are each limited to a maximum of 27 # characters. # # 5. Note text is limited to a maximum of 11 lines of 39 characters per line # (not counting the line terminator). # # ############################################################################ # # Links: bkutil, pbkform # ############################################################################ # # See also: bkutil.icn, pbkform.icn # ############################################################################ link bkutil, pbkform # HP 95LX Appointment Book File Format # # The HP 95LX Appointment Book file is structured as a file-identification # record, followed by a settings record, followed by a variable number of data # records, and terminated by an end-of-file record. There are multiple types of # data records corresponding to the different types of appointment book entries. # # The formats of these appointment book records is described in the following # tables. In the descriptions, the type refers to a two-byte integer # stored least significant byte first, the type refers to a two-byte # integer stored most significant byte first, the type refers to a # one-byte integer, and the type refers to a string of ASCII # characters. # # HP 95LX Appointment Book File Identification Record: # # Byte Offset Name Type Contents # # 0 ProductCode int -1 (FFh, FFh) # 2 ReleaseNum int 1 (01h, 00h) # 4 FileType char 1 (01h) # procedure abk_write_id(f) return writes(f,"\xff\xff\x01\x00\x01") end record abk_id(releaseNum,filetype) procedure abk_read_id(f) bk_read_int(f) = 16rffff | fail return pbk_id(bk_read_int(f),ord(reads(f))) end # # HP 95LX Appointment Book Settings Record: # # Byte Offset Name Type Contents # # 0 StartTime int Daily display start time as the # number of minutes past midnight. # 2 Granularity int Daily display time line granularity # in minutes. # 4 AlarmEnable char 1 = on, 0 = off # 5 LeadTime char Alarm default lead time in minutes. # 6 CarryForward char To do carry forward default, # 1 = on, 0 = off. # record abk_settings(startTime,granularity,alarmEnable,leadTime,carryForward) procedure abk_write_settings(f,data) return writes(f,bk_int(data.startTime),bk_int(data.granularity), char(data.alarmEnable), char(data.leadTime),char(data.carryForward)) end procedure abk_read_settings(f) return abk_settings(bk_read_int(f),bk_read_int(f),ord(reads(f)), ord(reads(f)),ord(reads(f))) end # # # HP 95LX Appointment Book Daily Data Record: # # Byte Offset Name Type Contents # # 0 RecordType char 1 (01h) # 1 RecordLength int Number of bytes in remainder # of this data record, see note 1 # below. # 3 ApptState char See note 2 below. # 4 Year char Year counting from 1900. # 5 Month char Month, 1 - 12. # 6 Day char Day, 1 - 31. # 7 StartTime swpint Start time in minutes since midnight. # 9 EndTime int End time in minutes since midnight. # 11 LeadTime char Alarm lead time in minutes, 0 - 30. # 12 ApptLength char Length of appointment text in bytes. # 13 NoteLength int Length of note text in bytes. # 15 ApptText ASCII Appointment text - see note 4 below. # 15+ApptLength NoteText ASCII Note text where the null character # is used as the line terminator - # see note 5. # record abk_daily(alarmEnable,year,month,day,startTime,endTime,leadTime, apptText,noteText) procedure abk_write_daily(f,data) writes(char((\data.alarmEnable,1) | 0), char(data.year),char(data.month),char(data.day), bk_int(data.startTime),bk_int(data.endTime),bk_int(data.leadTime), char(*data.apptText),char(*data.noteText),data.apptText,data.noteText) return data end procedure abk_read_daily(f) local alarmEnable,year,month,day,startTime,endTime,leadTime, apptText,noteText,apptLength,noteLength,next_rec (reads(f) == "\x01" | (seek(f,where(f) - 1),&fail) & next_rec := bk_read_int(f) + where(f) & alarmEnable := iand(ord(reads(f)),1) = 1 | &null & year := ord(reads(f)) & month := ord(reads(f)) & day := ord(reads(f)) & startTime := bk_read_int(f) & endTime := bk_read_int(f) & leadTime := ord(reads(f)) & apptLength := ord(reads(f)) & noteLength := bk_read_int(f) & apptText := reads(f,apptLength) & noteText := reads(f,noteLength)) | fail return abk_daily(alarmEnable,year,month,day,startTime,endTime,leadTime, apptText,noteText) end # # HP 95LX Appointment Book Weekly Data Record: # # Byte Offset Name Type Contents # # 0 RecordType char 2 (02h) # 1 RecordLength int Number of bytes in remainder # of this data record, see note 1 # below. # 3 ApptState char See note 2 below. # 4 DayOfWeek char Day of week, 1=Sun, ..., 7=Sat. # 5 StartTime swpint Start time in minutes since midnight. # 7 StartYear char Start year counting from 1900. # 8 StartMonth char Start month, 1 - 12. # 9 StartDay char Start day, 1 - 31. # 10 EndTime int End time in minutes since midnight. # 12 EndYear char End year counting from 1900. # 13 EndMonth char End month, 1 - 12. # 14 EndDay char End day, 1 - 31. # 15 LeadTime char Alarm lead time in minutes, 0 - 30. # 16 ApptLength char Length of appointment text in bytes. # 17 NoteLength int Length of note text in bytes. # 19 ApptText ASCII Appointment text - see note 4 below. # 19+ApptLength NoteText ASCII Note text where the null character # is used as the line terminator - # see note 5 below. # record abk_weekly(alarmEnable,dayOfWeek,startTime,startYear,startMonth,startDay, endTime,endYear,endMonth,endDay,leadTime,apptText,noteText) procedure abk_write_weekly(f,data) writes(char((\data.alarmEnable,1) | 0), char(data.dayOfWeek), bk_int(data.startTime),char(data.startYear), char(data.startMonth),char(data.startDay), bk_int(data.endTime),char(data.endYear), char(data.endMonth),char(data.endDay), bk_int(data.leadTime), char(*data.apptText),char(*data.noteText),data.apptText,data.noteText) return data end procedure abk_read_weekly(f) local alarmEnable,dayOfWeek,startTime,startYear,startMonth,startDay, endTime,endYear,endMonth,endDay,leadTime,apptLength,noteLength, apptText,noteText,next_rec (reads(f) == "\x02" | (seek(f,where(f) - 1),&fail) & next_rec := bk_read_int(f) + where(f) & alarmEnable := iand(ord(reads(f)),1) = 1 | &null & dayOfWeek := ord(reads(f)) & startTime := bk_read_int(f) & startYear := ord(reads(f)) & startMonth := ord(reads(f)) & startDay := ord(reads(f)) & endTime := bk_read_int(f) & endYear := ord(reads(f)) & endMonth := ord(reads(f)) & endDay := ord(reads(f)) & leadTime := ord(reads(f)) & apptLength := ord(reads(f)) & noteLength := bk_read_int(f) & apptText := reads(f,apptLength) & noteText := reads(f,noteLength)) | fail return abk_daily(alarmEnable,dayOfWeek,startTime,startYear,startMonth, startDay,endTime,endYear,endMonth,endDay,leadTime,apptText,noteText) end # # # HP 95LX Appointment Book Monthly by Date Data Record: # # Byte Offset Name Type Contents # # 0 RecordType char 3 (03h) # 1 RecordLength int Number of bytes in remainder # of this data record, see note 1 # below. # 3 ApptState char See note 2 below. # 4 DayOfMonth char Day of month, 1 - 31. # 5 StartTime swpint Start time in minutes since midnight. # 7 StartYear char Start year counting from 1900. # 8 StartMonth char Start month, 1 - 12. # 9 StartDay char Start day, 1 - 31. # 10 EndTime int End time in minutes since midnight. # 12 EndYear char End year counting from 1900. # 13 EndMonth char End month, 1 - 12. # 14 EndDay char End day, 1 - 31. # 15 LeadTime char Alarm lead time in minutes, 0 - 30. # 16 ApptLength char Length of appointment text in bytes. # 17 NoteLength int Length of note text in bytes. # 19 ApptText ASCII Appointment text - see note 4 below. # 19+ApptLength NoteText ASCII Note text where the null character # is used as the line terminator - # see note 5 below. # record abk_monthly(alarmEnable,dayOfMonth,startTime,startYear,startMonth, startDay,endTime,endYear,endMonth,endDay,leadTime,apptText,noteText) procedure abk_write_monthly(f,data) writes(char((\data.alarmEnable,1) | 0), char(data.dayOfMonth), bk_int(data.startTime),char(data.startYear), char(data.startMonth),char(data.startDay), bk_int(data.endTime),char(data.endYear), char(data.endMonth),char(data.endDay), bk_int(data.leadTime), char(*data.apptText),char(*data.noteText),data.apptText,data.noteText) return data end procedure abk_read_monthly(f) local alarmEnable,dayOfMonth,startTime,startYear,startMonth,startDay, endTime,endYear,endMonth,endDay,leadTime,apptLength,noteLength, apptText,noteText,next_rec (reads(f) == "\x03" | (seek(f,where(f) - 1),&fail) & next_rec := bk_read_int(f) + where(f) & alarmEnable := iand(ord(reads(f)),1) = 1 | &null & dayOfMonth := ord(reads(f)) & startTime := bk_read_int(f) & startYear := ord(reads(f)) & startMonth := ord(reads(f)) & startDay := ord(reads(f)) & endTime := bk_read_int(f) & endYear := ord(reads(f)) & endMonth := ord(reads(f)) & endDay := ord(reads(f)) & leadTime := ord(reads(f)) & apptLength := ord(reads(f)) & noteLength := bk_read_int(f) & apptText := reads(f,apptLength) & noteText := reads(f,noteLength)) | fail return abk_daily(alarmEnable,dayOfMonth,startTime,startYear,startMonth, startDay,endTime,endYear,endMonth,endDay,leadTime,apptText,noteText) end # # HP 95LX Appointment Book Monthly by Position Data Record: # # Byte Offset Name Type Contents # # 0 RecordType char 4 (04h) # 1 RecordLength int Number of bytes in remainder # of this data record, see note 1 # below. # 3 ApptState char See note 2 below. # 4 WeekOfMonth char Week of month, 1 - 5. # 5 DayOfWeek char Day of week, 1=Sun, ..., 7=Sat. # 6 StartTime swpint Start time in minutes since midnight. # 8 StartYear char Start year counting from 1900. # 9 StartMonth char Start month, 1 - 12. # 10 StartDay char Start day, 1 - 31. # 11 EndTime int End time in minutes since midnight. # 13 EndYear char End year counting from 1900. # 14 EndMonth char End month, 1 - 12. # 15 EndDay char End day, 1 - 31. # 16 LeadTime char Alarm lead time in minutes, 0 - 30. # 17 ApptLength char Length of appointment text in bytes. # 18 NoteLength int Length of note text in bytes. # 20 ApptText ASCII Appointment text - see note 4 below. # 20+ApptLength NoteText ASCII Note text where the null character # is used as the line terminator - # see note 5 below. # record abk_monthly_pos(alarmEnable,weekOfMonth,dayOfWeek,startTime,startYear, startMonth,startDay,endTime,endYear,endMonth,endDay,leadTime, apptText,noteText) procedure abk_write_monthly_pos(f,data) writes(char((\data.alarmEnable,1) | 0), char(data.weekOfMonth), char(data.dayOfWeek), bk_int(data.startTime),char(data.startYear), char(data.startMonth),char(data.startDay), bk_int(data.endTime),char(data.endYear), char(data.endMonth),char(data.endDay), bk_int(data.leadTime), char(*data.apptText),char(*data.noteText),data.apptText,data.noteText) return data end procedure abk_read_monthly_pos(f) local alarmEnable,weekOfMonth,dayOfWeek,startTime,startYear,startMonth, startDay,endTime,endYear,endMonth,endDay,leadTime,apptLength,noteLength, apptText,noteText,next_rec (reads(f) == "\x04" | (seek(f,where(f) - 1),&fail) & next_rec := bk_read_int(f) + where(f) & alarmEnable := iand(ord(reads(f)),1) = 1 | &null & weekOfMonth := ord(reads(f)) & dayOfWeek := ord(reads(f)) & startTime := bk_read_int(f) & startYear := ord(reads(f)) & startMonth := ord(reads(f)) & startDay := ord(reads(f)) & endTime := bk_read_int(f) & endYear := ord(reads(f)) & endMonth := ord(reads(f)) & endDay := ord(reads(f)) & leadTime := ord(reads(f)) & apptLength := ord(reads(f)) & noteLength := bk_read_int(f) & apptText := reads(f,apptLength) & noteText := reads(f,noteLength)) | fail return abk_daily(alarmEnable,weekOfMonth,dayOfWeek,startTime,startYear, startMonth,startDay,endTime,endYear,endMonth,endDay,leadTime,apptText, noteText) end # # HP 95LX Appointment Book Yearly Data Record: # # Byte Offset Name Type Contents # # 0 RecordType char 5 (05h) # 1 RecordLength int Number of bytes in remainder # of this data record, see note 1 # below. # 3 ApptState char See note 2 below. # 4 MonthOfYear char Month of year, 1=Jan, ... 12=Dec. # 5 DayOfMonth char Day of month, 1 - 31. # 6 StartTime swpint Start time in minutes since midnight. # 8 StartYear char Start year counting from 1900. # 9 StartMonth char Start month, 1 - 12. # 10 StartDay char Start day, 1 - 31. # 11 EndTime int End time in minutes since midnight. # 13 EndYear char End year counting from 1900. # 14 EndMonth char End month, 1 - 12. # 15 EndDay char End day, 1 - 31. # 16 LeadTime char Alarm lead time in minutes, 0 - 30. # 17 ApptLength char Length of appointment text in bytes. # 18 NoteLength int Length of note text in bytes. # 20 ApptText ASCII Appointment text - see note 4 below. # 20+ApptLength NoteText ASCII Note text where the null character # is used as the line terminator - # see note 5 below. # record abk_yearly(alarmEnable,monthOfYear,dayOfMonth,startTime,startYear, startMonth,startDay,endTime,endYear,endMonth,endDay,leadTime, apptText,noteText) procedure abk_write_yearly(f,data) writes(char((\data.alarmEnable,1) | 0), char(data.monthOfYear), char(data.dayOfMonth), bk_int(data.startTime),char(data.startYear), char(data.startMonth),char(data.startDay), bk_int(data.endTime),char(data.endYear), char(data.endMonth),char(data.endDay), bk_int(data.leadTime), char(*data.apptText),char(*data.noteText),data.apptText,data.noteText) return data end procedure abk_read_yearly(f) local alarmEnable,monthOfYear,dayOfMonth,startTime,startYear,startMonth, startDay,endTime,endYear,endMonth,endDay,leadTime,apptLength,noteLength, apptText,noteText,next_rec (reads(f) == "\x05" | (seek(f,where(f) - 1),&fail) & next_rec := bk_read_int(f) + where(f) & alarmEnable := iand(ord(reads(f)),1) = 1 | &null & monthOfYear := ord(reads(f)) & dayOfMonth := ord(reads(f)) & startTime := bk_read_int(f) & startYear := ord(reads(f)) & startMonth := ord(reads(f)) & startDay := ord(reads(f)) & endTime := bk_read_int(f) & endYear := ord(reads(f)) & endMonth := ord(reads(f)) & endDay := ord(reads(f)) & leadTime := ord(reads(f)) & apptLength := ord(reads(f)) & noteLength := bk_read_int(f) & apptText := reads(f,apptLength) & noteText := reads(f,noteLength)) | fail return abk_daily(alarmEnable,monthOfYear,dayOfMonth,startTime,startYear, startMonth,startDay,endTime,endYear,endMonth,endDay,leadTime,apptText, noteText) end # # HP 95LX Appointment Book To Do Data Record: # # Byte Offset Name Type Contents # # 0 RecordType char 6 (06h) # 1 RecordLength int Number of bytes in remainder # of this data record, see note 1 # below. # 3 ToDoState char See note 3 below. # 4 Priority char Priority, 1 - 9. # 5 StartYear char Start year counting from 1900. # 6 StartMonth char Start month, 1 - 12. # 7 StartDay char Start day, 1 - 31. # 8 CheckOffYear char Check off year counting from 1900, # 0 indicates not checked off. # 9 CheckOffMonth char Check off month, 1 - 12, # 0 indicates not checked off. # 10 CheckOffDay char Check off day, 1 - 31, # 0 indicates not checked off. # 11 ToDoLength char Length of to do text in bytes. # 12 NoteLength int Length of note text in bytes. # 14 ToDoText ASCII To do text - see note 4 below. # 14+ToDoLength NoteText ASCII Note text where the null character # is used as the line terminator - # see note 5 below. # record abk_todo(carryForward,checkOff,priority,startYear,startMonth, startDay,CheckOffYear,CheckOffMonth,CheckOffDay,toDoText,toDoNote) procedure abk_write_todo(f,data) writes(char(ior((\data.carryForward,1) | 0,(\data.checkOff,2) | 0)), char(data.priority), char(data.startYear), char(data.startMonth),char(data.startDay), char(data.checkOffYear), char(data.checkOffMonth),char(data.checkOffDay), char(*data.toDoText),char(*data.noteText),data.toDoText,data.noteText) return data end procedure abk_read_todo(f) local carryForward,checkOff,priority,startYear,startMonth, startDay,CheckOffYear,CheckOffMonth,CheckOffDay,toDoLength,noteLength, toDoText,toDoNote,toDoState,next_rec (reads(f) == "\x06" | (seek(f,where(f) - 1),&fail) & next_rec := bk_read_int(f) + where(f) & toDoState := ord(reads(f)) & carryForward := iand(toDoState,1) = 1 | &null & checkOff := iand(toDoState,2) = 1 | &null & priority := ord(reads(f)) & startYear := ord(reads(f)) & startMonth := ord(reads(f)) & startDay := ord(reads(f)) & CheckOffYear := ord(reads(f)) & CheckOffMonth := ord(reads(f)) & CheckOffDay := ord(reads(f)) & toDoLength := ord(reads(f)) & noteLength := bk_read_int(f) & toDoText := reads(f,toDoLength) & toDoNote := reads(f,noteLength)) | fail return abk_daily(carryForward,checkOff,priority,startYear,startMonth, startDay,CheckOffYear,CheckOffMonth,CheckOffDay,toDoText,toDoNote) end # # HP 95LX Appointment Book End of File Record: # # Byte Offset Name Type Contents # # 0 RecordType char 50 (32h) # 1 RecordLength int 0 (00h, 00h) # procedure abk_write_end(f) writes(f,"\x32\x00\x00") return end procedure abk_read_end(f,id) (reads(f) == "\x32" & reads(f,2)) | fail return end