Newton Technology Journal: Volume 2, Number 5

download Newton Technology Journal: Volume 2, Number 5

of 20

Transcript of Newton Technology Journal: Volume 2, Number 5

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    1/20

    Inside This Issue

    continued on page 3 continued on page6

    Volume II, Number 5 October 1996

    NewtonScript Techniques Newton Communications

    NewtonScript TechniquesUsing Unit Referencesto SpeedApplication Development 1

    Newton CommunicationsNewton 2.0Messaging Enabler -GetYour MessagesMovin 1

    Advanced TechniquesMock Entriesfor Debugging 9

    Understanding NewtonScriptDebugging Tutorial: Finding andFixing Bugsin an Application 11

    Product DevelopmentAvoiding Common UI Mistakes 14

    Newton DirectionsGet Connected 15

    Communications TechnologyThe High Level Frame Desktop

    Integration Library(HLFDIL) 16

    Newton 2.0Messaging

    Enabler -GetYour MessagesMovinby Jason Rukman, Apple Computer, Inc.

    Connectivity! Do you carrya cell phone, pageror possiblysome other device to stayin touch?

    If you do, then you would probablylike to

    transfer some of thisinformation onto your

    Newton PDA. When I have myNewton with me

    Id like the information on mypager to go

    directlyto myNewton.

    The Messaging Enabler isa 2.0transport that

    solvesthisproblem byproviding a framework

    specificallydesigned for 1-wayand 2-waywireless

    messaging. With the Messaging Enabler,

    developersare able to get a messaging device

    working quickly, easilyand consistentlywith the

    Newton. The messaging device will be

    integrated with the rest of the Newton system

    and Newton applicationsthat support routing.

    For the Messaging Enabler to be useful, it

    requiresa plug-in driver, called a messagemodule, for a particular hardware device. A

    message module must implement a set of APIs

    for communicating with the particular hardware

    device and the Messaging Enabler looksafter the

    rest. (ThisAPI isdistributed with the Messaging

    Enabler development kit.)

    Your specialtymaybe developing

    communicationssoftware. The idea behind the

    Messaging Enabler isto remove the user

    Using UnitReferencesto

    Speed ApplicationDevelopmentby Bob Ebert, Newton DTS, Apple Computer Inc.

    THEPROBLEMNTK isgetting faster with each release. WithNTK 1.6.x on a PowerMac, the compilation phase

    of even large projectsisamazinglyshort. Unless

    you have to do it over and over and over again,

    all daylong. Whatsworse, no matter howmuch

    faster NTK gets, it still takestime to download

    the package, and a PowerMacwont help with

    that. I find it annoying to have to wait a minute

    or two or twentyto see howa tinychange plays

    out in a large package.

    Wouldnt it be great to be able to split an

    application into smaller projects? You could

    build each project separately, saving time both

    during compilation and during downloading,

    since onlythe smaller part you just edited would

    need to be built and downloaded. Separating an

    application into piecescould also allowa team of

    programmersto work on a project. Each

    engineer would produce one part, hack at it untilitsworking, then share it with the team.

    HAVENTWESOLVEDTHATPROBLEM?Newton TechnologyJournal volume 1,

    number 4, August 1995, contained an article

    called Small Parts: A Faster Wayto Develop

    Large Applications which addressed this

    problem. It showed howto split your application

    into separate modulesthat could be compiled

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    2/20

    October 1996 Newton Technology Journal

    2

    The Excitement is Building

    I just returned from Macworld Expo/

    Boston, where I met a good number of

    enthusiasticNewton developersat Developer

    Central . Granted, I took some heat for

    demoing Newton Toolkit for Windowson a

    Pentium (at a Macintosh Expo no less), but as

    the implicationsof making Newton

    development available to the Windows

    communitybegan to dawn on folks, their

    eyeslit up. Thisisa verygood thing they

    said. I have to agree the possibilitiesare

    endless, and the excitement isgrowing.

    Speaking of excitement, I want to invite

    each of you to the upcoming Fall Newton

    DevelopersConference on November 4, 5,

    and 6th in San Francisco, California. Bring a

    hat to hold onto, asthere will be plentyof

    extremelyinteresting news, technical

    presentations, hardware demos, and labs. Be

    sure to bring your existing code, for reasons

    youll hear about later. Be prepared to be

    blown away.(Im reallynot verygood atkeeping secrets, can you tell?) For conference

    registration information, please visit the

    Newton Development Home page at

    http://devworld.apple.com/dev/newtondev.shtml

    Speakingof secrets, youve probablyheard

    bynowthat Apple haswiselyformed the

    Information AppliancesDivision, of which

    Newton isa part. Jim Groff wasnamed Senior

    Vice President of the division byDr. Gil Amelio

    in earlyJune. Mr. Groff hasa strongand vocal

    commitment to Newton and a rich historywith

    Apple which spansa wide range of product

    and market areas, from Internet serverstoEducation. SandyBenett wasformallynamed

    asVice President of the Newton Systems

    Group (he wasactingin the position for quite

    some time), and another newface isthat of

    Barbara Groth, who nowheadsup the Newton

    SolutionsMarketinggroup (formerlyknown as

    Developer Relations). Youll be hearingmore

    detail on the structure of thiskeygroup in

    monthsahead.

    In thisissue of the Newton Technology

    Journal, we bring you coverage of Newton

    Communicationsin the form of Messaging

    Enabler and FDILsarticles. We heighten your

    programming finesse with articleson User

    Interface tipsand howto shorten your

    development cycle using unit references. In

    the debugging arena, youll find advanced

    techniquesusing mock entries, and an

    excerpted article on debugging techniques

    from the newlyupdated book Programming

    for the Newton, 2nd Edition byJulie

    McKeehan and Neil Rhodes. And we bring

    you important information on the long-

    awaited Newton ConnectionsUtilityfor

    Newton 2.0.

    Keep your eyesopen for Decembers

    issue, which no Newton developer will want

    to miss. To all of you who spoke with me at

    Macworld Expo, thank you for your product

    demos, and to all Newton developers, thank

    you for your enthusiasm, your belief in your

    products, and your ongoing commitment to

    Newton. I am confident that all of your hard

    work isabout to payoff. The future isvery

    bright on the Newton front.

    See you at the developer conference!

    Jen Dunvan

    dunvan@ newton.apple.com

    Published by Apple Computer,Inc.

    Jennifer D unvan Managing Editor

    GerryKane Coordinating Editor,Technical Content

    Gabriel Acosta-Lopez Coordinating Editor, DTS and

    Training Content

    Technical Peer Review Board

    J. Christopher Bell,Bob Ebert, D avid Fedor,

    Ryan Robertson,Jim Schram, M aurice Sharp,

    Bruce Thompson

    Contributors

    Bob Ebert, Cami Hsu, Julie M cKeehan, N eil Rhodes,

    Jason Rukman, Bill Worzel

    Produced by Xplain Corporation

    N eil T icktin Publisher

    W ill Iverson Technical Production Review

    InfoG raphix Design/Production

    1996 Apple Computer,Inc.,1 Infinite Loop,C upertino,C A95014,408-996-1010. A ll rightsreserved.

    Apple, the Apple logo, APD A, AppleDesign, AppleLink,AppleShare, Apple SuperDrive, AppleTalk, HyperCard,LaserWriter,Light Bulb Logo,Mac,M acApp,Macintosh,MacintoshQ uadra, MPW, N ewton, N ewton Toolkit, N ewtonScript,Performa, Q uickT ime, StyleW riter and WorldScript are

    trademarks of Apple C omputer, Inc., registered in the U.S. andother countries. AO CE, AppleScript, AppleSearch, ColorSync,develop, eWorld, Finder, O penD oc, Power M acintosh,Q uickD raw, SNA ps, StarCore, and Sound Manager aretrademarks,and AC O T isa service mark of Apple Computer, Inc.Motorola and Marco are registered trademarksof Motorola, Inc.N uBus is a trademark of Texas Instruments. PowerPC is atrademark of International BusinessM achinesCorporation, usedunder license therefrom. W indowsis a trademark of M icrosoftCorporation and SoftWindowsisa trademark used under licenseby Insignia from Microsoft Corporation. UN IX is a registeredtrademark of UN IX System Laboratories, Inc. D eveloper Centralis a trademark of X plain Corporation. CompuServe, PocketQ uicken by Intuit, CIS Retriever by BlackLabs, PowerForms bySestra, Inc.,AC T ! bySymantec,Berlitz,and all other trademarksarethe propertyof their respective owners.

    Mention of products in this publication is for informational

    purposes only and constitutes neither an endorsement nor arecommendation.A ll product specificationsand descriptionsweresupplied by the respective vendor or supplier. Apple assumesnoresponsibility with regard to the selection, performance, or use ofthe products listed in this publication. A ll understandings,agreements,or warrantiestake place directlybetween the vendorsand prospective users. Limitation of liability: Apple makes nowarrantieswith respect to the contentsof productslisted in thispublication or of the completenessor accuracyof thispublication.Apple specifically disclaims all warranties, express or implied,including, but not limited to, the implied warranties ofmerchantabilityand fitnessfor a particular purpose.

    Volume II, Number 5 October 1996

    Letter From the Editorby Jennifer Dunvan

    Editors Note

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    3/20

    Newton Technology Journal October 1996

    3

    and downloaded separately, but which would still work together. The small

    effort to split your application up wastypicallyrecovered in the first dayof

    building and downloading smaller pieces. The DTS 1.x Q&Asalso go intodetail on howto split up an application.

    One of the drawbacksto using those approachesisthat you have to edit

    your code to make the connectionswork properly, then edit it again when

    producing a final version. You also need to create global variables, and write

    code to hook these globalsinto your app. Even after mastering all that,

    getting data from another package into a templates_proto slot isverytricky.

    Thisarticle buildson those techniques. Using the unit reference feature

    added in the 2.0release of the Newton OS, you can split a large application

    into pieceswhich can be built and downloaded separately, or combined into

    a single part. Whatsmore, the source filescan nowwork either waywithout

    modification.

    BACKGROUND: UNITREFERENCESNewin the 2.0release of the Newton OS isthe abilityfor one package to

    directlyreference data in another. Actually, youve been able to do thisall

    along using run-time referencesfound in global variables, slotsin the root

    view, or other places. Whatsnewisthat you can nowhave NTK compile in

    referencesto data in other packagesso you wont need to use any

    NewtonScript heap space to make the connections.

    You mayhave heard of so-calledmagic pointers, which are referencesin

    your packagesto objectsin the ROM. Whatsmagic about these pointersis

    that the objectsthemselvesare in different locationsin the variousROM

    releases. Yet your package still managesto find the right value, no matter

    which ROM it loadsin. Magic!

    Itsnot reallymagic, of course. Magicpointerswork like handles, theres

    a double-dereference involved. EveryROM putsa lookup table for magic

    objectsin a special place, and the OS looksup the real reference via the table

    when the magicpointer isused.

    UNITREFERENCESWORKLIKEMAGICUnit referencesgive the partsin your packagesthe abilityto contain

    objectsthat can be referenced like magicpointers. Package A can create an

    array, frame, or binaryobject and export it. Package B can have a reference

    to that object, and the OS will make sure that when B looksfor the object, it

    findsit, so long asA isinstalled. No matter where in memoryA happensto

    be!

    Unit referencesare more magical than magicpointers. Theresno wayofknowing in advance where in memoryan exporting package will be located,

    so theresno easywayto locate the table of referencesfor a given part. But it

    happens, and your importing package findsthe correct object.

    Nowletsclean up the terminology. Aunitisa group of zero or more

    objects, identified bya unique symbol aswell asa major and minor version

    number. Apartiswhat NTK typicallyproduces, for example an application

    or auto part, and a part can export and import zero or more units. Partsgo in

    packages, with zero or more partsper package. (But a package with zero

    partsisnt good for much besidesdebugging the OS.) Remember that itsat

    the part level that unitsare imported or exported, not the package level.

    Unit referencesare great for all kindsof applications. Anytime a bunch o

    applicationsneed to share some read-onlydata, code, or objects, you should

    consider using unit references. One alternative isputting copiesof theshared data in each package, which wastesmemory. Another alternative is

    using a soup, but thatstypicallycomplicated because you need to write code

    to make, find, and use the data at run-time. Large data objects, shared

    prototypes, widelyused functions, or even modulesfrom other programmers

    are all thingsthat might be shared via unit references. Thisarticle focuseson

    using them during development to speed the build/download/test cycle.

    For more detailson the API for unit references, aswell asdocumentation,

    supporting functions, and a cool example, check out the Moo Unit sample

    code byMike Engber. Moo Unit isdistributed with the DTS sample code.

    BACKGROUND: ANAPPLICATIONEach layout or user proto in NTK normallyproducesonlya single object.

    That object ismade available to the rest of the project through the build-time

    constant functionGetLayout(filename).It ispossible to create layoutsin NTK that produce more than one value.

    BeforeScriptsor afterScriptsin the templatesmaycreate other constants,

    build-time global variables, or cause other side effects. While thiscan

    sometimesbe handy, I think itsbad form for one layout to relyon side

    effects from compilation of some other layout. Layoutsand protosare

    primarilydeclarativetheycreate an objectand relying on side effectsof

    that objectsconstruction can be confusing. Itseasyto avoid programming

    thiswaybycreating text filesof common objectsused bymore than one

    layout.

    Text filesin NTK can be thought of asnothing but side effects. They

    create global variableslike theInstallScript

    , or constantslike the

    localization frame that are used in other partsof your application. Even with

    text filesitsusuallya good idea to have each file produce a small, well-

    defined set of values. Thisset can be thought of asthe interface between

    that file and the rest of the application.

    User protosin NTK actuallydo a little bit more than simplycreate an

    object at build time. Theyalso clue NTK into the fact that some new

    prototype object exists, which allowsNTK to put an item in the User Proto

    popup in the palette. Thiscurrentlydoesnt buyyou anything other than the

    abilityto drag out a user proto in the layout view. Well come back to this

    later.

    Linked Layoutsin NTK can be thought of asa special case of user protos.

    Unlike user protos, linked layoutsconstrain thingsso that a layout can only

    be placed in a project once. Well come back to this, too.

    BREAKINGAPROJECTINTOSMALLERPARTSIll assert that all the inter-file connectionsmade while building your

    project are accomplished via build-time constants. Thismaynot alwaysbe

    so, but itsa useful wayof thinking about your projects, especiallyfor the

    purpose of splitting it into pieces.

    Anyplace where an object isshared onlyvia a constant isa good place to

    split up an application. You do thisbymoving the protos, layouts, or text

    filesout of the main project and into a newproject of their own. Thisnew

    project will create an auto part that exportsthe shared objects.

    continued from page 1

    Using Unit Referencesto Speed Application Development

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    4/20

    Newton Technology Journal October 1996

    4

    Thatsreallyall you need to know. That idea, along with the unit

    reference documentation, will let you break your big packagesinto smaller

    onesthat can be downloaded individually, vastlyreducing the time it takesto

    build, download, and test anyone of them.

    But keep reading. The rest of the article will describe one wayto create the

    interface between the projectsso that no existingcode needsto change. It will

    also describe some thingsI do to help with debugginga project built thisway.

    CONSTANTAGONIZINGFor constantsprovided via text files, either withDefConst or the

    constant keyword, both the code that definesthe constant and thecode that usesthe value of the constant are using the same symbol. This

    seemsobvious. It wouldnt work anyother way!

    Lessobviousisthat thisistrue for layoutsand protosaswell. Earlier I

    mentioned that NTK providesaccessto layoutsand protosthrough the build

    time constant functionGetLayout. The old waywasto use a constantnamedlayout_filename, and thisisstill supported. In fact, NTK 1.5and1.6use the constant namedlayout_filenameto implement theGetLayout function. The onlything a layout or proto reallyproducesisa constant with the special name.

    When sharing an object via unit references, you could name the reference

    anything you like. However, the symbol thatsthe name of the constant, e.g.

    layout_filename, turnsout to be an excellent choice. Itsa goodchoice because all your code that usesthe object isalreadywritten to use

    that symbol, and the name in the unit reference declaration will be the only

    commonalitybetween the exporting project and the importing project.

    After the project issplit, the code that definesthe constant isin a different

    project than the code that usesit, so well actuallycreatetwoconstants, onein each project. Byusing the same symbol for the namesof them in both

    projects, none of the existing code needsto be edited.

    Build-time global variablesdont fit into thisscheme. ThatsOK, because

    build-time globalsarent the right tool for thiskind of project design. Build-

    time constantsfill the same need, and are handled better bythe compiler.

    There are timeswhen a build-time global variable isthe right thing to use to

    solve a problem, but those casesdont require the global to be shared

    between projects, so theyre irrelevant to thisarticle.

    USINGUNITREFERENCESThe core of the unit reference mechanism isimplemented bythree

    functions. DeclareUnit tellsNTK that a unit isbeing used, the majorand minor version of the unit, and the namesof the objectswithin the unit.

    It must be called byboth the importing and exporting projects.

    DefineUnit definesthe objectsthat the unit will contain, and iscalledonlybythe exporting project. UnitReference givesyou a magicreference to an imported object that will be hooked up at run time bythe

    OS. UnitReference isneeded in the importing application, though itcan be used bythe exporter aswell.

    DeclareUnit requiresa declaration frame. Thisisa frame thatdeclareswhat will be shared. The namesof the slotsprovide the namesfor

    the objectsin a unit, and the valuesof the slotsare unique integers. The

    exporting project must provide a frame with unique sequential integers

    starting with 0. Importing projectsare allowed to have gaps. Thisallowsyou

    to keep some objectsprivate byremoving their entriesfrom the declaration

    frame when given to an importer. Read the unit reference documentation in

    the Newton 2.0Q&Asor the Moo Unit sample code for more detail on how

    unit referenceswork.

    THEINTERFACEFILESince were using unitsfor development only, we dont need to worry

    about which objectsare publicand which are private. The exporting project

    and the importing project will share the same declaration frame for a unit.

    Itsconvenient to put the declaration frame and the code that usesit into a

    text file, which I call aninterface file.

    The interface file well create will be used in both the exporting project

    and the importing project. Again, thisisnt a requirement for using unitreferenceswith NTK, but itsa veryconvenient wayto make sure the two

    partsstayin sync. Hereswhat an interface file will contain:

    constant kPart1Sym := |Part1:EBERT|;constant kPart1Declaration := {

    layout_protoFoo: 0,layout_AboutSlip: 1,kMungeAStringFunc: 2,

    };DeclareUnit(kPart1Sym, 1, 0, kPart1Declaration);

    The symbol inkPart1Sym isthe name of the unit, and must beunique in the Newton, so a registered signature isused. You should put this

    same symbol in the app symbol field of the auto partsproject preferences.

    Ill tell you whyin a moment.

    Im specifying three thingsin thisunit: a user proto, a layout, and a

    constant that happensto contain a function. The unit hasmajor version 1,

    and minor version 0. I never change these numbersduring development.

    Heressome additional code that I put in myinterface files:

    if kAppSymbol kPart1Sym then// building importing project, so create constantsbegin

    DefGlobalFn(ImpureUnitRef,constantFunctions.UnitReference);

    foreach slot, value in kPart1Declaration doDefConst(slot, ImpureUnitRef(kPart1Sym, slot));

    end

    Thiscode createsa constant for each slot in the unit reference declaration

    frame, but onlyfor importing projects! The exporting project alreadyhasthe

    constantsin the text files, layouts, or user protos. Thatswhywe made the

    unit symbol the same asthe appSymboltestingkAppSymbol againstthe unit symbol isan easywayof telling if the code isbeing compiled in the

    exporting or an importing project.

    Thiscode also doessomething unusual. UnitReference isaconstant function, and so it can onlybe called with constant arguments. In

    order to make the loop work properly, we need to call the function with the

    slot variable from the loop. So we cheat and define a newnormalglobal function calledImpureUnitRef thatsthe same asthe constantfunctionUnitReference. Thistrick worksin NTK 1.5and 1.6, but itsnot guaranteed to work in the future.

    Note that exactlythe same thing could be accomplished, in a supported

    way, like this:DefConst(layout_protoFoo,

    UnitReference(kPart1Sym, layout_protoFoo));DefConst(layout_AboutSlip,

    UnitReference(kPart1Sym, layout_AboutSlip)DefConst(kMungeAStringFunc,

    UnitReference(kPart1Sym, kMungeAStringFunc)

    Thismayseem simpler, and even shorter for thisexample. However, I

    dont do it thiswaybecause it requiresme to edit more code everytime I

    add, remove, or change the name of a shared object. If you use the loop, the

    onlything in the interface file that needsto be edited asthe projectschange

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    5/20

    isthekPart1Declaration frame. I think thisissafe becauseduring development I typicallyupgrade NTK much lessfrequentlythan I edit

    the contentsof myunits.

    THEEXPORTINGPROJECTTheresa little more code that needsto be written to make it all hang

    together. The exporting project needsto actuallyspecifythe objectsto

    export. Create a newtext file onlyfor the exporting project with thefollowing code:

    DefConst(kPart1Objects, {//:

    layout_protoFoo: layout_protoFoo, // oldlayout_AboutSlip: GetLayout(AboutSlip), // newkMungeAStringFunc: kMungeAStringFunc,

    });DefineUnit(kPart1Sym, kPart1Objects);

    Thatsit! You mayask Whycreate the constantkPart1Objects atall? Whynot just put the frame right in the call toDefineUnit and bedone with it? That would work fine, but once again I do a little bit more.

    Hereswhat else I put in the exporting projectsdefinition file, strictlyfor

    debugging:

    if kDebugOn thenbegin

    InstallScript := func(partFrame, removeFrame)begin

    DefGlobalVar(EnsureInternal(kPart1Sym),kPart1Objects);

    foreach slot, value in kPart1Objects doDefGlobalVar(EnsureInternal(slot), value);

    end;RemoveScript := func(removeFrame)

    beginforeach slot, value in GetGlobalVar(kPart1Sym) do

    UndefGlobalVar(slot);UndefGlobalVar(kPart1Sym);

    end;end;

    What thisdoesiscreate a bunch of run-time global variables. One of the

    variableswill have the same name asthe unit, in thiscase

    |Part1:EBERT|, and will be a frame with all the exported objects.TheUnitReference function doesnt work at run-time, so withoutsticking a reference to the exported objectsin some easilyaccessible frame it

    could be hard to locate them later.

    The rest of the globalseach have the same name asthe objectsbeing

    exported. Note that I dont include myregistered signature in the namesof

    each of these constants. That meanstheressome chance one of mynames

    will collide with some system object. I typicallyname thingsesoterically

    enough to prevent this. Itsunlikelythat a system object will be called

    layout_protoFoo, but you should keep the danger in mind if youdo the same thing.

    Youre probablyasking Whyeven bother creating all those individualconstants? Surelyhaving the valuesavailable via the one global frame is

    sufficient? I create the extra globalsbecause Im lazy. I like to prototype

    code in the inspector, to get it more or lessworking before I make it part of a

    project. Global variablesand constantsare accessed using identical syntax.

    Having the global variable available at run time for the inspector with the

    same name asthe constant thatsavailable at build time for the compiler

    meansI can copy/paste code between the inspector and the project and not

    edit it. call kMungeAStringFunc with (YourName)worksin either place.

    If you havent caught on yet, I like it a lot when the same code worksin

    different environmentsor when put together different ways, especiallywhen

    no editing isnecessary. Im a verylazyprogrammer.

    ABOUTUSERPROTOSANDLINKEDLAYOUTSUser Protosdo a wee bit more than just provide a constant. When a user

    proto isin a project, NTK knowsto put itsname in the palette so you can

    drag one out. After the split, a user proto mayno longer be in the same

    project asthe code that usesit. So what do you drag out?I drag out aprotoFloater instead, then add an after script to fix

    up the contentsof the_proto slot. Anypredefined proto would work,butprotoFloaterjust happensto be on the palette and not add anyextra default slots. TheafterScript lookslike this:

    thisView._proto := GetLayout(protoFoo);

    The same can be done for linked layouts. After the split, the linked layout

    mayno longer be in the same project asthe layout itslinked to.

    protoFloater to the rescue again! Just drag out aprotoFloater instead of a linked layout, and have theafterScript replace the _proto slot:

    thisView._proto := GetLayout(AboutSlip);

    Thisactuallydoesnot produce the same result asa real linked layout. We

    end up with an extra level of_proto inheritance that wouldnt be therewith normal linked layouts. I t ispossible to completelysimulate what NTK

    doeswhen it linksa layout. However, fullyintegrating a declared linked

    layout requiresunderstanding of the Newton viewsystem declare

    mechanism, which isbeyond the scope of thisarticle. Using a

    protoFloater isthe simplest solution, since it letsyou declare theviewsin NTK, just like you would with linked layouts.

    SUMMARYIt takesjust a fewsimple stepsto split a project up into separate

    compilation unitsthat will exist at run time asseparate packagesand share

    objectsvia unit references. The stepsare:

    Remove the layouts, protos, or text files fromthe main project.

    Put themin a newproject that produces an auto part.

    Create the interface file containingeverythingthats shared.

    Place it at the beginningof the exportingproject.

    Create the definition file for the newproject.

    Put it at the end of the exportingproject.

    Build and download the exportingpackage.

    Add the interface file at the beginningof the main project.

    Build and download the main package.

    Everything should end up working exactlyasit did before. Notice that you

    didnt edit anyof the source layouts, protos, or text filesat all! (Okay, except

    maybe to clean up the_proto slotsfor user protosor linked layouts.)

    October 1996 Newton Technology Journa

    5

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    6/20

    NEXTSTEPSFor interim or beta releases, you can make the main project a multi-part

    package that containsall the exporting partsaswell asthe main part, so your

    beta usersonlysee one package. Remember that the unit reference

    mechanism workson a part-by-part basis, so theresno reason the exporting

    part and the importing part cant be in the same package.

    When youre readyfor your final build, you can just drop the source files

    right back into the main project. Put them right where the interface file was,and remove the interface file from the main project. Thistime you dont

    have to edit anything at all, even trivially.

    Theresactuallyno compelling reason to ever put the filesback in a single

    part. The code will all work fine asa multi-part package. I have a suspicion

    that performance will improve if everything isin one part. I believe this

    because unit referencesmust cost something, but I have not measured the

    costs. The localityof the package (in other words, which objectsare next to

    which other objects) will also change when switching from separate packages

    to a multi-part package to an all-in-one package, and thiscan affect

    performance. I recommend trying the variousconfigurationsand choosing

    the one you like best.

    A BUGTOWATCHOUTFORThere isa bug with unit referencesin the 2.0OS. Sometimeswhen an

    importing package isinstalled before an exporting package, the unit

    referencesare not properlyconnected. When thishappens, an exception will

    be thrown when the bad reference isfollowed bythe importer. You can work

    around the problem byreinstalling the importing packages. Bythe time this

    ispublished, Apple Computer will probablyhave released a system update

    that fixesthisbug, so that you can re-download an exporting package manytimeswithout touching the importer.

    CONCLUSIONWith the invention of unit references, itsnoweasier than ever to split a

    large application into separate compilation units. Whatsmore, these units

    can be put in individual packagesand downloaded separately. Over a full

    project development cycle, thiscould amount to daysor even weeksof your

    time, much lessthan the time needed to split up the application. The

    technique also encouragesa good coding discipline, and can be used to allow

    teamsof programmersto work together on large applications.

    interface requirement from the Original Equipment Manufacturer (OEM).

    Thisallowsa consistent user interface for all wirelessmessaging productsthat

    use the Messaging Enabler.

    Is it for you?

    Of course, the Messaging Enabler wont be suitable for everymessaging

    system. It hasbeen designed to enable asmanyof the wirelessmessaging

    systemsaspossible. If you want to enable a piece of hardware for the

    Newton platform, then it maybe worth using the Messaging Enabler if the

    hardware can receive, and possiblysend, messageswirelessly(for instance

    pagers, wirelessPC cards, etc.).

    A good understanding of routing isrecommended for developersusing

    the Messaging Enabler or writing a message module. Although an

    understanding of transportsmaybe helpful when writing a message module,

    it isnot required. You can find information on routing and transportsin the

    Newton Programmers Guide: Communications.

    The Messaging Enabler doesmost of the work for you, so that you can

    have your hardware up and running assoon aspossible. The exciting

    featuresof the Messaging Enabler are covered below.

    Message moduleshave manyoptionsthat maybe customized so you can

    support featuresspecificto the messaging device being used.Most Newton applicationsthat support routing can use the messaging

    device via the Messaging Enabler with no changes. Thisisdue to the

    NewtonScript routing mechanism. Applicationscan also be designed to

    control the Messaging Enabler directlywhich isideallysuited for applications

    targeted to a vertical market.

    Features

    The following list of featuresshould give you a better idea of some of the

    functionsprovided bythe Messaging Enabler:

    Standardized preferencesfor wirelessmessaging.

    Figure 1: Messaging Enabler Preferences

    Device specificpreferences. Note that not all of these preferenceswill

    necessarilybe displayed for each device.

    Figure 2: Device Specific Preferences

    NTJ

    October 1996 Newton Technology Journal

    6

    continued from page 1

    Newton 2.0 Messaging Enabler -Get your MessagesMovin

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    7/20

    Newton Technology Journal October 1996

    7

    Send routing slip(s).

    Figure 3: Paging Routing Slip

    Paging addressdata definitions. Thisextendsthe in-built addressdata

    definitions.

    Figure 4: Pager Address Listpicker

    Message replying. Some 2-waymessaging devicescan replyto received

    messages, for instance the Motorola Tango .

    Figure 5: Message Reply Picker

    Automaticmessage retrieval. Automaticcontrol and combination of

    multi-part messages.

    Text message viewing/editing/and put away.

    The following message showsan item in the In Box made up of two

    combined messages.

    Figure 6: Displayed In Box Message

    Manage and control the I/O Box.

    User statusfeedback.

    Howit ticks

    Figure 7: Messaging Enabler Hierarchy

    Asthisdiagram showsthe Messaging Enabler fitsin at the same location

    in the Newton communicationslayering asa 2.0Transport.

    Installinga message module

    To add a message module to the system, you create an auto part. This

    meansthat when a message module isinstalled, it addsservicesto the system

    but doesnot add an application to the extrasdrawer; however, an icon is

    added to the Extensions folder. You define a message module based on the

    prototype, protoMsgModule. To add the defined message module tothe system, you call theRegMsgModule platform file function fromyour auto partsInstallScript function with the template you havedefined.

    call kRegMsgModuleFunc with (kAppSymbol,partFrame.partData.TestEnabler

    );

    To unregister the message module you need to supplytwo part framefunctions: DeletionScript and RemoveScript. The DeletionScript function willcall the DeleteMsgModule platform file function to remove anypreferences

    for the message module, and also ensuresyour message module

    RemoveScript iscalled.

    SetPartFrameSlot(DeletionScript,func() begin

    call kDeleteMsgModuleFunc with (kAppSymbol

    );end

    );

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    8/20

    In yourRemoveScript of the auto part you should deregister themessage module bycalling theUnRegMsgModule platform filefunction:

    call kUnRegMsgModuleFunc with ( kAppSymbol );

    Workingwith callbacks and events

    Most of the methodsdefined inprotoMsgModule take a callbackasone of the parameters. The Messaging Enabler will call methodsthat you

    override inprotoMsgModulewhen the Messaging Enabler needstoperform a particular operation. For example: When the Messaging Enabler

    needsa message from the message module, it maysend the

    GetNextMessagemessage, which could be implemented asfollows:

    GetNextMessage := func( callBack ) begin........ // go get the next message....:doEvent(

    kEV_PROGRESS,{ type: vBarber,

    statusText: Almost done...}

    );....:doCallBack(

    callBack ,kRES_SUCCESS,message // your retrieved message

    );

    end; // GetNextMessage

    Note that the callsto the internallydefined methodsof

    protoMsgModule,doEvent, anddoCallBack. ThemethoddoEventwasused to change the statusdisplay. The MessagingEnabler providesa default statusdisplaybut bysending eventsto the

    Messaging Enabler thiscan be customized. Sending thedoCallBackmessage isrequired to inform the Messaging Enabler when the operation for

    GetNextMessage hasbeen completed. Thisalso returnsthe resultfrom the requested operation.

    You maysend other eventsto the Messaging Enabler to let it knowwhen

    certain thingshappen. For example, if a newmessage hasbeen received, you

    would send akEV_MESSAGE event to alert the Messaging Enabler toread the message. You would do thisbysending thedoEvent message.

    Need to send messages?

    To support sending you need aSendOptions frame and aSendMessage method. TheSendOptions frame definesoptionsfor sending messages. The Messaging Enabler will call the

    SendMessagemethod when a newitem needsto be transmitted. The

    main slot required for theSendOptions frame isrouteSlipType. Thisdefinesthe addressing type to use whensending. The Messaging Enabler addsa paging data definition to the system.

    For more information about data definitions, please see the Stationery

    chapter in theNewton Programmers Guide: System Software.

    A newitem will be added to the action picker based on the

    SendOptions frame contents. A typicalSendOptions framemight be similar to the following:

    { routeSlipType: |nameRef.people.pager|,replyTypes: [ ack, user, canned ],dataTypes: [ text, frame ],group: page,

    groupIcon: ROM_RoutePageIcon,groupTitle: Page

    }

    Figure 8: Notepad Routing Picker

    Thismeansthat anyNewton application that supportsrouting for either

    text orframe datatypeswill nowbe able to send thisdata asa page.See the Routing Interface chapter in theNewton Programmers Guide:

    Communications.

    Whats your preference?

    The Messaging Enabler providesseveral different mechanismsfor

    controlling user preferences. The main preference slip asseen in Figure 1

    containsseveral itemsthat will onlybe visible if your message module

    overridescertain prototype slots. For example, the first option, When

    receiving, will onlybe visible if your message module setsthe

    dirSupport slot totrue. (Note, however, that thislabelpicker maystill be visible if another installed message module hasthisset.)

    A separate viewdisplaysthe hardware preferencesfor each messaging

    device. The Messaging Enabler providesfive genericpreferencesthat you

    mayuse asseen in Figure 2. These preferencesare veryeasyto set up. All

    that isneeded isan arrayof stringsthat become the optionsfor each

    preference (such asthelabelCommands for thelabelPicker).For example, you could setsoundStrings to the following array:

    [ Off, Tunes, Annoying, Loud ]

    to correspond with the hardware optionsfor the particular messaging device.

    Note that the first arrayitem will be the default for each of the preferences,

    so it isimportant to make the most reasonable preference setting the first

    item in the array. The Messaging Enabler determineswhen these

    preferencesneed to be set and will call theSetConfigmethod of themessage module at the appropriate time.

    A third wayto provide user preferencesgivesmore customization control,

    but also requiresmore work. Provide your own preference viewtemplate.

    You might need to do thisif there issome special setting that isnot covered

    byanyother preference controls. You supplythisviewtemplate in the

    prefsTemplate slot of your message module.Asyou can see, there are several levelsof control for the user preferences.

    In most cases, it isimportant to remember that lessisoften better. Most userswork better with devicesthat function in an expected manner, rather than

    having to set a bunch of preferencesto get them to work a particular way.

    Controllingthe MessagingEnabler.

    The Messaging Enabler mayalso be controlled byan installed Newton

    application. Thisfeature isintended primarilyfor vertical applications(such

    asa health-care dispatch application) that would need to set the preferences

    explicitly.

    To change the Messaging Enabler preferencesan installed Newton

    application would call theTransportNotifyglobal function.

    October 1996 Newton Technology Journal

    8

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    9/20

    Newton Technology Journal October 1996

    9

    For example:

    TransportNotify(MsgEnabler,ChangeConfig,[ callBack,

    { disable: true,autoStatus: nil,hideItems: nil,

    },

    { deviceSym: MM_msgModule,powerIndex: 1,portIndex: 2

    }]

    );

    Thisdoesthe following:

    Disablesthe user accessto the Messaging Enabler preferencesso they

    cannot be changed.

    The statusdialog will not be automaticallyopened. ( The user can still see

    the statusif it isselected from the NotifyIcon at the top of the screen.)

    The Messaging Enabler itemswill not be displayed in the I/O Box.

    The installed message moduleMM_msgModulewill have itspreferencesset to the second item in thepowerStrings arrayandthe third item in theportStrings array.

    Asyou can see, thisgivesan application the necessarycontrol over the

    Messaging Enabler. There are manyother preferencesof the Messaging

    Enabler that can also be set in thisway.

    Note that thisfunction isdesigned to be integrated with a single Newton

    application and isideallysuited for vertical market applications. If two

    separate Newton applicationswere to attempt thisoperation, the Messaging

    Enabler preferenceswould be set to a combination of these two applications

    and the resultswould be unpredictable.

    Give me those In Box items!

    So howdoesan installed Newton application get the itemsfrom the

    Messaging Enabler once theyare in the In Box? Because the Messaging

    Enabler isa transport, anyinstalled application can receive itemsfrom the

    messaging enable using the standard Newton routing APIs.

    Please refer to the Newton Programmers Guidefor a description of the

    different mechanismsavailable for routing itemsfrom the In Box, specifically

    RegInBoxApps, RegAppClasses, PutAway andAutoPutAway.

    * And remember that the namesof the innocent have been changed to

    protect the guilty.

    Editing support; R. Robertson, J.C. Bell & A. Weiss.NTJ

    Mock Entriesfor Debuggingby Bob Ebert, Newton Developer Technical Support.

    Advanced Techniques

    THEPROBLEM

    The NSDebugToolspackage, part of NTK 1.6, allowsyou to set break

    pointsin NewtonScript code. Thisisverypowerful and will help you find

    manyof your bugswhich dont raise exceptions. However, once in a while

    what you need to knowiswhen some object isaccessed, not when some line

    of code isexecuted. One wayto do thisisto set the global variabletracetoTRUE, but then you typicallyhave to wait a long time for the trace output

    to stop scrolling by, then wade through reamsof data to find the accessesyoure interested in.

    MOCKENTRIESTOTHERESCUEA little-known and even lessfrequentlyused feature that wasadded to the

    Newton OS in the 2.0release isthe abilityto create entry-like objects, called

    Mock Entries. These objectsare composed of two parts. One part isa

    simple NewtonScript frame, often called thecached entry. The other part is

    ahandlerwhich knowshowto create and save the cached entry. The parts

    together are sometimescalled afault block; when something needsthe

    cached entryand it doesnt exist, afaultoccursand a message issent to the

    handler, which then createsorfaults inthe entry.

    The Newton OS in 2.0allowsyou to create these fault blocksfor your own

    objects, which meansyou get to write the code that executeswhen the

    cached object needsto be faulted in. The code that createsthe cached entry

    can also do other things, for example it could enter a breakloop, which would

    give you a chance to look at the stack and see whatsaccessing the frame.

    Heresa simple example of using a fault block for debugging. Well create

    a simple frame that printsan exclamation point in the inspector and beepsthe speaker everytime itsaccessed.

    handler := {object: {foo: bar},EntryAccess: func(mockEntry)

    beginwrite(!);GetRoot():Sysbeep();object;

    end,};

    f := NewMockEntry(handler, nil);

    f isnowa Mock Entry. Hereshowit looksto the OS:

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    10/20

    When anyslot inf needsto be accessed, the OS checksto see if there isa cached object. Because we passedNIL asthe 2nd argument toNewMockEntry, andEntrySetCachedObject hasnt beencalled, there will be no cached object forf. When there isno cached object,the OS callsthe handlersEntryAccessmethod, which isexpected tocreate the cached object, tell the OS about it using

    EntrySetCachedObject, and return it.We cheat and dont callEntrySetCachedObject. The OS uses

    the return value ofEntryAccess asthe object for thisaccess, and sincewe returnhandler.object everything works, but next timesomething touchesf, EntryAccesswill be called again. Theresourhookeverytime some part of the OS readsor writesanyslot inf,EntryAccess iscalled.

    To almost all of the Newton OS,f lookslike a regular frame. f.fooevaluatestobar. ClassOf(f) isframe. f.baz := 42will add a slot to the frame, which isalso referenced as

    handler.object in our example, so the next time the frame isaccessed, the modified object will be returned. The illusion iscomplete, only

    the test functionIsMockEntry() can tell thatf isa mock entryand nota normal NewtonScript frame.

    ANIMPROVEMENTIf you trythis, youll see that the frame isaccessed a lot more often than

    you might think. Getting the value off.foo callsEntryAccesstwice. Setting a slot also callsEntryAccess twice. Creating a newslotcallsit 11times. Theprint function must do a lot, because printingf inthe inspector callstheEntryAccessmethod a whole bunch of times.

    In our application debugging example above, we reallyonlywant to know

    when the object isbeing used for the first time in a while. Recall that if the

    OS findsthat a cached object exists, it wont callEntryAccess but willsimplyuse the object. So to prevent excessive calls, ourEntryAccessmethod will nowcreate the cached object. The trick then becomesclearing

    the cached object. Ive found that clearing the object at a deferred time

    workswelltypicallyitscleared the next time control returnsto the top

    level, which issoon enough to catch most bugs. Hereshowto do that: ( the

    bold text isnew)handler := {

    object: {foo: bar},EntryAccess: func(mockEntry)

    beginwrite(!);GetRoot():Sysbeep();EntrySetCachedObject(mockEntry, object);AddDeferredCall(

    GetGlobalFn(EntrySetCachedObject),[mockEntry, nil]);

    object;end,

    };f := NewMockEntry(handler, nil);

    You might want to experiment with clearing the cached object at other times.

    LIMITATIONSTheEntryAccessmethod of the handler object iscalled onlywhen

    a slot in the frame isaccessed. That is, a statement likeg := fwontcause theEntryAccessmethod to be called, since no slot inf isaccessed. The result of that statement will be that you nowhave two

    referencesto the mock entryfault block, and eitherg.foo orf.foowill cause theEntryAccessmethod to be called.

    The Newton 2.0OS onlysupportscreating mock objectsthat are backed

    up byframes. While itsnot guaranteed, you might experiment and see what

    happensif the object isan arrayor a binaryobject. (But back up your data

    first!) Trysome special case binaryobjectslike stringsor real numbers.

    Depending on your situation, you maybe able to use thisdebugging

    technique with arraysor binaryobjectsaswell aswith frames.

    Ive found that some partsof the OS work normallyin thiscasethe

    mock object istreated just like a string, bitmap, array, or whatever. Other

    partsof the OS notice that the object isa fault block and not the

    appropriate object type, which typicallycausesa throw. The error messages

    in thiscase can be interesting. For example, putting the stringfoo intheobject slot of thehandlerwill create an object that appearstobe a string. Printing works, but functionslikeStrLen(f) or theaccessorf[0] notice that the object isnt a string, and throwwith theseeminglycontradictoryerror message: Expected a string,got foo. Thishappensbecause the exception printerdoesntnoticethat the mock object isnt a string, and so it callsEntryAccess, getsthestring, and printsit.

    ADVANCEDTECHNIQUESYou can put anyNewtonScript code in the handler, specificallyin the

    EntryAccessmethod, so you can use thistrick to do other things. Forexample, you could add a counter and find out howmanytimesa frame is

    accessed during some operation. You could add in a test to see if some slot

    in the frame haschanged, and stop when it getsa certain value.

    Unfortunately, when theEntryAccessmethod iscalled you donthave anyinformation about whatshappening. You cant tell if a slot isbeing

    read or set. You cant tell which slot (or element, or byte) isbeing accessed.

    If you write code that watchesfor changesyou end up finding out after the

    change takesplace.

    But thiscan still be useful. Consider if your handler settrace toTRUE and then set it toNILagain in a deferred call. Thiswould do a great

    job of limiting the trace output to onlycode that actuallyused the object.

    TheEntryAccessmethod might also watch for some change and,upon detecting the change, settrace toNIL and enter a breakloop.That wayyoud knowwithout doubt that the last section of trace output was

    the one you needed to look at.You might even consider using mock objectsto implement a kind of

    sentinel that letsyou knowwhen other applicationsaccessyour objects.

    CONCLUSIONBeing able to have your code execute when a frame isaccessed is

    powerful, and haslotsof good uses. However, keep in mind that any

    observationsyou or I make about howthe OS dealswith mock objects

    should be used onlyfor debugging. That is, it would be a mistake to write

    production code that reliesonEntryAccess

    October 1996 Newton Technology Journal

    10

    NTJ

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    11/20

    Newton Technology Journal October 1996

    11

    #440F63D {_parent: {_parent: {#440D221},_proto: {#6008D0C1},viewCObject: 0x110926D,viewclipper: 17863292,base: ,viewFlags: 577,viewBounds: {#440F5C1}},_proto: {buttonClickScript:,text: Beep,viewBounds: {#6008D539},_proto: {@226}},viewCObject: 0x110A530,viewFlags: 515}

    Now, letsget the parent slot and we will have the right view:

    floatNGo := beepingButton._parent#440F5DD {_parent: {minute: 178,

    downButton: {#440B2E9},calculator: {#4406159},mailEditor: {#44064C1},extrasDrawer: {#4409671},defaultTransport:Newton: {#4405DD9},OutOfMemoryAlert: {#4405D95},notification: {#4405D35},remindSlip: {#44060C5},namesButton: {#44063D9},folderEdit: {#4405DF1},phoneKeyboard: {#4405ECD},ovButton: {#440643D},upButton: {#4406461},thegang: {#44065F9},

    printerSerialPicker: {#4405D05},...},_proto: {viewBounds: {#6008D199},

    stepChildren: [#6008D1B9],_proto: {@180},debug: myFloatNGo,appSymbol: |Demo:NTK.Demo|},

    viewCObject: 0x110926D,viewclipper: 17863292,base: ,viewFlags: 577,viewBounds:{left:-25, top:173, right:139, bottom:265}}

    ThenumBeeps slot doesnt seem to be in thefloatNGo. The viewotherwise appearsto be correct. It soundslike a problem in declaring. Lets

    check the Template Info dialog for that template (see Figure 3). Well, well,

    well. Turnsout it actuallywasnt declared. Well checkmark the Declare To:checkbox and rebuild.

    Figure 3: Template Info dialog showing undeclared numBeeps.

    BEEPINGBUTTONBROUHAHA

    Weve written a verysimple application in which the user can write a

    number. Pressing the Beep button makesthe Newton beep that many

    times. Figure 1showsthe application. Figure 2showsthe application

    templatesin NTK.

    Figure 1: Beeping Button application.

    Figure 2: Structure of the Beeping Button project.

    FIRSTPROBLEM

    The first thing that happenswhen we write in a number and then press

    the Beep button isa notification on the Newton: Sorry, a problem has

    occurred (-48807). Letsturn onbreakOnThrows (clicking the icon inthe Inspector Window) and pressthe button again. Now, the Inspector prints

    out

    Undefined variable: numBeepsevt.ex.fr.intrp;type.ref.frame-48807

    (#6008D1D1).buttonClickScript(), 3: Push text

    Entering break loop: level 1

    If we look at the code we see that were trying to accessthe

    numBeeps variable from ourbuttonClickScript. That variableshould refer to ourprotolabelInputLine view. What could bewrong?If weve correctlydeclarednumBeeps to theprotoFloatNGo, theprotoFloatNGo viewshould have a slotnamednumBeeps. Letslook in that viewfornumBeeps. ( That viewisthe parent of our current self.) .First, letsgetself:

    // get current selfbeepingButton := GetCurrentReceiver(0);

    Debugging Tutorial: Finding & Fixing Bugsin an ApplicationJulie McKeehan and Neil Rhodes, Academic Press. 1996

    Understanding NewtonScript

    Excerpted from Programming for the Newton,2nd edition

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    12/20

    SECONDPROBLEM(AHARDONE)We rebuild, download, and rerun. We write in a number and tap the

    Beep checkbox. We get the following error in the Inspector:

    Undefined variable: numBeepsevt.ex.fr.intrp;type.ref.frame-48807

    (#6008D229).buttonClickScript(), 3: Push textEntering break loop: level 1

    Thisisexactlythe same error at the same place we had it before. Letscheck

    thefloatNGo viewagain:

    beepingButton := GetCurrentReceiver(0);floatNGo := beepingButton._parentand here is what we find when the Inspector returns ourresult:#4412B0D {_parent: {minute: 181,

    downButton: {#440B129},calculator: {#4406159},mailEditor: {#44064A1},extrasDrawer: {#4409651},defaultTransport:Newton: {#4405DD9},OutOfMemoryAlert: {#4405D95},notification: {#4405D35},remindSlip: {#44060C5},namesButton: {#44063D9},

    folderEdit: {#4405DF1},phoneKeyboard: {#4405ECD},ovButton: {#440643D},upButton: {#440EF4D},thegang: {#44065D9},printerSerialPicker: {#4405D05},...},

    _proto: {viewBounds: {#6008D1F1},stepChildren: [#6008D211],_proto: {@180},debug: myFloatNGo,numBeeps : NIL,stepAllocateContext: [#6008D731],appSymbol: |Demo:NTK.Demo|},

    viewCObject: 0x1108C2C,numBeeps : {_parent: ,

    _proto: {#6008D5D1},viewCObject: 0x1109F0C,entryLine: {#4419229},

    labelLine: {#4418E49},width: 73,indent: 75,height: 13},

    viewclipper: 17863746,base: ,viewFlags: 577}

    ThenumBeeps slot seemsto be there and seemsto point to whatlookslike it could be our view. Letstryto accessit from the Inspector:

    floatNGo.numBeeps#2 NIL

    That doesnt make sense. We can see that it isthere. Letstryanother wayto

    get to that viewusing theDebug function:

    Debug(numBeeps)#2 NIL

    Curiouser and curiouser. However, look verycloselyat the waythe

    numBeeps slot printsout versusanyother slot:

    _proto: {viewBounds: {#6008D1F1},stepChildren: [#6008D211],_proto: {@180},debug: myFloatNGo,numBeeps : NIL,stepAllocateContext: [#6008D731],appSymbol: |Demo:NTK.Demo|},

    viewCObject: 0x1108C2C,

    numBeeps : {_parent: ,_proto: {#6008D5D1},

    Other slotshave no space before the colon (:), while thenumBeepsslot hasone space there. Could thishave anything to do with our problem?

    What if that space were significant?LetstrycallingDebugwith an extraspace afternumBeeps:

    Debug(numBeeps )

    and here isthe Inspector return result that we get:

    #4418AF5 {_parent: {_parent: {#4412B25},_proto: {#6008D0C1},viewCObject: 0x1108C2C,numBeeps : ,viewclipper: 17863746,base: ,viewFlags: 577},

    _proto: {viewBounds: {#6008D681},label: Num Beeps:,entryFlags: 10753,_proto: {@189},debug: numBeeps ,preAllocatedContext: |numBeeps |},

    viewCObject: 0x1109F0C,

    entryLine: {_parent: ,_proto: {#356429},viewCObject: 0x110A83B,viewFlags: 10753,viewBounds: {#4418F4D},text: 2},

    labelLine: {_parent: ,_proto: {#356569},viewCObject: 0x110A871,text: ?Num Beeps:,viewFont: {@100},viewBounds: {#4418E2D}},

    width: 73,indent: 75,height: 13}

    So if it actsasthough the name had an extra spacemaybe it does. Lets

    check the Template Info dialog for that template more carefully(see Figure

    4). Indeed, there isa trailing space afternumBeeps. Well delete it andrebuild.

    Figure 4: Template Info dialog for numBeeps

    with an extra space at the end.

    THIRDPROBLEM

    We rebuild, download, and rerun. We write the number 2 and tap

    Beep. We get the following error in the Inspector:

    Expected an integer, got nilevt.ex.fr.type;type.ref.frame-48406(#6008D229).buttonClickScript(), 27: PushConstant NILEntering break loop: level 1

    October 1996 Newton Technology Journal

    12

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    13/20

    Newton Technology Journal October 1996

    13

    Were still in ourbuttonClickScript, about to execute the code atprogram counter 27. Heresthe NewtonScript code for the

    buttonClickScript:

    func()begin

    local beeps := StringToNumber(numBeeps.text);for i := 1 to beeps do

    :SysBeep();

    end

    Letslook at the disassembled code for the

    buttonClickScript:

    Disasm(GetCurrentFunction(0))0: FindVar numBeeps1: Push text2: GetPath 13: Push StringToNumber4: Call 15: SetVar beeps6: PushConstant 17: SetVar i8: GetVar beeps9: SetVar i|limit

    10: PushConstant 1

    11: SetVar i|incr12: GetVar i|incr13: GetVar i14: Branch 2317: PushSelf18: Push SysBeep19: Send 020: Pop21: GetVar i|incr22: IncrVar i23: GetVar i|limit24: BranchIfLoopNotDone 1727: PushConstant NIL28: Return

    #2 NIL

    Were about to execute the code at offset 27it looksasthough were at

    the end of the loop. Letslook at the valuesof our variablesto see if theyare

    reasonable:

    GetAllNamedVars(0);#4419641 {beeps: NIL,

    i: 1,i|limit: NIL,i|incr: 1,numBeeps: {_parent: {#4418345},

    _proto: {#6008D5D9},viewCObject: 0x110A57D,entryLine: {#44186F5},labelLine: {#44181FD},width: 73,indent: 75,height: 13},

    text: Beep,SysBeep: }

    It doesnt seem right thatbeeps isnil. In fact, that would explain theerror we got. The for loop expected an integer, but got nil. But whyis

    beeps nil?It wasobtained from callingStringToNumber onnumBeeps.text. Letsstart bylooking atnumBeepsmore closely:

    numBeeps := GetNamedVar(0, numBeeps);#4417EA9 {_parent: {_parent: {#4411D11},

    _proto: {#6008D0C1},viewCObject: 0x110A483,numBeeps: ,viewclipper: 17863765,base: ,viewFlags: 577},

    _proto: {viewBounds: {#6008D689},

    label: Num Beeps:,entryFlags: 10753,_proto: {@189},debug: numBeeps,preAllocatedContext: numBeeps},

    viewCObject: 0x110A57D,entryLine: {_parent: ,

    _proto: {#356429},viewCObject: 0x110A58C,viewFlags: 10753,

    viewBounds: {#4418301},text: 2},labelLine: {_parent: ,

    _proto: {#356569},viewCObject: 0x110A5C2,text: ?Num Beeps:,viewFont: {@100},viewBounds: {#44181E1}},

    width: 73,indent: 75,height: 13}

    Nowletslook at the value of thetext slot innumBeeps. Expectingto find the value of 2, we get a surprise instead:

    numBeeps.text#4632AD

    There isnt a text slot in thenumBeeps viewor template. So the valueofnumBeeps.text must be coming from theprotoLabelInputLine itself. Notice, however, that there doesseem to be atext slot with the value 2 innumBeeps.entryLine. But of course! For aprotoLabelInputLine, the input text isnt found in the text slot ofthe labelInputLine view, but in the text slot of the child viewwhere the input isactuallydone. With thisbit of fresh information we can

    nowmodifythe code in the buttonClickScript. Our codeshould actuallybe:

    func()begin

    local beeps :=StringToNumber(numBeeps.entryLine.text);

    for i := 1 to beeps do:SysBeep();

    end

    FOURTHPROBLEMWe rebuild, download, and rerun. We write in 2 in the input line and tap

    the Beep button. We get the following error in the Inspector:

    Expected an integer, got evt.ex.fr.type;type.ref.frame-48406(#6008D229).buttonClickScript(), 27: PushConstant NILEntering break loop: level 1

    Hmm. Thisisthe same location where we broke before. Last time the

    error wasExpected an integer, got nil. Thistimeit got a real number. Letstake a look atbeeps:

    GetNamedVar(0, beeps);#4418E79 2.00000

    Well, thatsthe problem. Thebeeps variable isa real number, not aninteger. Using our brilliant deductive capabilitieswe realize that

    StringToNumbermust return a real number. Letscheck within theInspector:

    continued on page 19

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    14/20

    October 1996 Newton Technology Journal

    14

    Thisarticle isan excerpt fromNewton User Interface Guidelines,

    published byAddison-Wesleyand summarizeswhat you should do to avoid

    the top 20user interface mistakes. The book providesdetailed discussionsof

    the correct approach you should use for each of the situationsdescribed here.

    Info Button

    Use the Info buttonwith the i iconand itspicker for information

    optionssuch asHelp, About, and Prefs. Alwaysplace the Info button at the

    far left end of the statusbar unlessyour application includesan Analog Clock,

    which isoptional.

    Newand ShowButtons

    If userscan create newitemsor displaydifferent viewsof information in

    your application, include a Newbutton and a Showbutton like the onesin

    the built-in applications. Put the Newbutton near the left end of the status

    bar next to the Info button ( if present) , and put the Showbutton to the right

    of the Newbutton.

    Screen Size

    Design your application to handle anyscreen size and aspect ratio. If your

    application cant scale itsviewssmall enough or cant rearrange viewcontents

    to fit the aspect ratio, notifythe user before closing your application.

    Tappingv. Writing

    Tapping isfaster than writing, so for data input favor pickers, scrolling lists

    and tables, radio buttons, sliders, and so forth over written input.

    Picker Placement and Alignment

    Align the top of a picker with the top of itsbutton or label. Make

    exceptionsfor overviewpickers, for other verywide or verytall pickers, or for

    small screens.

    Displaya picker so itsbutton or label isat least partiallyvisible, and keep

    the button or label highlighted while the picker isopen. (An overviewpicker

    can cover the label or button that makesit appear.)

    Field AlignmentBe consistent in howyou align field valueswith field labels( including

    picker labels). Generallyyou should line up a fieldslabel with the fields

    displayed value, not with the dotted line (if present) on which a user edits

    the field value. In a viewthat hasseveral fieldsin a column, line up the labels

    at their left edgesto insure a neat, orderlyappearance for your application.

    Close Box Size

    Use a regular (small) Close box in a viewwhere there are no adjacent

    buttons. Use a large Close box onlywhere there are adjacent text buttonsor

    standard-height picture buttons.

    Button Location

    Put buttonsthat affect an entire viewat the bottom of the view, and put

    buttonsthat onlyaffect part of the viewelsewhere. Group buttonsthat

    affect content and appearance at the bottom left of a view, and put buttons

    that control or initiate action at the bottom right.

    Button Spacing

    Space adjacent buttonsthree pixelsapart, and leave four pixelsbetween

    buttonsand the border of the viewtheyre in.

    Button SizeMake everytext button 13pixelshigh and center the buttonsname

    vertically. Make the button just wide enough that with the buttonsname

    horizontallycentered there are three or four pixelsbetween the name and

    the buttonsleft and right borders.

    Capitalization

    Capitalize the following itemslike sentences: check boxes, field

    labels, and picker items. Capitalize the following itemslike book titles:

    view titles, text button names, and radio buttons. In some contextsit

    makessense to capitalize differently, but your should be consistent

    within an application.

    Picker Icons

    Think twice before including iconsin pickers. Theyre hard to design and

    have limited benefit.

    Dismissinga Slip

    If dismissing a slip doesnot cause an action to take place (other than

    accepting changesmade to data in the slip), use a Close box for putting away

    the slip. In thiscontext the Close box meansclose or put away. Use a

    take-action button and a Close box if usershave a choice when dismissing

    the slip of initiating an action or canceling. In thiscontext the Close box

    meanscancel.

    Take-Action ButtonName a slipstake-action button with a specificverb such asPrint, Fax,

    or File. Onlyuse vaguelyaffirmative namessuch asOK and Yeswhere you

    want to force usersto scan other partsof the slip to verifywhat action the

    button initiates.

    Fonts

    Use fontscarefully. For the voice of the system and application use the

    bold style of the System font in 9-or 10-point sizes. For valuesa user can

    change use Casual 10-and 12-point. (Those are the fontsthat are preset by

    the system protos.)

    Avoiding Common UI Mistakes

    Product Development

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    15/20

    Newton Technology Journal October 1996

    15

    than 29pixelstall and wide. Leaving a little space helpsseparate icons.

    Limit the length of an ExtrasDrawer iconsname to between 9and 11

    charactersper line. Put a blank space in the name where you want it to break

    and wrap onto another line.

    Make a Newton icon more distinctive and easier to identifybygiving it a

    distinctive silhouette rather than a boxyshape.

    StorageAllowusersto move your applicationsdata between storage locations

    with the Filing button in the ExtrasDrawersstatusbar. Thisisthe method

    used bythe built-in applications.

    Date and Time Input

    To input datesand timesuse the speciallydesigned Newton pickers.

    Keyboard Button

    If your application includesa Keyboard button on the statusbar or at the

    bottom of a slip, use the larger-size button (asin the Notepad) unlessspace

    on the statusbar isconstrained (asin the Date Book) .

    Punctuation to Avoid

    Dont use ellipses(...) in button names, picker labels, or list-picker items.

    Do put an ellipsisat the end of the title or the message text in a statusslip, but use three periodsrather than an ellipsischaracter. Also use an ellipsis

    to accommodate an item whose text istoo long to fit on a line in the space

    available for it ( for example, in overviews).

    Dont use a colon at the end of a title, a heading, or a field label.

    Extras Drawer Icons

    To avoid overlapping iconsin the ExtrasDrawer, make yoursno more

    Newton Connection Utilities1.0(NCU) isenabling technologythat will

    integrate your Newton device with your existing WindowsPC or Macintosh

    OS based computer. NCU will enable you to get connected with your favorite

    desktop computer applications.

    The featuresinclude Backup, Synchronize, Install, Import/Export and

    Keyboard. The Backup function createsa backup file of your Newton PDA

    and restoresinformation from that file to your Newton device whenever

    necessary. The Synchronize function enablesdirect exchange of information

    between popular desktop applicationsand your Newton PDA. The Install

    Package function enablesthe installation of Newton software onto your

    Newton PDA. The Import function enablesthe sending of information from

    PIMs, word processors, or text filesinto your Newton PDA. The Export

    function enablesthe sending of information from your Newton PDA to your

    personal computer in a varietyof formats, including word processing and PIMformats. The Keyboard function enablesusage of your PC keyboard to enter

    information directlyinto your Newton PDA.

    Integrate the Newton with the following applicationsusing NCU:

    Mac OS based computer:

    NowUp To Date 3.0/3.5

    NowContact 3.0/3.5

    NowDateBook 4.01

    NowTouchBase 4.01

    ClarisOrganizer 1.0

    RTF

    Delimited ASCII

    Windows PC:

    Schedule+ 7.0

    Ecco 3.03

    LotusOrganizer 2.1

    SideKick95

    Sidekick for Windows1.0

    Sidekick for Windows2.0

    Delimited ASCII

    Word 2.0/6.0/7.0

    NTJ

    Get Connected!

    Newton Directions

    Newton Connection Utilities 1.0 Beta

    this Summer,Shipping this Fall.

    by Cami Hsu, Apple Computer, Inc.

    NTJ

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    16/20

    October 1996 Newton Technology Journal

    16

    The High Level Frame Desktop Integration Library(HLFDIL) isused to

    move Newton framesand arraysto and from a desktop machine, running

    either the Macintosh OS or Windows. (In common usage, HLFDIL isusually

    shortened to Frame Desktop Integration Library, or FDIL, and the two terms

    are used interchangeablythroughout thisarticle.) Before the HLFDIL can be

    opened a connection between the Newton and the desktop machine must

    be established using the CommunicationsDesktop Integration Library

    (CDIL).

    The FDIL isused to map the dynamicstructure of Newton framesto the

    staticstructuresused on desktop machines. Aswith the CDIL, it is

    implemented in C+ + but hasa C language API. The basicassumption of

    the FDIL isthat the format of the Newton framesbeing moved isalready

    known. A C language structure having a one-to-one correspondence with the

    Newton frame can be defined, and the desktop programmer can define the

    mapping of slotsto fields. However, since there are caseswhen the

    programmer maynot knowthe structure of the Newton frame in advance or

    when additional slotshave been added to the frame, there must be a wayto

    handle these unexpected or unknown slots. Thisishandled bythe FDIL by

    uploading these slotsasunbound data, that is, data for which there isnot a

    previouslydefined memorylocation of the appropriate size and type. The

    unbound data istherefore put into memoryon the desktop machine in a

    tree structure which defineswhere the data isin the NewtonScript frame in

    relation to other slotsin the frame.

    Throughout thisarticle, the use of the FDIL to transfer Newton frame data

    will be discussed. However, it should be remembered that it isalso used to

    transfer Newton arraydata. It isworth noting that the FDIL cannot be used to

    transfer simple data such asintegersor stringsunlesstheyare part of a frame

    or array. It isrecommended that such data be transferred using the CDIL

    mechanism, or put into a simple NewtonScript frame, such as

    fooFrame:={myInteger:3}.

    Openingthe FDIL and CreatingObjects

    After the CDIL connection, or pipe, hasbeen opened, the FDIL maybe

    initialized and used. The FDIL routine FDInitFDIL iscalled asfollows:

    fErr = FDInitFDIL();

    Anyerror in initializing the librarywill be returned. FDIL errorsfall in the -

    28000range and a complete list maybe found at the end of the FDIL section

    of the documentNewton Desktop Integration Librarieswhich can be found

    on the DIL web page at http://dev.info.apple.com/newton/tools/dils.html.

    Next, one or more FDIL objectsmust be created using the routine

    FDILCreateObject which isdefined as:

    DILObj *FDCreateObject(short objType,char *objClass);

    The first argument describeswhether the object being created isan array

    or a frame, and the second argument isan optional classname which

    NewtonScript arraysmaycarry. Each frame or arraywhich istransferred must

    have a separate object created for it. Thisincludessub-framesand sub-arrays

    within a parent frame or array.

    For example, for the following NewtonScript frame, three separate FDIL

    objectsmust be created before the frame can be defined on the desktop:

    aFrame:={name:foo,phone:[333-444-5555,101-202-3333],address:{street:123 Main, town:Fooburg,state:GA, postalCode:12345}

    }

    There must be an FDIL object for the main frame,aFrame, one for thephone sub-arrayand one for theaddress sub-frame.

    The callsto create these FDIL objectswould look like this:

    DILObj *aFrameObj, foneObj, addrObj;

    aFrameObj = FDCreateObject(kDILFrame, NULL);foneObj = FDCreateObject(kDILArray,homePhone);addrObj = FDCreateObject(kDILFrame, NULL);

    In thisexampleFDCreateObject iscalled twice with thepredefined constantkDILFrame to create an object for defining a frameand once to create an arrayobject using the

    kDILArrayconstant for the

    first argument. In the case of the array, we also supplythe classname

    homePhone asit isa named (classed) array. Named arraysaredescribed on page 2-9of theNewtonScript Reference. (An electronicversion

    of thisbook isavailable from the Newton documentation web page noted

    above.)

    Asof thiswriting a known bug existswhich will throwan error on the

    Newton when a string isdownloaded, if an arrayincludesan unnamed string

    (that is, a classlessstring) asone of itselements. The work around isexplicitly

    to give unclassed stringsthe default classof string when theyare array

    members. See the routineDearchiveFrame in the FDIL Archive Labsolution code for an example of thiswork around. Thisbug should be fixed

    in future releasesof the HLFDIL.

    DefiningObjects

    Once you have created an FDIL object, you maybegin to bind memory

    locationsto the object. Thisprocessdescribesto the FDIL where data being

    transferred to or from the Newton will come from or go to. In other words,

    bybinding a memorylocation on the desktop to a slot in a Newton frame,

    the FDIL knowswhere to put data or where to go to get data. The memory

    locationsused in thisbinding maybe a variable on the stack, a global

    memorylocation or a dynamicallyallocated heap location, depending on the

    use and duration of the data being transferred.

    The routineFDbindSlot isused to connect the memorylocation

    The High Level Frame Desktop Integration Library(HLFDIL)by Bill Worzel, Newton Developer Training

    Communications Technology

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    17/20

    Newton Technology Journal October 1996

    17

    with the Newton slot. Itsformal definition is:

    objErr FDbindSlot(DILObj *theObj,char* slotName,void *bindVar, short varType, longmaxLen,long curLen, char *objClass);

    The first argument (theObj) isthe object created to define the framebeing transferred, and the second (slotName) isthe name of the slot

    that isbeing bound.The third (bindVar) isa pointer to the memorylocation to which the

    slot isbeing connected. When data isto be downloaded to the Newton this

    will be the location of the data being sent. In the case of an upload from the

    Newton thisisthe place where the received data will be put. In the latter case

    it isup to the programmer to make sure there isenough room to hold the

    data being received. ThemaxLen argument givesthe total size of theobjectsbuffer, and thecurLen argument tellshowmuch of that bufferhasbeen filled byyour desktop application (that is,maxLen isused forreceiving data from the Newton device, andcurLen isused for sending it) .In the case of an arrayor frame,maxLen andcurLen should be set to -1.

    ThevarType argument describeswhat type of data object the slotbeing bound isexpected to be. The following table showsthe existing types:

    kDILPlainArray // as opposed to a classed arraykDILArray // array with class name associatedkDILBoolean // true or falsekDILUnicodeCharacter // 16-bit characterkDILCharacter // 8-bit ASCIIkDILFrame // object is a framekDILSmallRect // packs a Newton rect into a longkDILImmediate // Newton immediate value (not int)kDILInteger // 30-bit integerkDILNIL // Newton nil value (NULL)kDILBinaryObject // double or other binary sequencekDILString // char *kDILSymbol // handled as char *

    Of these typesseveral are worth special mention.

    kDILArrayversus

    kDILPlainArray-manyarrayson the

    Newton are simplysequencesof data but a fewhave a classassociated with

    them.kDILPlainArray hasno classassociated with it whilekDILArray does.kDILBoolean andkDILNIL -both have platform-specific

    definitionsfor the valuestrue, false and nil.

    kDILSmallRect isautomaticallyused when a frame on theNewton which isused to store a rectangle issent and the rectangle values

    (top, left, bottom, right) all fit in a single byte value. In thiscase the valuesare

    packed into a single long value.

    kDILBinaryObject isused for anyunspecified binaryobject(such assounds, pictures, and so forth) aswell asfor the Newton Real type.

    Note, however, that unlike integersor immediates, platform-specificbyte

    ordering must be accounted for.Make sure you compile using 8-byte doublesif you are going to transfer

    Real numbers. When transferring Newton Real numbers, you must set your

    development environment to use 8-byte double valuesor it will interpret the

    realsreceived asa different value than expected. Thisisusuallyan option

    specificto your system. For example, Metrowerksdefaultsto 4-byte doubles

    and the 8-byte double option must be specified in the compiler optionsin

    the Preferencesmenu item. MPWdefaultsto 8-byte doublesand so no special

    action must be taken.

    kDILString includesboth classed and unclassed strings.kDILSymbol isa Newton symbol (such asmySymbol) transferred to

    and from the desktop asa C string.

    The last argument inFDbindSlot (objClass) isthe class, ifany, of the object. While manyobjectson the Newton have no class

    associated with them, manymayhave a classassigned bythe programmer or

    bythe system. For example, while most stringshave no classassociated with

    them, theymayhave one assigned explicitlybythe Newton programmer.

    Conversely, Newton Real numbersalwaysare transferred asobjectsof type

    kDILBinaryObject with a classof Real. If an object hasnospecial classassociated with it, thisargument should be a NULL to use the

    default classsymbol (string, array, etc ). If it hasa classit istransferred

    with a C string, such asfor the classname.

    An example taken from the SoupDrink sample code involvesdownloading

    a name frame to the Newton Name soup. The following pseudo-

    NewtonScript describesa card frame and itsassociated FDIL type:

    card := {

    cardType:kDILInteger,Name: kDILFrame,Address: kDILString,City: kDILString,Region: kDILString,Postal_Code: kDILString,

    phones: kDILArray,sorton: kDILString}

    Thisisonlya code fragment from the SoupDrink example. The variables

    shown (such asthe name strings) are assigned valuesin earlier code. To see

    the full code, see the SoupDrink code walk through.

    In the same waytheName frame and thephones arraymaybedefined as:

    Name := {

    class: kDILSymbol,first: kDILString,last: kDILString

    }

    phones := [kDILString, kDILString, ...]

    While not shown here, the elementsof thephones arrayeach have aseparate classassociated with them such asHomePhone, WorkPhone,

    and so forth.

    The code to create the FDIL object for thisstructure is:

    name = FDCreateObject(kDILFrame, NULL);FDbindSlot(name, Class, (void *)&pClass, kDILSymbol,

    strlen(pClass), -1, NULL);FDbindSlot(name, first, (void *)&fName, kDILString,

    strlen(fName), -1, NULL);FDbindSlot(name, last, (void *)&lName, kDILString,

    strlen(lName), -1, NULL);

    phones = FDCreateObject(kDILArray, NULL);FDbindSlot(phones, NULL, (void *)&phoneNo, kDILString,

    strlen(phoneNo), -1, HomePhone));

    entry = FDCreateObject(kDILFrame, NULL);FDbindSlot(entry, cardType, (void *)&cardType,kDILInteger, sizeof(int), -1, NULL) ;FDbindSlot(entry, Name, (void *)name, kDILFrame, 0, -1,

    NULL);FDbindSlot(entry, Address, (void *)&addr, kDILString,

    strlen(addr), -1, NULL) ;FDbindSlot(entry, City, (void *)&town, kDILString,

    strlen(town), -1, NULL) ;FDbindSlot(entry, Region, (void *)&state, kDILString,

    strlen(state), -1, NULL) ;FDbindSlot(entry, Postal_Code, (void *)&zip,kDILString, strlen(zip), -1, NULL) ;

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    18/20

    FDbindSlot(entry, phones, (void *)phones, kDILArray, 0,-1, NULL) ;

    FDbindSlot(entry, sorton, (void *)&sName, kDILString,strlen(sName), 0, Name);

    Here the FDIL objectsname andphones are bound to slotsin theentryobject. Note also that the string in thephones arrayhasa classassociated with it, HomePhone. Once theentry object isdefined it is

    readyto be used to download it to the Newton.

    TransferringData

    Once an FDIL object iscreated and the slotsare defined bybinding them

    to desktop memory, it maybe used to transfer data to or from the Newton.

    Thisisdone byusing the routinesFDget to upload and FDput to download

    the object and itsassociated data. These routinesare defined as:

    objErr FDput (DILObj *entry, short type, CDILPipe *pipe);

    objErr FDget (DILObj *entry, short type, CDILPipe *pipe,long timeOut, CDILPipeCompletionProcPtrcallBack,long refCon);

    Notice that the CDIL pipe isused here since thisisthe first time that data

    will actuallybe transferred. Note also that the FDget routine maybe called

    asynchronouslybypassing a procedure pointer in for the fifth argument.

    In both routinesthe first argument (entry) isthe master object beingtransferred. It mayhave sub-framesand arraysobjectsbound to it but thisis

    the top level object. The next argument (type) isthe FDIL type(kDILFrame orkDILArray) of thismaster object. The thirdargument (pipe) isthe CDIL pipe being used to transfer the data.

    For FDget we have these additional arguments:

    The fourth argument (timeOut) defineshowlong the FDIL shouldattempt to transfer the object before giving up and returning an error. The

    timeout value ismeasured in millisecondson Windowsmachinesand ticks

    on Macintosh OS machines.

    The next argument (callBack

    ) isa pointer to a callback routine if

    the FDget call ismade asynchronously. If you are making the call

    synchronously, simplypassNULL for thisargument.

    The last argument (refCon) isan arbitraryvalue which can be passedto your completion routine.

    SoupDrink downloadsthe previouslydefined entryFDIL object to the

    Newton using thiscall toFDput:

    FDput(entry, kDILFrame, ourPipe);

    The Newton must be in a state to receive a frame or arraybefore it issent

    from the desktop machine. See the SoupDrink code for the Newton for an

    example of code which importsand exportsframes.

    Unbound DataUnbound data isdata which arrivesat the desktop but isnot bound to

    anymemorylocationsbycallstoFDbindSlot(). Thistypicallyoccursin two situations: when the desktop programmer doesnot knowthe

    structure of the Newton data beforehand and when there are previously

    unknown slotswhich have been added to a frame.

    An example of the first case isa program which allowsthe programmer to

    select what will be transferred. SoupDrink doesthiswhen it allowsthe

    programmer to name a Newton soup which isto be uploaded. In thiscase

    SoupDrink providesa universal wayto handle all soupsbyuploading the

    information asunbound data which it then writesto file.

    The second situation occurseither when there isa system or program

    update or when applicationswhich tag along on system soupsare added.

    For example, if a newversion of the Namesapplication added newslotsto

    the soup framesstored for a Name card, SoupDrink would get the data from

    the old slotsif it used the entrydefinition shown above but would not have a

    place allocated to put newdata slots. Similarly, if a newcontact application

    wasloaded into the Newton, it might choose to build off of the existing

    Namesapplication but add additional information to the soup entries. In thiscase SoupDrink would get the standard data but would not be prepared for

    the data added to the Namessoup entries.

    In either case, unbound data providesa wayto accept unknown data slots

    and then to parse them for further disposition. Following isa description of

    unbound data and howto extract information about the data once it has

    arrived at the desktop.

    Unbound data islinked together in a chain of data structuresof type

    slotDefinition. TheslotDefinition data type isdefinedasfollows:

    typedef struct slotDefinition{short varType; // Data type of this variable

    void *var; // Actual pointer to dataulong length; // Length of data (strings)ulong maxLength; // Maximum Length of dataulong streamLen; // internalulong bufIndex; // internallong namePrec; // internallong classPrec; // internalchar *slotName; // Name of slot for this varchar *oClass; // class of this objectshort slotType; // Data type of this slotulong truncSize; // Current size of truncated objectlong childCnt; // Number of child nodeslong peerCnt; // Number of peer nodesshort dataFilled; // TRUE if data added in this oplong internalFlags; // Internal state flagsshort boundData; // internalstruct slotDefinition *children;struct slotDefinition *next;} slotDefinition ;

    The fieldswhich are significant to understanding the structure of

    unbound data are thechildCnt, peerCnt, childrenandnext fields. Unbound data isstored asa seriesof linkedslotDefinition structureswhich mayhave siblings(peers) orchildren. In thisscheme,peerCnt isthe number of peersan item has,childCnt isthe number of children,next isa pointer to theslotDefinition for the next peer in the list andchildren isapointer to the start of the chain ofslotDefinitions for thechildren of the item.

    Thisisshown in the following diagram:

    October 1996 Newton Technology Journal

    18

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    19/20

  • 7/28/2019 Newton Technology Journal: Volume 2, Number 5

    20/20