m'ʔdDF $"Ϯ%>c-*)H=\GLH\AldurContactOpx\Develop.txt\GLH\AldurContactOpx\AldurContactOpx!:\AldurSoft\AldurContactOpx\GLH\AldurContactOpx\AldurContact.oxh!:\system\Opl\AldurContact.oxh\Epoc32\Release\Marm\Rel\AldurContact.opx!:\system\Opx\AldurContact.opxAldurContact OPX G.L.HoldenAldurContact OPX Graham Holden, 2004 This is an incredibly early first stab at a replacement for Contact.OPX (which apparently doesn't work well). It's incomplete and undertested, so use with care! See the example OPL program 'AldurContactOpx' for more. 7mcU\cdCoinclude "Const.oph"include "System.oxh"include "AldurContact.oxh"REM include "Contact.oxh"REM -------------------------------------------------------------REM Throughout this example program, I use 'CurrentDatabase$'REM and set it to either 'SystemDatabase$' or 'TestDatabase$'REM (normally the latter for safety).REMREM One feature I've added to the OPX, but not used here, is toREM allow 'COContactOpenFile:( "" )' to open the system databaseREM (that used by the Contacts Application) without having toREM know the name/location of it.REM -------------------------------------------------------------REM -------------------------------------------------------------REM These are the field indices for the 'First name' and 'LastREM name' fiels. If in your Contacts file they are in differentREM positions, adjust accordingly.REM -------------------------------------------------------------Const KFirstNameField% = 2Const KLastNameField% = 4REM -------------------------------------------------------------REM Main menuREM -------------------------------------------------------------proc Main: Global SystemDatabase$( 255 ) Global TestDatabase$( 255 ) Global CurrentDatabase$( 255 ) Global FieldsPerPage% Global LinesPerPage% Global UidTypeArray&( 100 ), UidTypeArraySize% Global id&, contact&, label$(255), data$(255) Global ArrayHandle&, ArrayData&(100) Global searchFor$(255) Global LineNo%, StepNo% local dlg% REM ----------------------------------------------------------- REM Setup various semi-constants. REM REM FieldsPerPage% is the number of fields displayed per page REM of the edit/examine contact dialog. REM LinesPerPage% is the number of lines before displaying REM the '[more]' prompt for text output. REM ArrayHandle& is the address of an array used to access REM field information and for sorting contacts. REM GetDatabaseNames: sets the file/paths of the test and live REM contact databases. REM BuildUidArrays: Initialises field-types for use in dialogs. REM ----------------------------------------------------------- FieldsPerPage% = ( 9*gHeight - 576) / 208 LinesPerPage% = (11*gHeight - 240) / 120 ArrayHandle& = ADDR( ArrayData&() ) GetDatabaseNames: BuildUidArrays: REM ----------------------------------------------------------- REM Ensure that a 'test' database exists for us to work with; REM We don't want to mangle the 'live' contacts by accident. REM ----------------------------------------------------------- if CopyOrCreateTestDatabase%:( KFalse%) dInit "Goodbye" dText "", "You have chosen not to create a 'test' database," dText "", "so this demonstration program will not run." dButtons "Close", $10D Dialog return endif REM ----------------------------------------------------------- REM Main program loop -- present a range of options to the user. REM ----------------------------------------------------------- while KTrue% dInit "Choose task", KDlgDensePack% dText "Examine/edit contacts", "", KDTextAllowSelection% dText "Examine contact template", "", KDTextAllowSelection% dText "List default contacts", "", KDTextAllowSelection% dText "Filter default contacts", "", KDTextAllowSelection% dText "Find field", "", KDTextAllowSelection% dText "Repair contacts file", "", KDTextAllowSelection% dText "Switch database in use", "", KDTextAllowSelection% dText "Recreate test database", "", KDTextAllowSelection% dlg% = Dialog if dlg% = 0 break elseif dlg% = 2 : ExamineOrChangeContact: elseif dlg% = 3 : ExamineContactTemplate: elseif dlg% = 4 : ListDefaultContacts: elseif dlg% = 5 : FilterDefaultContacts: elseif dlg% = 6 : FindField: elseif dlg% = 7 : RepairContactsFile: elseif dlg% = 8 : SelectDatabase: elseif dlg% = 9 : CopyOrCreateTestDatabase%:( KTrue%) endif endwhendpREM -------------------------------------------------------------REM General support functions -- pausing screen outputREM -------------------------------------------------------------proc CLS: Cls LineNo% = 0endpproc Pause%:( prompt$ ) local ch% print prompt$; ch% = Get print Chr$( 13 ); " "; Chr$( 13 ); LineNo% = 1  return (ch% = %q) OR (ch% = %Q) OR (ch% = 27)endpproc Done: Pause%:( "Finished." )endpproc More%: return Pause%:( "[more]" )endpproc Line%: if LineNo% >= LinesPerPage% return More%: endif LineNo% = LineNo% + 1 return KFalse%endpproc Step: stepNo% = stepNo% + 1 print "Step", stepNo% More%:endpREM -------------------------------------------------------------REM Sets up the variables for the default System database (whichREM we'll copy) and the location of the Test database (that we'llREM be working on). The latter is in the same place as the OPLREM program.REM -------------------------------------------------------------proc GetDatabaseNames: local parse%(6) TestDatabase$ = Parse$( "TEST.cdb", Cmd$( KCmdAppName% ), parse%() ) SystemDatabase$ = COGetSystemDatabase$: CurrentDatabase$ = TestDatabase$endpREM -------------------------------------------------------------REM When first run, either takes a copy of your main ContactsREM database to work on, or creates an empty database. Later,REM can be called to re-copy or clear the working database.REM -------------------------------------------------------------proc CopyOrCreateTestDatabase%:( force% ) local dlg% while KTrue% if NOT Exist( TestDatabase$ ) dInit "Create test database" dText "", "To avoid mangling your 'live' Contacts database, this program works" dText "", "with a 'test' database. As this doesn't exist, you need to either" dText "", "take a copy of your live Contacts, or create a new, blank, test file." elseif force% dInit "Overwrite test database" dText "", "You can overwrite the current test contacts database either with" dText "", "a copy of your live Contacts, or by creating a blank test file." else return endif dText "", "", KDTextSeparator% dText "System database", SystemDatabase$ dText "Test database", TestDatabase$ dText "", "", KDTextSeparator% dButtons "Edit database paths", %e, "Copy 'live' Contacts", %c, "Create new file", %n dlg% = Dialog if dlg% = 0 return KTrue% elseif dlg% = %e dInit "Edit database paths" dEdit SystemDatabase$, "System database", 20 dEdit TestDatabase$, "Test database", 20 Dialog elseif dlg% = %c Copy SystemDatabase$, TestDataBase$ gIPrint "Copied 'live' contacts" break elseif dlg% = %n if Exist( TestDatabase$ ) Delete TestDatabase$ endif COCreateContactFile:( TestDatabase$ ) COCloseContactFile: gIPrint "Created empty contacts" break endif endwh CurrentDatabase$ = TestDatabase$ return KFalse%endpREM -------------------------------------------------------------REM Allow the user to switch from using the TEST database to useREM the LIVE database (as used by the Contacts Application).REMREM Care should be exercised, since quite apart form deleting orREM overwriting data it IS possible to mangle the database, e.g.REM by deleting fields from the template.REMREM It is also possible that there are bugs in the OPX.REM -------------------------------------------------------------proc SelectDatabase: dInit "Select database" dText "", "This demonstration program normally works on a test" dText "", "database of contacts, so that you (or it) won't accidentally" dText "", "damage your 'live' contacts file." dText "", "", KDTextSeparator% dText "", "However, you can switch to working on your 'live' contacts" dText "", "if you wish. If you choose to do so, you are STRONGLY" dText "", "advised to ensure you have a backup of the file:" dText "", SystemDatabase$, KDTextCentre% dButtons "Switch to LIVE contacts", %l, "Use TEST contacts", 13 if Dialog = %l dInit "About to use LIVE contacts" dText "", "You are about to switch to using your LIVE" dText "", "contacts. Please exercise suitable care." dButtons "No, I've changed my mind", -27, "Ok, carry on", 13 if Dialog = 13 CurrentDatabase$ = SystemDatabase$ gIPrint "Using LIVE contacts" WarnIfWorkingOnLive: return endif endif CurrentDatabase$ = TestDatabase$ gIPrint "Using TEST contacts"endpREM -------------------------------------------------------------REM Set up a BUSY message in top-right corner if working onREM the LIVE contact database.REM -------------------------------------------------------------proc WarnIfWorkingOnLive: if CurrentDatabase$ = SystemDatabase$ Busy "** Working with LIVE contacts **", KBusyTopRight% endifendpREM -------------------------------------------------------------REM Selects a contact (or the template) to examine or edit;REM allows a new contact to be created.REMREM Exiting contacts are accessed using:REMREM COSortContactFile:( ArrayHandle& )REMREM This takes the address of an array; the first element holdsREM the number of elements used (including itself). RemainingREM elements identify the fields to sort on (subsequent elementsREM are only used when there's a match). A negative elementREM means sort in descending order.REMREM A similar array is used for COFindContact&:().REM -------------------------------------------------------------proc ExamineOrChangeContact: local dlg% Busy "Opening contacts...", 1 REM KBusyBottomLeft%, 2 COOpenContactFile:( CurrentDatabase$ ) ArrayData&(1) = 0 ArrayData&(2) = -KUidCntFieldFamilyName ArrayData&(3) = KUidCntFieldGivenName COSortContactFile:( ArrayHandle& ) Busy Off WarnIfWorkingOnLive: while KTrue% Trap Raise 0 NotFound::OnErr Off if ERR <> 0 dInit "Error accessing contact" dText "Error " + Gen$( ERR, 5 ), ERR$( ERR ) Dialog Trap Raise 0 endifrem OnErr NotFound:: if COCountContacts&: dInit "Examine contact (1.." + Gen$( COCountContacts&:, 5 ) + ")" dLong contact&, "Contact number", 1, COCountContacts&: dButtons "New contact", %n, "Template", %t, "View", 13 else dInit "Examine contact" dText "", "There are no contacts in the database." dButtons "New contact", %n, "Template", %t endif dlg% = Dialog if dlg% = 0 break elseif dlg% = %n CreateContact: contact& = -1 elseif dlg% = 13 COSortedContactFileAt:( contact& ) elseif dlg% = %t contact& = 0 COReadContactTemplate: endif DisplayContact%:( COContactId&: ) endwh COCloseContactFile:endpREM -------------------------------------------------------------REM Creates a new contact item to edit. For simplicity of thisREM example program, I create an item then immediately add it toREM the database, so that DisplayContact%:() can work on it.REMREM In practice, you would create/add/amend/delete fields betweenREM the COCreateContact: and COAddNewContact: calls.REMREM COCreateContact:REM creates a new item based on the template (i.e. has allREM fields present);REM COCreateContactEmpty:REM create a new item without using the template (it willREM not have any fields at this point).REM COContactFieldReset:REM will delete all fields in the current item (can be usedREM after COCreateContact: or COOpenContact:)REM COAddNewContact:REM will add the current item to the database as a newREM contact. Any fields not present will be inherited fromREM the template. This can be used with ANY item, so:REM COReadContact:( id& )REM COAddNewContact:REM will duplicate a contact (or you could change some ofREM the fields between the two calls).REM CODeleteContact:REM will throwaway the newly created contact item. (ThisREM is also used to delete existing contacts within theREM database).REMREM After COCreateContact: or COCreateContactEmpty:, you shouldREM always call COAddNewContact: or CODeleteContact: CallingREM COCloseContactFile: will also discard a new contact item.REM -------------------------------------------------------------proc CreateContact: local id& COCreateContact: COAddNewContact:endpREM -------------------------------------------------------------REM Full-screen dialog to isplays all fields of the contact itemREM selected above (existing, template or new). The controls are:REM Tab Show previous page of fieldsREM Enter Show next page of fieldsREM Ctrl-A Add a fieldREM Ctrl-V Move a fieldREM Ctrl-E Edit a fieldREM Del Delete a fieldREM Ctrl-D Show details of all fields (types + mapping)REM Ctrl-Z Zap (delete) the itemREM -------------------------------------------------------------proc DisplayContact%:( id& ) local nFields%, field%, pageNo%, nPages%, dlg%, label$(255) pageNo% = 0 while KTrue% nFields% = COContactFieldCount&: nPages% = (nFields% + FieldsPerPage% - 1) / FieldsPerPage% dInit "Contact ID " + Gen$( id&, 5 ) + " [page " + Gen$( pageNo% + 1, 5 ) + " of " + Gen$( nPages%, 5 ) + "] " + Gen$( nFields%, 5 ) + " fields", KDlgDensePack% OR KDlgFillScreen% REM --------------------------------------------------------- REM Because we're checking several properties for each field, REM we'll use COContactFieldArrayAt:() which makes on of the REM fields in the current item 'active'. REM REM For nearly all the field-accessing functions, I've also REM added COContactFieldXxxAt: versions, which take a field REM number as their first parameter. REM --------------------------------------------------------- field% = 1 while (field% <= FieldsPerPage%) AND (pageNo% * FieldsPerPage% + field% <= nFields%) COContactFieldArrayAt:( pageNo% * FieldsPerPage% + field% ) label$ = Gen$( pageNo% * FieldsPerPage% + field%, 5 ) + ". " + COContactFieldLabel$: if COContactFieldIsHidden%: label$ = label$ + " [hid]" endif if COContactFieldIsReadOnly%: label$ = label$ + " [r/o]" endif if COContactFieldIsDisabled%: label$ = label$ + " [dis]" endif if COContactFieldStorage%: = KStorageTypeText% dText label$, COContactFieldText$: elseif COContactFieldStorage%: = KStorageTypeDateTime% dText label$, COContactFieldDateTime$: else dText label$, "" endif field% = field% + 1 endwh dButtons "Back", 9, "Add F.", %a, "Del F.", 8, "Move F.", %v, "Edit", %e, "Details", %d, "Zap", %z, "Next", 13 dlg% = Dialog  if dlg% = 9 if pageNo% > 0 pageNo% = pageNo% - 1 else gIPrint "On first page" endif elseif dlg% = 13 if (pageNo% + 1) * FieldsPerPage% < nFields% pageNo% = pageNo% + 1 else gIPrint "On last page" endif elseif dlg% = %a AddField%:( pageNo% * FieldsPerPage% + 1 ) elseif dlg% = %d ListContactFields: elseif dlg% = 8 DeleteField%:( pageNo% * FieldsPerPage% + 1 ) elseif dlg% = %v MoveField%:( pageNo% * FieldsPerPage% + 1 )  elseif dlg% = %e EditField%:( pageNo% * FieldsPerPage% + 1 ) elseif dlg% = %z CODeleteContact&: break elseif dlg% = 0 break endif endwhendpREM -------------------------------------------------------------REM Add a field to the current contact item.REMREM Note that a contact item must be 'open' before changes canREM recorded; call COOpenContact:( id& ) or COOpenCurrentContact:REM to do this. Changes made to the "in-memory" copy can then beREM saved back to the database with COCloseContact:, or thrownREM away with COUnlockContact:. Closing the database will alsoREM discard changes.REMREM COCloseContactReRead: and COUnlockContactReRead: can also beREM used; these leave a copy of the updated or original contactREM "in-memory" (though not open for update).REM -------------------------------------------------------------REM When adding a field, you need to specify the label (name), andREM a value (can be blank). Ideally you should specify a type andREM mapping. Additional types can be used to clarify a field'sREM use (e.g. dfferent types of 'phone numbers). See a 'Detail'REM listing for examples.REM -------------------------------------------------------------REM If a new field is added to an individual contact, it SEEMS toREM be forced to be AFTER all fields in the template; I don't knowREM if there's a way around this, or if it is 'normal' behaviour.REM -------------------------------------------------------------REM Fields can be added to the Template using this function; inREM this case, they can be added anywhere.REM -------------------------------------------------------------REM NOTE ALSO that if a field is added to a contact only (and notREM the template): it will appear, and can be edited within theREM Contacts application; HOWEVER, if its value is set to an emptyREM string, the field will be removed. It appears that any NEWREM field is best added to the template.REM -------------------------------------------------------------proc AddField%:( initial% ) local label$(255) local value$(255) local field%, page%, i%, type% dInit "Add field" dEdit label$, "New field", 20 dEdit value$, "New value", 20 REM ----------------------------------------------------------- REM Display choices for field type. REM ----------------------------------------------------------- i% = 1 while i% < UidTypeArraySize% dChoice type%, "Choice", UidName$:( UidTypeArray&( i% ) ) + ",..." i% = i% + 1 endwh dChoice type%, "Choice", "" REM ----------------------------------------------------------- REM Set initial value of the "insert after" field to be the REM first on the current page of fields (needs "+1" because of REM the "insert before first" option. REM ----------------------------------------------------------- field% = initial% + 1 REM ----------------------------------------------------------- REM Ideally, the block below, which is used several times, REM should be a function. However, OPL doesn't allow Dialog REM construction to occur across procedure boundaries. REM This can be done if I switch to using AldurDlg. REM ----------------------------------------------------------- dChoice field%, "Position after", ",..." i% = 1 while i% < COContactFieldCount&: dChoice field%, "", COContactFieldLabelAt$:( i% ) + ",..." i% = i% + 1 endwh dChoice field%, "", COContactFieldLabelAt$:( i% ) REM ----------------------------------------------------------- page% = 2 dChoice page%, "Show on", "No page,'Home' page,'Work' page,'Other' page" if Dialog = 0 return KFalse% endif REM ----------------------------------------------------------- REM Create the field; set its label, value, type (from the REM dialog) and a default mapping. The "UserFlags" setting is REM used by the Contacts application to determine on which page REM is should appear. Finally, insert the newly-created field REM at the requested position in the field-set. REM REM Note: COContactFieldInsert:() would more precisely be called REM 'COContactFieldInsertAfter:()'; a value of zero puts the new REM field at the beginning of the item (subject to the rules REM above), a value of 5 would put it after the fifth field (it REM would become the sixth; shuffling all the rest down). REM REM As noted, however, fields added to a contact rather than to REM the template seem to be forced to be after all template- REM defined fields; specifying an insert position that is less REM than the number of template-derived fields just results in REM the field being inserted after the last template-defined REM field. REM ----------------------------------------------------------- COOpenCurrentContact: COContactFieldCreate: COContactFieldSetLabel:( label$ ) COContactFieldSetText:( value$ ) COContactFieldDisable:( KFalse% ) COContactFieldAddType:( UidTypeArray&( type% ) ) COContactFieldSetMapping:( KIntCntFieldVCardMapUnusedN ) COContactFieldSetUserFlags:( page% - 1 ) COContactFieldInsert:( field% - 1 ) COCloseContactReRead: return KTrue%endpREM -------------------------------------------------------------REM Delete a field from the current contact item.REMREM !! IMPORTANT !!REM If you delete a field from the template that has a non-emptyREM value in one or more contact items, then the Contact engineREM is liable to panic when that/those contact(s) are accessed.REM If the database gets in this state, it can be very hard toREM repair things -- the Contact Application cannot delete itREM because it needs to display the record first. You POSSIBLYREM can delete the record using CODeleteContact: IF YOU KNOW THEREM ID. If not you may have to revert to a previous version ofREM the contacts database, IF YOU HAVE ONE!REM -------------------------------------------------------------REM Note that if you use the "Set-up Labels" screen of theREM Contacts application (which essentially edits the templateREM record), "deleting" a field does not really remove it fromREM the template, it just marks it as DISABLED. I guess at leastREM part of the reason for this is to avoid the problem above.REM -------------------------------------------------------------proc DeleteField%:( initial% ) local field% local i% field% = initial% dInit "Delete field" REM ----------------------------------------------------------- REM Ideally should be a function... REM ----------------------------------------------------------- i% = 1 while i% < COContactFieldCount&: dChoice field%, "Field to delete", COContactFieldLabelAt$:( i% ) + ",..." i% = i% + 1 endwh dChoice field%, "", COContactFieldLabelAt$:( i% ) REM ----------------------------------------------------------- dButtons "Cancel", -$11b, "Delete", $10d if Dialog = 0 return KFalse% endif REM ----------------------------------------------------------- REM Field numbers are 1..COContactFieldCount&: inclusive. REM ----------------------------------------------------------- COOpenCurrentContact: COContactFieldDeleteAt:( field% ) COCloseContactReRead: return KTrue%endpREM -------------------------------------------------------------REM Move a field within the current contact item.REMREM As noted for COContactFieldInsert:(), any fields added toREM individual contacts seem to be placed after all template-REM derived fields. COContactFieldMove:() cannot be used toREM break this rule -- you can rearrange the order of any non-REM template-derived fields, but they will still only appearREM after all template-derived field.REMREM Also, for an individual contact, you cannot alter the orderREM of the template-derived fields. To achieve this, you need toREM alter the template record itself.REMREM (In other words, fields defined in the template ALWAYS appearREM in template-order for all contacts, and ALWAYS appear ahead ofREM any contact-specific fields).REM -------------------------------------------------------------proc MoveField%:( initial% ) local field%, newField% local i% field% = initial% dInit "Move field" REM ----------------------------------------------------------- REM Ideally should be a function... REM ----------------------------------------------------------- i% = 1 while i% < COContactFieldCount&: dChoice field%, "Field to move", COContactFieldLabelAt$:( i% ) + ",..." i% = i% + 1 endwh dChoice field%, "", COContactFieldLabelAt$:( i% ) REM ----------------------------------------------------------- REM ----------------------------------------------------------- REM Ideally should be a function... REM ----------------------------------------------------------- i% = 1 while i% < COContactFieldCount&: dChoice newField%, "", COContactFieldLabelAt$:( i% ) + ",..." i% = i% + 1 endwh dChoice newField%, "", COContactFieldLabelAt$:( i% ) REM ----------------------------------------------------------- dButtons "Cancel", -$11b, "Move", $10d if Dialog = 0 return KFalse% endif REM ----------------------------------------------------------- REM Field numbers are 1..COContactFieldCount&: inclusive. REM The first (FROM) field is moved to the (current) position REM of the second (TO) field. REM REM If the FROM field was originally BEFORE the TO field, then REM all the fields from FROM+1 to TO are shuffled up and the REM FROM field will now be AFTER the TO field (i.e. in the TO REM field's original position). Fields before FROM and after REM the original TO are not affected. REM REM e.g. if the fields are: A B C D E F G H I REM COContactFieldMove:(3,6) gives: A B D E F C G H I REM REM If the FROM field was originally AFTER the TO field, then REM all the fields from TO to FROM-1 are shuffled down and the REM FROM field will now be BEFORE the TO field (again in its REM original position). Fields before TO and after the original REM TO are not affected. REM REM e.g. if the fields are: A B C D E F G H I REM COContactFieldMove:(6,3) gives: A B F C D E G H I REM ----------------------------------------------------------- COOpenCurrentContact: COContactFieldMove:( field%, newField% ) COCloseContactReRead: return KTrue%endpREM -------------------------------------------------------------REM Edits a field's value, its label and/or the flags.REMREM Nothing unusual here; select the field you want to edit, thenREM change its value and/or label. Neither change is appliedREM until the main dialog is confirmed.REMREM NOTE: for some reason, I don't seem able to adjust the HIDDENREM or READ-ONLY flags of a field; I don't yet know if I'mREM doing something wrong or if these can't be altered.REM -------------------------------------------------------------proc EditField%:( initial% ) local field%, value$(255), name$(255), dlg% local hid%, r_o%, dis%, usr%, syn%, flags& local date&, time& local nameChanged%, flagsChanged% local i% dInit "Edit field" field% = initial% REM ----------------------------------------------------------- REM Ideally should be a function... REM ----------------------------------------------------------- i% = 1 while i% < COContactFieldCount&: dChoice field%, "Field to edit", COContactFieldLabelAt$:( i% ) + ",..." i% = i% + 1 endwh dChoice field%, "", COContactFieldLabelAt$:( i% ) REM ----------------------------------------------------------- dButtons "Cancel", -$11b, "Edit", $10d if Dialog = 0  return KFalse% endif REM ----------------------------------------------------------- REM Once a field has been selected with an 'COContactField...At' REM variant, other accesses can be without the '...At'. REM ----------------------------------------------------------- if COContactFieldStorageAt%:( field% ) = KStorageTypeText% value$ = COContactFieldText$: elseif COContactFieldStorage%: = KStorageTypeDateTime% date& = COContactFieldDate&: time& = COContactFieldTime&: else gIPrint "Not a text field" return KFalse% endif name$ = COContactFieldLabel$: while KTrue% if nameChanged% dInit "Edit field (was called " + COContactFieldLabel$: + ")" else dInit "Edit field" endif if COContactFieldStorage%: = KStorageTypeText% dEdit value$, name$, 20 else dDate date&, "Date", 0, 1000000 dTime time&, "Time", 0, 0, &1517F endif dButtons "Cancel", -$11b, "Edit flags", %f, "Edit name", %e, "Update", 13 dlg% = Dialog if dlg% = 0 return KFalse% elseif dlg% = %e if nameChanged% dInit "Edit field name (was " + COContactFieldLabel$: + ")" else dInit "Edit field name" endif dEdit name$, "Field name", 20 dButtons "Cancel", -$11b, "Update", 13 if Dialog nameChanged% = KTrue% endif elseif dlg% = %f dInit "Edit flags for '" + name$ + "'" hid% = COContactFieldIsHidden%: r_o% = COContactFieldIsReadOnly%: dis% = COContactFieldIsDisabled%: usr% = COContactFieldIsUserAdded%: syn% = COContactFieldIsSynchronize%: flags& = COContactFieldUserFlags&: dCheckBox hid%, "Hidden" dCheckBox r_o%, "Read-only" dCheckBox dis%, "Disabled" dCheckBox usr%, "User added" dCheckBox syn%, "Synchronize" dLong flags&, "User flags", &80000000, &7fffffff if Dialog flagsChanged% = KTrue% endif elseif dlg% = 13 break endif endwh COOpenCurrentContact: if COContactFieldStorageAt%:( field%) = KStorageTypeText% COContactFieldSetText:( value$ ) else COContactFieldSetDate:( date& ) COContactFieldSetTime:( time& ) endif if nameChanged% COContactFieldSetLabel:( name$ ) endif if flagsChanged% COContactFieldSetHidden:( hid% ) COContactFieldSetReadOnly:( r_o% ) COContactFieldDisable:( dis% ) COContactFieldSetUserAdded:( usr% ) COContactFieldSetSynchronize:( syn% ) COContactFieldSetUserFlags:( flags& ) endif COCloseContactReRead: return KTrue%endpREM -------------------------------------------------------------REM Produces a list of all the fields in the Contact Template.REM -------------------------------------------------------------proc ExamineContactTemplate: Cls: COOpenContactFile:( CurrentDatabase$ ) COReadContactTemplate: ListContactFields: COCloseContactTemplate: COCloseContactFile:endpREM -------------------------------------------------------------REM List the field structure of the current contact item. ThisREM can either be a normal contact or the Contact Template.REMREM The Line%: function pauses after a full screen of info andREM displays a "[more]" prompt. Pressing 'Q' or ESC will abandonREM the listing; any other key continues.REM -------------------------------------------------------------proc ListContactFields: local field%, nFields%, type% nFields% = COContactFieldCount&: Line%: : print "Field count", nFields% Line%: : print "Contact ID:", COContactID&:; if COContactID&: = 0 print " (the Contact Template)" else print endif Line%: : print Line%: : print "FieldNo Field Name and Type/Mapping details" Line%: : print "------- -----------------------------------" field% = 1 while field% <= nFields% COContactFieldArrayAt:( field% ) if Line%: : break : endif print Gen$( field%, -7 ); " "; COContactFieldLabel$:; REM --------------------------------------------------------- REM Print 'flags' for each field: REM hid Field is hidden. REM r/o Field is read-only. REM dis Field is disabled (not shown by Contacts). REM syn Field needs to be synchronised. REM usr Field is user-added. REM --------------------------------------------------------- if COContactFieldIsHidden%: print " [hid]"; endif if COContactFieldIsReadOnly%: print " [r/o]"; endif if COContactFieldIsDisabled%: print " [dis]"; endif if COContactFieldIsSynchronize%: print " [syn]"; endif if COContactFieldIsUserAdded%: print " [usr]"; endif REM --------------------------------------------------------- REM The Contacts Engine holds a 32-bit 'UserFlags' value for REM each contact field, that can be used for anything. The REM Contacts Application uses them (or possibly the bottom two REM bits) to indicate which page (Home/Work/Other) a field REM sshould appear on. REM --------------------------------------------------------- print " UserFlags="; COContactFieldUserFlags&:, ContactUserFlags$:( COContactFieldUserFlags&: ) REM --------------------------------------------------------- REM We're about to get "content info" for the field; details REM of the field-type and the VCard-mappings. For 'safety' REM (especially when first developing this program/the OPX) REM I fill them the array they'll be read into with dummy REM values. REM --------------------------------------------------------- type% = 1 while type% <= 20 ArrayData&( type% ) = &abcd0000 + type% type% = type% + 1 endwh REM --------------------------------------------------------- REM Read the field's 'content'. Pass in the address of a REM long-integer array (i.e. '&'). On return, the first REM element will contain the total number of valid entries REM (including itself); the remaining elements hold the UIDs REM of the types/mappings. REM REM The first entry seems to be the VCard Mapping, e.g.: REM KIntCntFieldVCardMapUnusedN REM KIntCntFieldVCardMapTEL REM KIntCntFieldVCardMapEMAILINET REM The second entry seems to be the field-type; this seems REM to be the one most used by the Contacts Application. E.g.: REM KUidCntFieldAddress REM KUidCntFieldCompanyName REM KUidCntFieldPhoneNumber REM KUidCntFieldGivenName REM KUidCntFieldFamilyName REM Subsequent entries, if used, seem to clarify the VCard REM mapping. E.g., KIntCntFieldVCardMapTEL in the first entry REM might be combined with one or more of: REM KIntCntFieldVCardTypeWORK REM KIntCntFieldVCardTypeHOME REM KIntCntFieldVCardTypeFAX REM KIntCntFieldVCardTypeCELL REM KIntCntFieldVCardTypePAGER REM So: REM MapTEL + TypeHOME would a home phone number; REM MapTEL + TypeHOME + TypeCELL would be a personal mobile; REM MapTEL + TypeWORK + TypeFAX would be a company fax. REM --------------------------------------------------------- COContactFieldContent:( ArrayHandle& ) if Line%: : return : endif print " [1] = "; ArrayData&(1), "content elements" type% = 2 while type% <= ArrayData&(1) if Line%: : return : endif print " ["; type%; "] = "; Hex$( ArrayData&( type% ) ), UidName$:( ArrayData&( type% ) ) type% = type% + 1 endwh if Line%: : return : endif : print field% = field% + 1 endwh Done:endpREM -------------------------------------------------------------REM This just lists the first/last name of all records in theREM database.REMREM This just cycles through all IDs from 1 to the number ofREM records; sometimes there will be "missing" records; I thinkREM these are IDs that have been deleted in the past but don't getREM reused (possible so as not to confuse synchronisation?).REM I DON'T think these are gaps in the database, since theyREM remain after compaction.REMREM NOTE: If the First and Last name fields aren't the same asREM in my database, you'll have to adjust the constants atREM the top of the file.REMREM ** I want to do a bit more with the 'FindField' function;REM when done, this can be mad better.REM -------------------------------------------------------------proc ListDefaultContacts: Cls: COOpenContactFile:( CurrentDatabase$ ) COReadContactTemplate: label$ = COContactFieldLabelAt$:( KFirstNameField% ) + ", " + COContactFieldLabelAt$:( KFirstNameField% ) Line%: : print "Listing contacts ("; label$; ") [unsorted] ["; COCountContacts&:; " item(s)]" Line%: : print Line%: : print "ContactID RecordNo Details" Line%: : print "--------- -------- -------" contact& = 0 id& = 0 while contact& <= COCountContacts&: if Line%: : break : endif : print Gen$( id&, -9 ); " ";  OnErr NotFound:: COReadContact:( id& ) NotFound::OnErr Off if ERR = 0 contact& = contact& + 1 print Gen$( contact&, -8); " "; COContactFieldTextAt$:( KFirstNameField% ), COContactFieldTextAt$:( KFirstNameField% ), data$ = COContactFieldTextAt$:( 18 ) if data$ <> "" print "("; data$; ")"; endif print elseif ERR = KErrNotExists% print "" Trap Raise 0 else Raise ERR endif id& = id& + 1 endwh Line%: : print Line%: : print "Closing..." COCloseContactFile: More%:endpREM -------------------------------------------------------------REM List contacts matching a given filter.REMREM The search string given will be looked for in the fieldsREM identified in 'ArrayData'.REM -------------------------------------------------------------proc FilterDefaultContacts: local contactCount& Cls: COOpenContactFile:( CurrentDatabase$ ) while KTrue% dInit "Filter contacts" dText "", "Enter an empty string for all records." dEdit searchFor$, "Containing", 20 if Dialog = 0 break endif Cls: COReadContactTemplate: label$ = COContactFieldLabelAt$:( KFirstNameField% ) + ", " + COContactFieldLabelAt$:( KFirstNameField% ) ArrayData&(1) = 3 ArrayData&(3) = KUidCntFieldGivenName ArrayData&(2) = -KUidCntFieldFamilyName COSortContactFile:( ArrayHandle& ) contactCount& = COFindContact&:( searchFor$, ArrayHandle& ) Line%: : print "Listing contacts ("; label$; ") ["; contactCount&; " item(s)]" Line%: : print Line%: : print "ContactID RecordNo Details" Line%: : print "--------- -------- -------" contact& = 1 while contact& <= contactCount& COSortedContactFileAt:( contact& ) data$ = COContactFieldTextAt$:( KFirstNameField% ) + " " + COContactFieldTextAt$:( KFirstNameField% ) if Line%: : break : endif : print Gen$( COContactID&:, -9 ); " "; Gen$( contact&, -8); " "; data$ contact& = contact& + 1 endwh endwh Line%: : print Line%: : print "Closing..." COCloseContactFile:endpREM -------------------------------------------------------------REM I want to do a bit more work on the FindField and function,REM and add others. At the moment, it finds an EXACTmatch only.REM -------------------------------------------------------------proc FindField: local field% COOpenContactFile:( CurrentDatabase$ ) COReadContact:( 1 ) ArrayData&(1) = 5 ArrayData&(2) = KIntCntFieldVCardMapTEL ArrayData&(3) = KUidCntFieldPhoneNumber ArrayData&(4) = KIntCntFieldVCardTypeHOME ArrayData&(5) = KIntCntFieldVCardTypeCELL Trap Raise 0 OnErr NotFound:: field% = COContactFieldFind%:( ArrayHandle& ) COContactFieldArrayAt:( field% ) print "Found field "; field%; ", "; COContactFieldLabel$:; ": "; COContactFieldText$:NotFound:: if ERR print "Error", ERR; ": "; ERR$(ERR) print "Field specified not found." Trap Raise 0 endif COCloseContactFile:endpREM -------------------------------------------------------------REM Functions to map UID values to and from names.REMREM UIDs (32-bit numbers) are used to identify field types andREM mappings.REMREM UidName$:( uid& )REM Will take a UID from a field's definition and return aREM string of its equivalent OPL constant definition (e.g. forREM the number &1000130C it returns "KUidCntFieldAddress").REMREM ContactUserFlags$:( flags& )REM Turn a field's 'UserFlags' value into a descriptive string.REM The Contacts Application uses this value to identify onREM which page the field should be displayed (Home/Work/Other).REMREM BuildUidArrays:REM Builds an array of field-type UIDs that are used (togetherREM with the UidName$:() function) during the AddField%: dialog.REM -------------------------------------------------------------proc UidName$:( uid& ) vector 1 + uid& - KUidCntFieldAddress u0001, u0002, u0003 endv vector 1 + uid& - KUidCntFieldGivenName u0101, u0102 endv vector 1 + uid& - KUidCntFieldAdditionalName u0201, u0202, u0203, u0204, u0205, u0206, u0207, u0208, u0209 endv vector 1 + uid& - KIntCntFieldVCardTypeBBS u0301, u0302, u0303, u0304, u0305, u0306, u0307, u0308, u0309 u0310 endv vector 1 + uid& - KIntCntFieldVCardTypePREF u0401, u0402, u0403 endv vector 1 + uid& - KIntCntFieldVCardTypeDOM u0501 endv vector 1 + uid& - KUidCntFieldNote u0601, u0602, u0603, u0604, u0605, u0606, u0607, u0608, u0609 u0610, u0611, u0612, u0613, u0614, u0615, u0616, u0617, u0618 u0619, u0620, u0621, u0622, u0623, u0624, u0625, u0626, u0627 endv vector 1 + uid& - KIntCntFieldVCardMapPOSTOFFICE u0701, u0702, u0703, u0704, u0705, u0706 endv vector 1 + uid& - KUidCntFieldPostOffice u0801, u0802, u0803, u0804, u0805, u0806 endv  return "<>" u0001:: return "KUidCntFieldAddress" u0002:: return "KUidCntFieldCompanyName" u0003:: return "KUidCntFieldPhoneNumber" u0101:: return "KUidCntFieldGivenName" u0102:: return "KUidCntFieldFamilyName" u0201:: return "KUidCntFieldAdditionalName" u0202:: return "KUidCntFieldSuffixName" u0203:: return "KUidCntFieldPrefixName" u0204:: return "KUidCntFieldHidden" u0205:: return "KUidCntFieldEMail" u0206:: return "KUidCntFieldMsg" u0207:: return "KUidCntFieldSms" u0208:: return "KUidCntFieldFax" u0209:: return "KUidCntFieldDefinedText" u0301:: return "KIntCntFieldVCardTypeBBS" u0302:: return "KIntCntFieldVCardTypeMODEM" u0303:: return "KIntCntFieldVCardTypeCAR" u0304:: return "KIntCntFieldVCardTypeISDN" u0305:: return "KIntCntFieldVCardTypeVIDEO" u0306:: return "KIntCntFieldVCardTypeWORK" u0307:: return "KIntCntFieldVCardTypeHOME" u0308:: return "KIntCntFieldVCardTypeMSG" u0309:: return "KIntCntFieldVCardTypeVOICE" u0310:: return "KIntCntFieldVCardTypeFAX" u0401:: return "KIntCntFieldVCardTypePREF" u0402:: return "KIntCntFieldVCardTypeCELL" u0403:: return "KIntCntFieldVCardTypePAGER" u0501:: return "KIntCntFieldVCardTypeDOM" u0601:: return "KUidCntFieldNote" u0602:: return "KIntCntFieldVCardMapADR" u0603:: return "KIntCntFieldVCardMapAGENT" u0604:: return "KIntCntFieldVCardMapBDAY" u0605:: return "KIntCntFieldVCardMapEMAILINET" u0606:: return "KIntCntFieldVCardMapGEO" u0607:: return "KIntCntFieldVCardMapLABEL" u0608:: return "KIntCntFieldVCardMapLOGO" u0609:: return "KIntCntFieldVCardMapMAILER" u0610:: return "KIntCntFieldVCardMapNOTE" u0611:: return "KIntCntFieldVCardMapORG" u0612:: return "KIntCntFieldVCardMapPHOTO" u0613:: return "KIntCntFieldVCardMapROLE" u0614:: return "KIntCntFieldVCardMapSOUND" u0615:: return "KIntCntFieldVCardMapTEL" u0616:: return "KIntCntFieldVCardMapTELFAX" u0617:: return "KIntCntFieldVCardMapTITLE" u0618:: return "KIntCntFieldVCardMapURL" u0619:: return "KIntCntFieldVCardMapUnusedN" u0620:: return "KIntCntFieldVCardMapUnusedFN" u0621:: return "KIntCntFieldVCardMapNotRequired" u0622:: return "KIntCntFieldVCardMapUnknownXDash" u0623:: return "KIntCntFieldVCardMapUnknown" u0624:: return "KIntCntFieldVCardMapUID" u0625:: return "KUidCntFieldBirthday" u0626:: return "KUidCntFieldUrl" u0627:: return "KUidCntFieldStorageInline" u0701:: return "KIntCntFieldVCardMapPOSTOFFICE" u0702:: return "KIntCntFieldVCardMapEXTENDEDADR" u0703:: return "KIntCntFieldVCardMapLOCALITY" u0704:: return "KIntCntFieldVCardMapREGION" u0705:: return "KIntCntFieldVCardMapPOSTCODE" u0706:: return "KIntCntFieldVCardMapCOUNTRY" u0801:: return "KUidCntFieldPostOffice" u0802:: return "KUidCntFieldExtendedAddress" u0803:: return "KUidCntFieldLocality" u0804:: return "KUidCntFieldRegion" u0805:: return "KUidCntFieldPostCode" u0806:: return "KUidCntFieldCountry"endpproc ContactUserFlags$:( flags& ) vector 1 + flags& f00, f01, f02, f03 endv  return ""  f00:: return "" f01:: return "(appears on 'Home' page)" f02:: return "(appears on 'Work' page)" f03:: return "(appears on 'Other' page)"endpproc BuildUidArrays: local i% i% = 1 UidTypeArray&( i% ) =&1000130C : i% = i% + 1 UidTypeArray&( i% ) =&1000130D : i% = i% + 1 UidTypeArray&( i% ) =&1000130E : i% = i% + 1 UidTypeArray&( i% ) =&1000137C : i% = i% + 1 UidTypeArray&( i% ) =&1000137D : i% = i% + 1 UidTypeArray&( i% ) =&1000178A : i% = i% + 1 UidTypeArray&( i% ) =&1000178B : i% = i% + 1 UidTypeArray&( i% ) =&1000178C : i% = i% + 1 UidTypeArray&( i% ) =&1000178D : i% = i% + 1 UidTypeArray&( i% ) =&1000178E : i% = i% + 1 UidTypeArray&( i% ) =&1000178F : i% = i% + 1 UidTypeArray&( i% ) =&10001790 : i% = i% + 1 UidTypeArray&( i% ) =&10001791 : i% = i% + 1 UidTypeArray&( i% ) =&10001792 : i% = i% + 1 UidTypeArray&( i% ) =&1000401C : i% = i% + 1 UidTypeArray&( i% ) =&10004034 : i% = i% + 1 UidTypeArray&( i% ) =&10004035 : i% = i% + 1 UidTypeArray&( i% ) =&10004036 : i% = i% + 1 UidTypeArray&( i% ) =&10004DF4 : i% = i% + 1 UidTypeArray&( i% ) =&10004DF5 : i% = i% + 1 UidTypeArray&( i% ) =&10004DF6 : i% = i% + 1 UidTypeArray&( i% ) =&10004DF7 : i% = i% + 1 UidTypeArray&( i% ) =&10004DF8 : i% = i% + 1 UidTypeArray&( i% ) =&10004DF9 : i% = i% + 1 UidTypeArray&( i% ) =&00000000 : i% = i% + 1 UidTypeArraySize% = i% - 1endpproc RepairContactsFile: Line%: : print "Opening file..." : Get COOpenContactFile:( CurrentDatabase$ ) Line%: : print "Repairing..." : Get COTest: Line%: : print "Closing..." : Get COCloseContactFile: Line%: : print "Closed." : Getendp\cefd\cefd.A*Texted.app 7mcU*\cd!REM -----------------------------------------------------------REM AldurContact.OXH version 0.01REM Header File for AldurContact.OPXREM Copyright (c) Graham L. Holden, 2001-4. All rights reserved.REM OPX Skeleton adapted from TOPX in Symbian's SDKREM -----------------------------------------------------------REM -----------------------------------------------------------REM OPX identifier and versionConst KUidOpxTemplate& = &101f9befConst KOpxTemplateVersion% = $0001REM -----------------------------------------------------------REM Field UIDsConst KUidCntFieldAddress =&1000130CConst KUidCntFieldCompanyName =&1000130DConst KUidCntFieldPhoneNumber =&1000130EConst KUidCntFieldGivenName =&1000137CConst KUidCntFieldFamilyName =&1000137DConst KUidCntFieldAdditionalName =&1000178AConst KUidCntFieldSuffixName =&1000178BConst KUidCntFieldPrefixName =&1000178CConst KUidCntFieldHidden =&1000178DConst KUidCntFieldEMail =&1000178EConst KUidCntFieldMsg =&1000178FConst KUidCntFieldSms =&10001790Const KUidCntFieldFax =&10001791Const KUidCntFieldDefinedText =&10001792Const KUidCntFieldNote =&1000401CConst KUidCntFieldBirthday =&10004034Const KUidCntFieldUrl =&10004035Const KUidCntFieldStorageInline =&10004036Const KUidCntFieldPostOffice =&10004DF4Const KUidCntFieldExtendedAddress =&10004DF5Const KUidCntFieldLocality =&10004DF6Const KUidCntFieldRegion =&10004DF7Const KUidCntFieldPostCode =&10004DF8Const KUidCntFieldCountry =&10004DF9Const KUidCntFieldNone =&00000000REM -----------------------------------------------------------REM Field VCard typeConst KIntCntFieldVCardTypeWORK =&100039DAConst KIntCntFieldVCardTypeHOME =&100039DBConst KIntCntFieldVCardTypeMSG =&100039DCConst KIntCntFieldVCardTypeVOICE =&100039DDConst KIntCntFieldVCardTypeFAX =&100039DEConst KIntCntFieldVCardTypePREF =&10003E70Const KIntCntFieldVCardTypeCELL =&10003E71Const KIntCntFieldVCardTypePAGER =&10003E72Const KIntCntFieldVCardTypeBBS =&100039D5Const KIntCntFieldVCardTypeMODEM =&100039D6Const KIntCntFieldVCardTypeCAR =&100039D7Const KIntCntFieldVCardTypeISDN =&100039D8Const KIntCntFieldVCardTypeVIDEO =&100039D9Const KIntCntFieldVCardTypeDOM =&10003E80REM -----------------------------------------------------------REM Field VCard mappingsConst KIntCntFieldVCardMapADR =&1000401DConst KIntCntFieldVCardMapAGENT =&1000401EConst KIntCntFieldVCardMapBDAY =&1000401FConst KIntCntFieldVCardMapEMAILINET =&10004020Const KIntCntFieldVCardMapGEO =&10004021Const KIntCntFieldVCardMapLABEL =&10004022Const KIntCntFieldVCardMapLOGO =&10004023Const KIntCntFieldVCardMapMAILER =&10004024Const KIntCntFieldVCardMapNOTE =&10004025Const KIntCntFieldVCardMapORG =&10004026Const KIntCntFieldVCardMapPHOTO =&10004027Const KIntCntFieldVCardMapROLE =&10004028Const KIntCntFieldVCardMapSOUND =&10004029Const KIntCntFieldVCardMapTEL =&1000402AConst KIntCntFieldVCardMapTELFAX =&1000402BConst KIntCntFieldVCardMapTITLE =&1000402CConst KIntCntFieldVCardMapURL =&1000402DConst KIntCntFieldVCardMapUnusedN =&1000402EConst KIntCntFieldVCardMapUnusedFN =&1000402FConst KIntCntFieldVCardMapNotRequired =&10004030Const KIntCntFieldVCardMapUnknownXDash =&10004031Const KIntCntFieldVCardMapUnknown =&10004032Const KIntCntFieldVCardMapUID =&10004033Const KIntCntFieldVCardMapPOSTOFFICE =&10004DEAConst KIntCntFieldVCardMapEXTENDEDADR =&10004DEBConst KIntCntFieldVCardMapLOCALITY =&10004DECConst KIntCntFieldVCardMapREGION =&10004DEDConst KIntCntFieldVCardMapPOSTCODE =&10004DEEConst KIntCntFieldVCardMapCOUNTRY =&10004DEFREM -----------------------------------------------------------REM Field storage types.REMREM Only the first and last are supported by the OPX(and IREM think by the Contacts Application).Const KStorageTypeText% = 0Const KStorageTypeStore% = 1Const KStorageTypeContactItemId% = 2Const KStorageTypeDateTime% = 3REM -----------------------------------------------------------REM Declaration of the OPX and its entry points.REMREM Most of the entry-points follow CONTACT.OPX; where I'veREM added "close-cousins" (e.g. to complement OpenContact:( id& )REM I've added OpenCurrentContact:, as well as all the REM COContactFieldXXXAt: variants), these will be +100 over theREM original. Completely new functions will be 200 onwards.Declare OPX AldurContact, KUidOpxTemplate&, KOpxTemplateVersion% COTest: : 0 COCreateContactFile:( aFileName$ ) : 1 COOpenContactFile:( aFileName$ ) : 2 COCloseContactFile: : 3 COCountContacts&: : 4 COSortContactFile:( aMappingArray& ) : 5 COFindContact&:( aString$, aMappingArray& ) : 6 COSortedContactFileAt:( aIndex& ) : 7 COContactId&: : 8 COReadContact:( aContactItemId& ) : 9 COOpenContact:( aContactItemId& ) : 10 COOpenCurrentContact: :110 COCloseContact: : 11 COUnlockContact: :111 COCreateContact: : 12 COCreateContactEmpty: :112 COAddNewContact: : 13 CODeleteContact: : 14 COOpenContactTemplate: : 15 COCloseContactTemplate: : 16 COContactFieldDisable:( aBool% ) : 17 COContactFieldDisableAt:( aFieldIndex&, aBool% ) :117 COContactFieldIsDisabled%: : 18 COContactFieldIsDisabledAt%:( aFieldIndex& ) :118 COSetContactHidden:( aHidden% ) : 19 COIsContactHidden%: : 20 COSetContactSystem:( aSystem% ) : 21 COIsContactSystem%: : 22 COCompressContactFile: : 23 COCompressNeeded%: : 24 COContactFieldCount&: : 25 COContactFieldArrayAt:( aFieldIndex& ) : 26 COContactFieldFind%:( aTypeArrayHandle& ) : 27 COContactFieldReset: : 28 COContactFieldCreate: : 29 COContactFieldCreateDateTime: :129 COContactFieldInsert:( aFieldIndex& ) : 30 COContactFieldAdd: : 31 COContactFieldDelete: : 32 COContactFieldDeleteAt:( aFieldIndex& ) :132 COContactFieldMove:( aPosFrom&, aPosTo& ) : 33 COContactFieldContent:( aContentTypeArray& ) : 34 COContactFieldContentAt:( aFieldIndex&, aContentTypeArray& ):134 COContactFieldSetHidden:( aHidden% ) : 35 COContactFieldSetHiddenAt:( aFieldIndex&, aHidden% ) :135 COContactFieldIsHidden%: : 36 COContactFieldIsHiddenAt%:( aFieldIndex& ) :136 COContactFieldSetReadOnly:( aReadOnly% ) : 37 COContactFieldSetReadOnlyAt:( aFieldIndex&, aReadOnly% ) :137 COContactFieldIsReadOnly%: : 38 COContactFieldIsReadOnlyAt%:( aFieldIndex& ) :138 COContactFieldSetLabel:( aLabel$ ) : 39 COContactFieldSetLabelAt:( aFieldIndex&, aLabel$ ) :139 COContactFieldLabel$: : 40 COContactFieldLabelAt$:( aFieldIndex& ) :140 COContactFieldSetMapping:( aMapping& ) : 41 COContactFieldSetMappingAt:( aFieldIndex&, aMapping& ) :141 COContactFieldAddType:( aType& ) : 42 COContactFieldAddTypeAt:( aFieldIndex&, aType& ) :142 COContactFieldSetText:( aString$ ) : 43 COContactFieldSetTextAt:( aFieldIndex&, aString$ ) :143 COContactFieldSetLong:( aStringAddr&, aLength& ) : 44 COContactFieldSetLongAt:( aFieldIndex&, aStringAddr&, aLength& ) :144 COContactFieldText$: : 45 COContactFieldTextAt$:( aFieldIndex& ) :145 COContactFieldLength&: : 46 COContactFieldLengthAt&:( aFieldIndex& ) :146 COContactFieldLong:( aBufHandle& ) : 47 COContactFieldLongAt:( aFieldIndex&, aBufHandle& ) :147 COReadContactTemplate: :200 COContactFieldSetSynchronize:( aSynchronize% ) :201 COContactFieldSetSynchronizeAt:( aFieldIndex&, aSynchronize% ):202 COContactFieldIsSynchronize%: :203 COContactFieldIsSynchronizeAt%:( aFieldIndex& ) :204 COContactFieldSetUserAdded:( aUserAdded% ) :205 COContactFieldSetUserAddedAt:( aFieldIndex&, aUserAdded% ) :206 COContactFieldIsUserAdded%: :207 COContactFieldIsUserAddedAt%:( aFieldIndex& ) :208 COContactFieldSetUserFlags:( aUserFlags& ) :209 COContactFieldSetUserFlagsAt:( aFieldIndex&, aUserFlags& ) :210 COContactFieldUserFlags&: :211 COContactFieldUserFlagsAt&:( aFieldIndex& ) :212 COCloseContactReRead: :213 COUnlockContactReRead: :214 COGetSystemDatabase$: :215 COContactFieldStorage%: :216 COContactFieldStorageAt%:( aFieldIndex&) :217 COContactFieldSetDateTime:( aDateTime& ) :220 COContactFieldSetDate:( aDaysSince1900& ) :221 COContactFieldSetTime:( aSecsSinceMidnight& ) :222 COContactFieldSetDateTimeAt:( aFieldIndex&, aDateTime& ) :223 COContactFieldSetDateAt:( aFieldIndex&, aDaysSince1900& ) :224 COContactFieldSetTimeAt:( aFieldIndex&, aSecsSinceMidnight& ):225 COContactFieldDateTime&:( aDateTime& ) :230 COContactFieldDate&: :231 COContactFieldTime&: :232 COContactFieldDateTimeAt&:( aFieldIndex&, aDateTime& ) :233 COContactFieldDateAt&:( aFieldIndex& ) :234 COContactFieldTimeAt&:( aFieldIndex& ) :235 COContactFieldDateTime$: :240 COContactFieldDate$: :241 COContactFieldTime$: :242 COContactFieldDateTimeAt$:( aFieldIndex& ) :243 COContactFieldDateAt$:( aFieldIndex& ) :244 COContactFieldTimeAt$:( aFieldIndex& ) :245End Declare\cn)efd\cv)efd.A*Texted.app~)*y]EPOC ݳn@r+07 7l4|7 :^             p@-(M` P  - - - -0,{ ,@z z 4Ѝl(ЍpA-4MP0`@o 0f $ @c (@$ _ 0^ 04Ѝp@-(M`$ P  - - - -00> ,@= 4 B Ѝl(Ѝp0@-M@ 0S ,: P 04S  ͫ | Ѝ00@-M@ 0S , Ph 04S  ͫ ] Ѝ0@-@ 0S @J ͫ@-@ 0S z @= ͫ@- Mp: P` 0S U P1 `@ @P 0 \ T00VP `FP0`0 0  ͫ4/7P 000 9 : <    ЍA- M ` 0S Vt ` P@ @P 0 H @00pU `  y PEͫͫ4/6P 000 @   f W 000 Ѝ0@-@ P 0S? 0S: 0S 0S 2 000U00U0S h& P 000 000E)  0@b ͫͫͫ@-@ 0S, 0S  @N ͫ@-@ 0Sx 0S 0S \ P 000 00:  v @% ͫͫ0@-@P 0S 0S 0S U  0Sd S PP 000 00 G 000@ ͫͫp@-@P` 0S 0S U0S#  & 0Stx   PP 000 00V   p@ ͫͫ0@-P@ 0SP 0S 0S H P 000 00T   @ T 00 00@v ͫͫ0@-@ 0S 0St 0S d  PP 000 00 0@I ͫͫ@-@ 0St0S` 0S  P 000 00@! ͫ@-@ 0Sx0S 0S \P 000 00 _  J @ͫͫ@-@ 0S0S 0S dP 000 00 6  ' 00@ͫͫp@-P@@hT ? p@@-@Q *0@@-@ 0S@D0S,?A@ͫ@-@ 0S0*0S%A@ͫ@-@ 0S@0S,rA@Zͫ@-@ 0S00SA@Vͫ@-@ 0S<0S 0S  @-ͫͫ@-@ 0S A@-ͫ@-@ 0S00S0@ ͫ@-@ @A-pPP 0S0Sf`Pb@TP\@@N00T HOPP@ V 0500T]AAͫͫ@-@ 0S8N0S$I@ͫ@-@ 0S<6$0S ,10$0@{ͫͫ@-@ 0S<$0S ,0$0@aͫͫ0@-@eP 0Sl0SX0SD$0S4 00$00@8ͫͫ@-@ 0Sh0ST0S@$0S000$0@ͫͫ0@-@PQ $0S U x$0S P 0000$0 s000@ͫp@-`@P 0S~0SyI00U00U0S hl<00T00T0S 4_@DPE- Kp@ͫͫ@-p@ PT `.0P*0P@T  0P@ @lp@-P@t@hT k p@R@-@Q V0@Qp@-P@I@hT @ p@'@-@Q +0@&p@-P@@hT  p@@-@Q t0@p@-P@@hT ^ p@@-@Q I0@@p@-P@`T 4c p@@-@Q R@0@-MP@ T   C< {Ѝ00@-MPQ { @&~Ѝ0p@-P@h`T c p@Jp@-P@O`T J p@10@-MP@ %T 0P ( @ͫЍ00@-P@T  P 0@ͫͫp@-P@`T _P DM @  Ѝp@ͫ@-M`Pp @  P my} Ѝ@-M`Pp @ p P IUY }Ѝ0@-MPQ }3P (0 @;xͫЍ0@-M@Q ^P ( AͫЍ0@-P@AT =P 0@ͫͫp@-$M`@!P UPP @$Ѝp0@-M@ P 0( 6Ѝ0p@-MP@ ` T0, 6Ѝpp@-MP@ ` T00 6Ѝp@-@Q 0rA@0@-DMP@/jyP @ eX6Dߍ0@-@ 0S0 c@}ͫ0@-@P 0S0SU0S0l0@$0S X 00U00U0S (E 000ͫͫͫ@-@ 0S P 0S  P 000 00P 000 P 00 0$0S P 0000$00@-P@R P 0ͫA-Mp@P K $T$@@$`Pu P\6`64@ 0RPu @   P00P0S 8 $KO$ d6ߍ@-@0047@-@MzP @v0 00000@-@P002~0@d7Q񟗭`*d*h*l*p*t*x*|************+++ +++++ +$+(+0+4+8+H+L+\+l+|+++++++++ ,,@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-***@-@-@-@-**@-@-@-@-@-@-@-@-@-@-,+@-@-@+@-T+d+t+++++++++,,$,@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-@-*,,4,<,D,L,T,\,d,l,t,|,,**,0-8-@-@-,,,,,,@-@-@-@-,,,,,,@-@-@-@----- -(-/<'NL  { >f $2ER42a   +)86MKK+M%G          nͫp@-M`@P H%PP h6 @ rHt6Ѝp 0@-P@P@~D0444444444444444p454445 5t4444444445444445|445l4x4D5T5X5@5(5<5855055H5 5,5L5P545$56 655655t5(65,65x55d55h586655<65@655p5l55`566|546\5065L66H6 65555555D6555556555$655P60@-P@0T P 0@0@xfGPRYn)78;BGH89:;<>?;>'Xcf17M QRTW\]_abUVW \ aiklp u~!"%&013:<@DFC%J%I0DebugIntDebugInt failed2%-B%:0%J%:1%T%:2%S%:3%+B %D%M%*Y%/0%1%/1%2%/2%3%/3%D%M%*Y%/0%1%/1%2%/2%3%/3%-B%:0%J%:1%T%:2%S%:3%+Bd4L&|&-h4.4.` +xfGPRYn)78;BGH89:;<>?;>'X cf17M QRTW\]_ab3=UVW \ aiklp u~!"%&013:<@DFJCEUSER[100000c1].DLLOPLR[10000077].DLLCNTMODEL[10001308].DLLEIKON[100001c2].DLL4$0000D0T0`0l0x0000444P5T5 T01l125 555x6666666666666666666666666666666777 77777 7$7(7,7074787<7@7D7H7L7P7T7X7\7`7d7h7l7p7t7x7|777777777777777777777777777777777888 88888 8$8(8,8084888<8@8D8H8L8P8T8X8\8`8d8h8l8p8t8x8|888888888888888888888888888888888999 99999 9$9(9,9094989<9@9D9H9L9P9T9X9\9`9d9h9l9p9t9x9|999999999999999999999999999999999::: ::::: :$:(:,:0:4:8:<:@:D:H:L:P:T:X:\:==L>X>d>p>|>>>>>>>>>>>? ??$?0?