You are on page 1of 894

Newton Programmers Guide

Alpha Draft 1.1


October 8, 1993 PIE Technical Publications Apple Computer, Inc. 1993

Apple Computer, Inc. 1993, 1944, Apple Computer, Inc. All rights reserved. No part of this publication or the software described in it may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Computer, Inc., except in the normal use of the software or to make a backup copy of the software. The same proprietary and copyright notices must be afxed to any permitted copies as were afxed to the original. This exception does not allow copies to be made for others, whether or not sold, but all of the material purchased (with all backup copies) may be sold, given, or loaned to another person. Under the law, copying includes translating into another language or format. You may use the software on any computer owned by you, but extra copies cannot be made for this purpose. Printed in the United States of America. The Apple logo is a registered trademark of Apple Computer, Inc. Use of the keyboard Apple logo (Option-Shift-K) for commercial purposes without the prior written consent of Apple may constitute trademark infringement and unfair competition in violation of federal and state laws. No licenses, express or implied, are granted with respect to any of the technology described in this book. Apple retains all intellectual property rights associated with the technology described in this book. This book is intended to assist application developers to develop applications only for licensed Newton platforms.

Apple Computer, Inc. 20525 Mariani Avenue Cupertino, CA 95014 408-996-1010 Apple, the Apple logo, APDA, AppleLink, AppleTalk, LaserWriter, Macintosh, and Newton are trademarks of Apple Computer, Inc., registered in the United States and other countries. Balloon Help, Espy, Geneva, the light bulb logo, MessagePad, NewtonScript, Newton Toolkit, New York, QuickDraw, and System 7 are trademarks of Apple Computer, Inc. Microsoft is a registered trademark of Microsoft Corporation. Windows is a trademark of Microsoft Corporation. Adobe Illustrator and PostScript are trademarks of Adobe Systems Incorporated, which may be registered in certain jurisdictions. FrameMaker is a registered trademark of Frame Technology Corporation. Helvetica and Palatino are registered trademarks of Linotype Company. ITC Zapf Dingbats is a registered trademark of International Typeface Corporation. Simultaneously published in the United States and Canada.

ALL IMPLIED WARRANTIES ON THIS MANUAL, INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE LIMITED IN DURATION TO NINETY (90) DAYS FROM THE DATE OF THE ORIGINAL RETAIL PURCHASE OF THIS PRODUCT. Even though Apple has reviewed this manual, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS MANUAL, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. AS A RESULT, THIS MANUAL IS SOLD AS IS, AND YOU, THE PURCHASER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS MANUAL, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modication, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specic legal rights, and you may also have other rights which vary from state to state.

LIMITED WARRANTY ON MEDIA AND REPLACEMENT If you discover physical defects in the manual or in the media on which a software product is distributed, APDA will replace the media or manual at no charge to you provided you return the item to be replaced with proof of purchase to APDA.

Contents
Figures and Tables xxiii xxix

Preface

About This Book

Audience xxix Related Books xxx Sample Code xxx Conventions Used in This Book xxxi Special Fonts xxxi Tap Versus Click xxxi Frame Code xxxii Developer Products and Support xxxiii Undocumented System Software Objects xxxiv

Chapter 1

Overview

1-1

Operating System 1-3 Memory 1-4 Packages 1-5 System Services 1-5 Object Storage System 1-6 View System 1-7 Recognition 1-8 Intelligent Assistant 1-9 Communications 1-10 Imaging and Printing 1-11 Sound 1-12 Book Reader 1-12 Other Services 1-13 Find 1-13 Filing 1-14 Routing 1-14 iii

Application Components 1-15 Using System Software 1-17 The NewtonScript Language 1-18

Chapter 2

Views

2-1

Templates and Views 2-2 Templates 2-2 Views 2-3 Coordinate System 2-7 Dening View Characteristics 2-9 Class 2-11 Behavior 2-13 Handling Pen Input 2-15 Location, Size, and Alignment 2-16 viewBounds Slot 2-16 View Size Relative to Parent Size 2-18 Using Screen-Relative Bounds 2-18 viewJustify Slot 2-20 viewOriginX and viewOriginY Slots 2-28 Appearance 2-28 viewFormat Slot 2-28 Custom Fill and Frame Patterns 2-32 viewTransferMode Slot 2-32 Opening and Closing Animation Effects 2-34 Other Characteristics 2-39 Inheritance Links 2-40 View Instantiation 2-41 Declaring a View 2-42 Creating a View 2-43 Closing a View 2-45 Getting References to Views 2-45 Displaying, Hiding, and Redrawing Views 2-47

iv

Dynamically Adding Views 2-54 Showing a Hidden View 2-55 Adding to the stepChildren Array 2-55 Using the AddStepView Function 2-57 Using the BuildContext Function 2-58 Creating Templates 2-58 Making a Picker View 2-59 Functions for Dynamically Adding Views 2-60 Making Modal Views 2-66 Finding the Bounds of Views 2-70 Animating Views 2-73 Dragging a View 2-81 Scrolling View Contents 2-82 Working With View Highlighting 2-87 Creating View Dependencies 2-91 View Synchronization 2-93 Laying Out Multiple Child Views 2-96 Working With Keyboard Views 2-100 Miscellaneous View Operations 2-104 Optimizing View Performance 2-105 Using Drawing Functions 2-106 View Fill 2-106 Redrawing Views 2-106 Memory Usage 2-107 Scrolling 2-108 Summary of Functions and Methods 2-109

Chapter 3

Working With Proto Templates


Container Protos 3-3 protoApp 3-3 protoDrawer 3-5 protoFloater 3-6 protoFloatNGo 3-8

3-1

Input Protos 3-10 protoDateExpando 3-10 protoExpandoShell 3-12 protoInputLine 3-17 protoLabelInputLine 3-19 protoPhoneExpando 3-23 protoTextExpando 3-26 Control Protos 3-29 protoActionButton 3-29 protoCheckbox 3-30 protoCloseBox 3-32 protoFilingButton 3-34 protoFolderTab 3-35 protoLabelPicker 3-36 protoLargeCloseBox 3-39 protoPicker 3-40 protoPictIndexer 3-46 protoPictRadioButton 3-48 protoPictureButton 3-50 protoRadioButton 3-51 protoRadioCluster 3-53 protoRCheckbox 3-55 protoRecToggle 3-57 protoSlider 3-58 protoTextButton 3-60 Roll Protos 3-62 protoRoll 3-62 protoRollBrowser 3-66 protoRollItem 3-68 Miscellaneous Protos 3-70 protoBorder 3-70 protoDivider 3-70 protoGauge 3-72 protoGlance 3-73 protoKeyboard 3-75

vi

protoKeypad 3-76 protoLabeledBatteryGauge 3-77 protoPrintFormat 3-78 protoSetClock 3-79 protoStaticText 3-81 protoStatus 3-82 protoStatusBar 3-83 protoTable 3-84 protoTextList 3-90 protoTitle 3-92 Creating Custom Protos 3-93 Summary of Prototypes 3-95

Chapter 4

Working with View Classes

4-1

Generic Container View (clView) 4-1 General Input View (clEditView) 4-3 Text View (clParagraphView) 4-6 Specifying a Font 4-11 Lightweight Text View 4-15 Shape View (clPolygonView) 4-16 Picture View (clPictureView) 4-19 Keyboard View (clKeyboardView) 4-21 Dening the Keys 4-23 KeyLegend 4-24 KeyResult 4-24 KeyDescriptor 4-25 Specifying Key Dimensions 4-26 Analog Gauge View (clGaugeView) 4-28 Monthly Calendar View (clMonthView) 4-31 Scaled View (clRemoteView) 4-33 Outline View (clOutline) 4-34 Summary of View Classes 4-37

vii

Chapter 5

Handling System Messages

5-1

Initialization and Termination Messages 5-2 viewSetupFormScript 5-4 viewSetupChildrenScript 5-4 viewSetupDoneScript 5-5 viewQuitScript 5-6 Drawing-Related Messages 5-7 viewShowScript 5-7 viewHideScript 5-7 viewDrawScript 5-8 viewHiliteScript 5-9 Scrolling and Overview Messages 5-10 viewScrollDownScript 5-10 viewScrollUpScript 5-10 viewOverviewScript 5-11 Input-Related Messages 5-12 viewClickScript 5-13 viewStrokeScript 5-14 viewGestureScript 5-15 viewWordScript 5-17 Other Messages 5-19 powerOffScript 5-19 printNextPageScript 5-20 soupChanged 5-21 viewAddChildScript 5-21 viewChangedScript 5-22 viewDropChildScript 5-23 viewIdleScript 5-23 Summary of System Messages 5-25

viii

Chapter 6

Written Input and Recognition

6-1

Overview 6-1 Controlling Recognition in Views 6-2 View Flags for Recognition 6-2 Combining View Flags 6-7 Text Flags 6-8 Using Dictionaries 6-8 Enumerated and Lexical Dictionaries 6-9 System-Supplied Dictionaries 6-9 Locale-specic Dictionaries 6-10 RAM-based Dictionaries 6-11 About the User Dictionary 6-11 Creating a RAM-based Dictionary 6-12 Using the RAM-based Dictionary 6-16 Removing a RAM-based Dictionary 6-17 Function Reference 6-18 Recognition Functions 6-18 Hit Testing Functions 6-22 Dictionary Functions 6-23 Summary of Recognition Functions 6-27 Recognition Functions 6-27 Hit-Testing Functions 6-27 Dictionary Functions 6-27

Chapter 7

Data Storage and Retrieval


Overview 7-1 Frames and Slots 7-2 Soups 7-2 Stores 7-3 Union Soups 7-3

7-1

ix

Entries 7-3 Queries and Cursors 7-4 Modifying Entry Frames 7-4 Storing Persistent Data 7-4 Soups and Boots 7-4 Sharing Soup Data 7-6 Optimizing Data Storage Performance 7-7 Soup Overhead 7-7 Alternatives to Using Soups 7-8 Optimizing Alternative Storage Schemes 7-8 Stores 7-9 Store Functions 7-9 About the Store Metasymbol 7-9 Soups 7-20 Naming Soups 7-21 Creating Soups and Union Soups 7-21 Accessing Soup Data 7-22 Getting System Soups 7-23 Adding Entries to Soups 7-23 Making Information Available to All Entries in a Soup 7-24 Creating Your Applications Soups 7-24 Sharing Soups With Other Applications 7-27 Registering Your Application for Notication 7-27 Unregistering Your Application for Notication 7-28 Receiving Notications 7-28 Sending Notications 7-29 Making Changes to Other Applications Soups 7-29 Cleaning Up Leftover Soup 7-30 But I Really Want to Remove My Soups 7-31 Determining a Soups Size 7-32 Storing User Preference Data 7-33 Soup Functions 7-34 About the Soup Metasymbol. 7-34

Queries and Cursors 7-47 Performing a Query 7-47 The Cursor 7-47 Counting the Number of Entries in a Soup Query and Cursor Functions 7-49 About the Cursor Metasymbol 7-49 Entries 7-58 Entries and RAM 7-59 Sharing Entry Data 7-60 Entry Functions 7-60 About the Entry Metasymbol 7-60 Advanced Techniques 7-65 Getting or Setting the Default Store 7-65 Detecting Null Union Soups 7-66 Summary of Functions and Methods 7-68 Accessors 7-68 Stores 7-68 Soups 7-69 Entries 7-69 Queries and Cursors 7-70 Notication 7-70 Soup Creation 7-71 Special-Purpose 7-71 Utility 7-71

7-48

Chapter 8

Accessing System Data

8-1

Notepad Application 8-2 Names Application 8-3 Dates Application 8-5 Meeting Frames 8-6 To-do Frames 8-10 System and User Preferences Data 8-11 User Conguration Entry 8-11 Application Preferences Code Example Globals 8-20

8-19

xi

Chapter 9

Drawing

9-1

Overview 9-2 How to Draw 9-3 Function Reference 9-4 Shape-Creation Functions Shape Operations 9-9 Other Drawing Functions

9-4 9-13

Chapter 10

Working With Sound

10-1

Event-related Sounds 10-1 Sounds in ROM 10-2 Sounds for Predened Events 10-3 The Sound Frame 10-4 Creating Sound Frames Procedurally 10-4 Cloning Sound Frames 10-5 Creating and Using Custom Sound Frames 10-5 Playing Sounds on Demand 10-6 Synchronous and Asynchronous Sound 10-6 Hearing Is Believing 10-7 About the Sound Chip 10-8 Sounds Like Fun 10-8 Pitch Shifting 10-9 Manipulating Sample Data 10-10 Function Reference 10-11 Methods 10-13

Chapter 11

The Intelligent Assistant

11-1 11-2

Human Interface to the Assistant 11-2 Intelligent Assistance vs. Online Help IA From the User s Perspective 11-4 Get My Drift, Newt? 11-5

xii

Programmers Guide to the Assistant 11-7 Architectural Overview 11-7 Structure of the Action Template 11-10 Required Slots 11-11 Sample Action Template 11-13 Structure of the Target Template 11-13 Required Slots 11-13 The lexicon Slot (Optional) 11-14 Sample Target Template 11-15 Structure of the Task Template 11-15 Required Slots 11-16 Optional Slots 11-19 Returned Values 11-19 Sample Task Template 11-22 The Postparse Method 11-23 A Sample Postparse Method 11-23 A Parsing Example 11-24 Parsing for Dollars (and Other Special-Format Objects) 11-26 Registering and Unregistering the Task Template 11-27 Resolving Verb Conicts 11-28 A Strategy for Resolving Verb Conicts 11-29 Adding Assistance to Your Application 11-30 Summary: Extending the Intelligent Assistant 11-30

Chapter 12

Additional System Services

12-1

Find 12-1 Supporting Find In Your Application 12-4 Programmers Overview of Find 12-5 Choosing a Finder Proto 12-7 Search Method Interfaces 12-7 Interface to the Find Method 12-8 Interface to the DateFind Method 12-9

xiii

Implementing Search Methods 12-9 The StandardFind Function 12-10 Creating the title Slot 12-11 Tips for Implementing the DateFind Method 12-12 Returning the Results of the Search 12-12 Creating the title Slot 12-13 Using the soupFinder proto 12-13 Using the ROM_compatibleFinder Proto 12-17 Storing The Result Frame 12-19 Reporting Progress to the User 12-20 Sample Search Methods 12-22 Finding Text With soupFinder 12-22 Finding Text With ROM_CompatibleFinder 12-23 DateFind Method Using soupFinder 12-25 ShowFoundItem Method 12-27 Handling Messages From the Find Overview 12-30 Supporting Global Finds 12-30 Creating an Application Identier Symbol 12-30 Storing Your Application Symbol in the AppSymbol Slot 12-31 Registering Your Application for Global Finds 12-31 Unregistering Your Application 12-32 Registration Unnecessary for Local Finds 12-33 Writing Your Own Finder Proto 12-33 Modifying Existing Finder Protos 12-33 Methods for Custom Finder Protos 12-34 Handling Messages From the Find Overview 12-36 FileAs 12-36 MoveTo 12-37 Delete 12-37 Filing 12-37 Programmers Overview of Filing 12-38 The protoFilingButton View and the lingChanged Message 12-38 The protoFolderTab View and the lterChanged Message 12-39

xiv

The folderChanged Message 12-41 Adding Filing Support to Your Application Required Slots 12-41 Required Methods 12-44 Adding the Filing Button 12-48 Adding the Folder Tab View 12-49 Filing Methods 12-50 Undo 12-51 Notication 12-52 Idling 12-54

12-41

Chapter 13

Routing

13-1

Overview 13-1 Adding Routing to Your Application 13-5 Dening Your Base View Slots 13-5 appSymbol 13-5 target 13-5 targetView 13-6 setupTarget 13-6 setupRoutingSlip 13-7 Creating a Routing Frame 13-7 title 13-8 routeForm 13-8 routeScript 13-9 formats 13-9 Adding Your Routing Frame 13-9 Deleting 13-10 Duplicating 13-11 Beaming 13-12 PutAway 13-12 Card Transfer 13-14 Printing, Faxing, and Mail 13-14 Creating a Format 13-15

xv

Accessing Your Target Data 13-16 Format Issues 13-17 Dening a Format Frame 13-18 Adding Your Format Frame to the Root View Multiple Formats 13-21

13-20

Chapter 14

Communications

14-1

Introduction 14-1 Endpoints 14-2 Options 14-2 Specifying the Service 14-3 Serial Endpoints 14-4 General Input/Output Parameters 14-6 Flow Control 14-7 Modem Endpoints 14-9 Modem Error Control 14-10 MNP Allocation 14-11 MNP Compression Type 14-11 Modem Dialing Preferences 14-12 Address Option 14-13 Serial Endpoints With MNP Compression 14-13 IR Endpoints 14-15 AppleTalk ADSP Endpoints 14-16 Address Option 14-17 Instantiating the Endpoint 14-18 Establishing a Connection 14-18 Sending Data 14-20 Receiving Data 14-22 Receiving Partial Input 14-26 Creating a State Machine 14-27 Checking the Endpoint State 14-29 Changing or Adding Options 14-30 Handling Exceptions 14-32

xvi

Closing a Connection 14-32 AppleTalk Functions 14-34 Opening and Closing the AppleTalk Drivers Obtaining Zone Information 14-35 NetChooser Function 14-37 Summary of Methods and Functions 14-40

14-34

Chapter 15

Localizing Newton Applications

15-1

The International Frame 15-1 How Locale Affects Recognition 15-3 Examining the Current Locale Bundle 15-3 Recognition Slots in the Current Locale Bundle 15-3 String Slots in the Current Locale Bundle 15-4 Other Slots in the Current Locale Bundle 15-13 Customizing the Current Locale Bundle 15-14 Creating a Custom Locale Bundle 15-15 Adding the Bundle to the Locales Array 15-16 Setting the New Locale 15-16 Removing the New Locale Bundle 15-16 Summary: Customizing Locale 15-17 Localized Output 15-18 Date and Time Values 15-18 Formatting Date and Time Values 15-19 Formatted Numeric Strings 15-22 Miscellaneous Date and Time Functions 15-23 Currency Values 15-23 Formatting Currency Values 15-23 Supporting Multiple Languages 15-24 Function Reference 15-25 Date and Time String Specication Constants 15-34 Summary of Functions 15-37 Locale Functions 15-37 Date and Time Functions 15-37

xvii

Formatted Date/Time Functions 15-38 Miscellaneous Date/Time Functions 15-38 Utility Functions 15-38

Chapter 16

Supporting Newton Connection

16-1

How Connection Handles Soup Data 16-2 Writing Meta Data to the Meta Data Soup 16-6 Meta Data Format 16-7 General Items 16-13 Soup 16-13 Name 16-14 Version 16-14 NewEntry 16-14 Moving Data Between Newton Soups and Connection Data Browser and Detail Window Flow of Control BrowserExport 16-19 EditExport 16-20 EditImport 16-21 Export 16-23 Import 16-24 Controlling the Connection Windows 16-25 DisplayInfo 16-26 EditInfo 16-29 Column0Width 16-31 CompareScripts 16-32 ExportInfo 16-34 Moving Data to and From External Files 16-35 TabExport 16-36 TabImport 16-37 NativeExport 16-39 NativeImport 16-40 NativeExportExceptions 16-42 ExportFilter 16-43

16-15 16-16

xviii

EntryValidation 16-46 ApplyCommands 16-47 Soup-Related Items 16-51 DontCreateSoups 16-51 SoupIndicies 16-51 SoupInfo 16-51 Multi-Soup Applications 16-52 Dependents 16-53 EditWith 16-54 Centralizing Denitions 16-54 AttributeFunctions 16-54 DefaultDenitions 16-55 EditTypes 16-57 Writing Meta Data Frames 16-61 NewtonScript Functions Available for Use in Meta Data 16-61 Newton Connection-Only Functions 16-65 DockerFlowParagraph 16-65 GetFolderName 16-66 GetStoresLocale 16-67 StringToParagraphArray 16-67 Data Validation Functions 16-69 Debugging Meta Data 16-77 Troubleshooting Notes 16-80 Native Format 16-81 Commands 16-82 ADD 16-83 DELETE 16-83 REPLACE 16-84 MODIFY 16-84 Warnings 16-84 The Re-Add Problem 16-84 Circular and Multiple References 16-85 Binary Objects and Parenthetical Notation 16-86 Export Considerations 16-87

xix

Native Format Syntax 16-88 Grammar 16-89 Native Format Lexical Denitions 16-90 Version 16-91 Case 16-91 Symbols 16-91 Strings 16-91 Labels 16-92 Comments 16-92 Specifying Soup Indexes in Import Files 16-92

Chapter 17

Utility Functions

17-1

Object System Functions 17-2 String Functions 17-10 Font Functions 17-25 Bitwise Functions 17-26 Array Functions 17-26 Integer Math Functions 17-34 Floating Point Math Functions 17-37 Managing the Floating Point Environment Financial Functions 17-54 Exception Functions 17-56 Message Sending Functions 17-58 Data Extraction Functions 17-62 Data Stufng Functions 17-66 Power-Related Functions 17-70 Miscellaneous Functions 17-71 Summary of Functions and Methods 17-79

17-51

xx

Appendix A

Errors

A-1

System Exceptions A-1 Newton System Errors A-2 Common Errors A-2 Application Errors A-2 Package Errors A-3 Newton Hardware Errors A-4 PCMCIA Card Errors A-4 Flash Card Errors A-5 Card Store Errors A-6 Newton Communications Errors A-7 Generic AppleTalk Errors A-7 LAP Protocol Errors A-8 DDP Protocol Errors A-8 NBP Protocol Errors A-9 AEP Protocol Errors A-9 RTMP Protocol Errors A-10 ATP Protocol Errors A-10 PAP Protocol Errors A-11 ZIP Protocol Errors A-11 ADSP Protocol Errors A-12 Communications Tool Errors A-12 Serial Tool Errors A-12 FAX Errors A-12 Modem Errors A-13 Sharp IR Errors A-13 Online Service Errors A-14 Printing Errors A-14 NewtonScript Environment Errors A-15 Store and Soup Errors A-15 Object System Errors A-16 Bad Type Errors A-16 Interpreter Errors A-17

xxi

Appendix B

The Inside Story on Declare


Compile-Time Results B-1 Run-Time Results B-2

B-1

Appendix C

Newton Signature Guidelines


Signature C-1 How to Register C-2 Application Name C-2 Application Symbol C-3 Package Name C-4 Predened Constants C-4 Soup Names C-4 System Soup Tag C-5 Additional Soup Fields C-5 Routing Formats C-6 Global Variables C-6

C-1

Chapter 18

Glossary

GL-1

Index

IN-1

xxii

Figures and Tables

Chapter 1

Overview
Figure 1-1 Figure 1-2

1-1 System software overview Using components 1-16 1-2

Chapter 2

Views

2-1 Template hierarchy 2-4 View hierarchy 2-6 Screen representation of view hierarchy View system coordinate plane 2-8 Points and pixels 2-9 Bounds Parameters 2-17 View justication effects 2-25 Transfer modes 2-35 Conrm dialog 2-67 SetOrigin example 2-84 LayoutTable Results 2-97 Built-in Keyboards 2-101 View classes 2-11 ViewFlags constants 2-14 ViewJustify constants 2-21 ViewFormat constants 2-30 ViewTransferMode constants 2-33 ViewEffect constants 2-37

Figure 2-1 Figure 2-2 Figure 2-3 Figure 2-4 Figure 2-5 Figure 2-6 Figure 2-7 Figure 2-8 Figure 2-9 Figure 2-10 Figure 2-11 Figure 2-12 Table 2-1 Table 2-2 Table 2-3 Table 2-4 Table 2-5 Table 2-6

2-7

Chapter 4

Working with View Classes


Figure 4-1 Table 4-1 Table 4-2 Table 4-3

4-1 4-27

Keyboard key codes

CopyProtection constants 4-9 Built-in font constants 4-12 Font packing constants 4-14

xxiii

Chapter 6

Written Input and Recognition


Table 6-1 Table 6-2 Table 6-3

6-1

System-supplied enumerated dictionaries 6-9 Locale-specic enumerated dictionaries 6-10 Locale-specic lexical dictionaries 6-11

Chapter 7

Data Storage and Retrieval


Figure 7-1 Table 7-1

7-1 7-22 7-23

Stores, soups and union soups

Constants representing built-in soups

Chapter 11

The Intelligent Assistant


Figure 11-1 Figure 11-2 Figure 11-3

11-1 11-3

A typical online help screen in Newton The task slip 11-5 The Please dialog box 11-6

Chapter 12

Additional System Services


Figure 12-1 Figure 12-2 Figure 12-3 Figure 12-4 Figure 12-5 Figure 12-6 Figure 12-7 Figure 12-8 Figure 12-9

12-1

The Find dialog box 12-2 Specifying text or date searches 12-2 The Find overview 12-3 Identifying strings in the Find overview 12-14 Typical progress message 12-20 The ShowFoundItem method displays an item from the overview 12-28 User interface to Filing service 12-39 Selecting a ling category in the protoFolderTab popup list 12-40 Notify alert 12-52

Chapter 13

Routing
Figure 13-1 Figure 13-2 Figure 13-3 Figure 13-4

13-1 Action button 13-2 Routing Slips 13-3 Out Box 13-4 In Box 13-4

xxiv

Chapter 14

Communications
Figure 14-1 Figure 14-2

14-1 14-38 14-39

Chapter 15

Localizing Newton Applications


Figure 15-1 Table 15-1 Table 15-2 Table 15-3 Table 15-4 Table 15-5 Table 15-6 Table 15-7 Table 15-8 Table 15-9 Table 15-10 Table 15-11

15-1 15-2

The Locale settings in Preferences

Format specications in ROM_dateTimeStrSpecs global 15-20 Using the kIncludeEverything constant 15-21 Values of format parameter 15-22 Date frame slots and values 15-26 Values of the format parameter 15-27 ROM language codes 15-29 Elements of date strings 15-34 Elements of time strings 15-35 Formats for date or time string elements 15-35 Constants dening commonly-used format specications 15-36 Using the kIncludeEverything constant 15-37

Chapter 16

Supporting Newton Connection


Figure 16-1 Figure 16-2 Figure 16-3 Figure 16-4 Figure 16-5

16-1

Application Browser 16-3 Data Browser 16-4 Detail Window 16-5 BrowserExport Makes a Text Frame 16-17 Connection Uses DisplayInfo to Display a Field 16-17 Meta data items 16-9 DisplayInfo slots 16-28 EditInfo slots 16-30 Second parameter of compare function Search Types 16-33 ExportInfo Slots 16-35

Table 16-1 Table 16-2 Table 16-3 Table 16-4 Table 16-5 Table 16-6

16-33

xxv

Table 16-7 Table 16-8 Table 16-9 Table 16-10 Table 16-11 Table 16-12 Table 16-13 Table 16-14 Table 16-15 Table 16-16 Table 16-17 Table 16-18 Table 16-19 Table 16-20

NativeExportExceptions slots 16-42 Command frame format 16-49 Meaning of having command slots present 16-50 Info array slots 16-56 Connection Built-In Types 16-57 Interpretation of date and time value of 1470 16-59 Newto n numeric operators for meta data functions 16-61 Newton global functions for meta data functions 16-62 Format for validation frames 16-70 ValidType slot values 16-71 Sample ValidTypes 16-72 FormatProto slots 16-73 Meta data validation error messages 16-78 Symbols used in syntax descriptions 16-89

Chapter 17

Utility Functions
Table 17-1 Table 17-2 Table 17-3

17-1 Instruction symbols for StringFilter Floating point exceptions 17-51 Exception frame data slot name and contents 17-57 17-21

Appendix B

The Inside Story on Declare


Figure B-1 Declare example

B-1 B-3

xxvi

P R E FA C E

About This Book


This book, Newton Programmers Guide, is the denitive guide and reference for Newton programming. This book explains how to write Newton programs and describes the system software routines that you can use to do so.

Audience
This guide is for anyone who wants to write NewtonScript programs for the Newton family of products. Before using this guide, you should read Newton Toolkit Users Guide to learn how to install and use Newton Toolkit, which is the development environment for writing NewtonScript programs for Newton. You may also want to read The NewtonScript Programming Language either before or concurrently with this book. That book describes the NewtonScript language, which is used throughout the Newton Programmers Guide. To make best use of this guide, you should already have a good understanding of object-oriented programming concepts and have had experience using a high-level programming language such as C or Pascal. It is helpful, but not necessary, to have some experience programming for a graphic user interface (like the Macintosh desktop or Windows). At the very least, you should already have extensive experience using one or more applications with a graphic user interface.

xxvii

P R E FA C E

Related Books
This book is one in a set of books included with Newton Toolkit, the Newton development environment. Youll also need to refer to these other books in the set:
n

Newton Toolkit Users Guide. This book introduces the Newton development environment and shows how to develop Newton applications using Newton Toolkit. You should read this book rst if you are a new Newton application developer. The NewtonScript Programming Language. This book describes the NewtonScript programming language. Newton Book Maker Users Guide. This book describes how to use Newton Book Maker and Newton Toolkit to make Newton digital books and to add online help to Newton applications. This book is included only if you purchased the Newton Toolkit package that includes Book Maker.

Sample Code
The Newton Toolkit product includes many sample code projects. You can examine these samples, learn from them, experiment with them, and use them as a starting point for your own applications. These sample code projects illustrate most of the topics covered in this book. They are an invaluable resource for understanding the topics discussed in this book and for making your journey into the world of Newton programming an easier one. The PIE Developer Technical Support team continually revises the existing samples and creates new sample code. You can nd the latest collection of sample code in the Newton developer area on AppleLink. You can gain access to the sample code by partici-

xxviii

P R E FA C E

pating in the PIE developer support program. For information about how to contact Apple regarding the PIE developer support program, see the section Developer Products and Support, on page xxxi.

Conventions Used in This Book


This book uses the following conventions to present various kinds of information.

Special Fonts
This book uses the following special fonts:
n

Boldface. Key terms and concepts appear in boldface on rst use. These terms are also dened in the Glossary. Courier typeface. Code listings, code snippets, and special identiers in the text such as predened system frame names, slot names, function names, method names, symbols, and constants are shown in the Courier typeface to distinguish them from regular body text. If you are programming, items that appear in Courier should be typed exactly as shown. Italic typeface . Italic typeface is used in code to indicate replaceable items, such as the names of function parameters, which you must replace with your own names. The names of other books are also shown in italic type, and rarely, this style is used for emphasis.

Tap Versus Click


Throughout the Newton software system and in this book, the word click sometimes appears as part of the name of a method or variable, as in viewClickScript or buttonClickScript. This may lead you to believe that the text refers to mouse clicks. It does not. Wherever you see the word click used this way, it

xxix

P R E FA C E

refers to a tap of the pen on the Newton screen (which is somewhat similar to the click of a mouse on a desktop computer).

Frame Code
If you are using the Newton Toolkit (NTK) development environment in conjunction with this book, you may notice that this book displays the code for a frame (such as a view) differently than NTK does. In NTK, you can see the code for only a single frame slot at a time. In this book, the code for a frame is presented all at once, so you can see all of the slots in the frame, like this: { viewClass: clView, viewBounds: RelBounds( 20, 50, 94, 142 ), viewFlags: vNoFlags, viewFormat: vfFillWhite+vfFrameBlack+vfPen(1), viewJustify: vjCenterH, viewSetupDoneScript: func() :UpdateDisplay(), UpdateDisplay: func() SetValue(display, 'text, value); }; If while working in NTK, you want to create a frame that you see in the book, follow these steps: 1. On the NTK template palette, nd the view class or proto shown in the book. Draw out a view using that template. If the frame shown in the book contains a _proto slot, use the corresponding proto from the NTK template palette. If the frame shown in the book contains a viewClass slot instead of a _proto slot, use the corresponding view class from the NTK template palette.

xxx

P R E FA C E

2. Edit the viewBounds slot to match the values shown in the book. 3. Add each of the other slots you see listed in the frame, setting their values to the values shown in the book. Slots that have values are attribute slots, and those that contain functions are method slots.

Developer Products and Support


APDA is Apples worldwide source for a large number of development tools, technical resources, training products, and information for anyone interested in developing applications on Apple platforms. Every four months, customers receive the APDA Tools Catalog featuring all current versions of Apple and the most popular third-party development tools. Ordering is easy; there are no membership fees, and application forms are not required for most of our products. APDA offers convenient payment and shipping options, including site licensing. To order product or to request a complimentary copy of the APDA Tools Catalog: APDA Apple Computer, Inc. P.O. Box 319 Buffalo, NY 14207-0319 Telephone 1-800-282-2732 (United States) 1-800-637-0029 (Canada) 716-871-6555 (International) 716-871-6511 APDA APDA 76666,2405 APDA@applelink.apple.com

Fax AppleLink America Online CompuServe Internet

xxxi

P R E FA C E

If you provide commercial products and services, call 408-974-4897 for information on the developer support programs available from Apple.

Undocumented System Software Objects


When browsing in the NTK Inspector window, you may see functions, methods, and data objects that are not documented in this book. Undocumented functions, methods, and data objects are not supported, nor are they guaranteed to work in future Newton devices. Using them may produce undesirable effects on current and future Newton devices.

xxxii

CHAPTER

Overview

This chapter describes the general architecture of the Newton system software. The Newton system software is divided into three levels, as shown in Figure 1-1. The lowest level includes the operating system and the low-level communications system. These parts of the system interact directly with the hardware and perform basic operations such as memory management, input and output, and task switching. NewtonScript applications have no direct access to system services at this low level. The middle level consists of system services which NewtonScript applications can directly access and interact with to accomplish tasks. The system provides hundreds of routines which applications can use to take advantage of these services. At the highest level are components that applications can use to construct their user interfaces. These reusable components neatly package commonly needed user interface objects such as buttons, lists, tables, input elds, and so on. These components incorporate NewtonScript code that makes use of the system services in the middle level, and which an application can override to customize an object.

1-1

CHAPTER

Overview

Figure 1-1

System software overview

1-2

CHAPTER

Overview

Operating System
The Newton platform incorporates a sophisticated preemptive, multi-tasking operating system. The operating system is a modular set of tasks performing functions such as memory management, task management, scheduling, task to task communications, input and output, power management and other low-level functions. The operating system manages and interacts directly with the hardware. A signicant part of the operating system is concerned with low-level communication functions. The communication subsystem runs as a separate task. It manages the hardware communication resources available in the system. These include serial, Fax modem, AppleTalk networking, and infrared. The communication architecture is extensible, and new communication protocols can be installed and removed at run time, to support additional services and external devices that may be added. Another separate operating system task of interest is the Inker. The Inker task is responsible for gathering and displaying input from the electronic tablet overlaying the screen when the user writes on the Newton. The Inker exists as a separate task so that the Newton can gather input and display electronic ink at the same time as other operations are occurring. All Newton applications, including the recognition system, built-in applications, and applications you write, run in a single operating system task, called the Application task. NewtonScript applications have no direct access to the operating system level of software. Access to certain low-level resources, such as communications, is provided by higher-level interfaces.

Operating System

1-3

CHAPTER

Overview

Memory
The use of random access memory (RAM) in the system is useful to understand, since this resource is shared by the operating system and all applications. Newton RAM is divided into separate domains, or sections, that have controlled access. Each domain has its own heap and stack. It is important to know about three of these domains:
n

The operating system domain. This portion of memory is reserved for use by the operating system. Only operating system tasks have access to this domain. The storage domain. This portion of memory is reserved for permanent, protected storage of user data. All soups, which store the data, reside here, as well as any packages that have been downloaded into the Newton. To protect the data in the storage domain from inadvertent damage, it can only be accessed through the object storage system interface, described in the chapter Data Storage and Retrieval. If the user adds a PCMCIA card containing RAM, Flash RAM, or read-only memory (ROM) devices, the memory on the card is used to extend the size of the storage domain. The storage domain occupies special persistent memory; that is, this memory is maintained even during a system reset. This protects user data, system software updates, and downloaded packages from being lost during system resets. The used and free space in the storage domain is reported to the user in the Memory item of the Preferences application. The application domain. This portion of memory is used for dynamic memory allocation by the recognizers and all Newton applications. A xed part of this domain is allocated to the NewtonScript heap. The NewtonScript heap is important because most objects allocated as a result of your NewtonScript application code are allocated from the NewtonScript heap. These are the only memory objects to which you have direct access. The NewtonScript heap is shared by all applications.

The system performs automatic memory management of the NewtonScript heap. You dont need to worry about memory allocation or disposal in an application. The system automatically allocates memory when you create a new object in NewtonScript. When references to an object no longer exist, it is freed during the next garbage collection cycle. The system performs garbage collection automatically when it needs additional memory.

1-4

Operating System

CHAPTER

Overview

The Newton operating system makes optimum use of memory by using compression. Various parts of memory are compressed and decompressed dynamically and transparently, as needed. This occurs at a low level, and applications dont need to be concerned with these operations.

Packages
A package is the unit in which software is installed on and removed from the Newton. Packages can combine multiple pieces of software into a single unit. The operating system manages packages, which can be installed from PCMCIA cards, from a serial connection to a desktop computer, a network connection, or via modem. When a package comes into the Newton system, the system automatically opens it and dispatches its parts to appropriate handlers in the system. A package consists of a header, which contains the package name and other information, and one or more parts, which contain the software. Parts can include applications, communication drivers, fonts, and system updates (system software code loaded into RAM that overrides or extends the built-in ROM code). Packages are optionally stored compressed on the Newton. Compressed packages occupy much less space (roughly half of their uncompressed size), but applications in compressed packages may execute somewhat slower and use slightly more battery power, because of the extra work required to uncompress them when they are executed.

System Services
The Newton system software contains hundreds of routines organized into functional groups of services. Your application can use these routines to accomplish specic tasks such as opening and closing views, storing and retrieving data, routing data through a communication link, playing sounds, drawing shapes, and so on. This section includes brief descriptions of the more important system services with which your application will need to interact. 1-5

System Services

CHAPTER

Overview

Object Storage System


This section is rst because it is key to the Newton information architecture. The object storage system provides persistent storage for data. Newton uses a unied data model. This means that all data stored by all applications uses a common format. Data can easily be shared among different applications, with no translation necessary. This allows seamless integration of applications with each other and with system services. Data is stored using a database-like model. Objects are stored as frames, which are like database records. A frame contains named slots, which hold individual pieces of data, like database elds. For example, an address card in the Names application is stored as a frame that contains a slot for each item on the card: name, address, city, state, zip code, phone number, and so on. Frames are exible and can represent a wide variety of structures. Slots in a single frame can contain any kind of NewtonScript object, including other frames, and slots can be added or removed from frames dynamically. For a description of NewtonScript objects, refer to The NewtonScript Programming Language. Groups of related frames are stored in soups , which are like databases. For example, all the address cards used by the Names application are stored in the Names soup, and all the notes on the Notepad are stored in the Notes soup. All the frames stored in a soup need not contain identical slots. For example, some frames representing address cards may contain a phone number slot and others may not. Soups are automatically indexed, and applications can create additional indexes on slots that will be used as keys to nd data items. You retrieve items from a soup by performing a query on the soup. Queries can be based on an index value or can search for a string, and can include additional constraints. A query results in a cursoran object representing a position in the set of soup entries that satisfy the query. The cursor can be moved back and forth, and can return the current entry.

1-6

System Services

CHAPTER

Overview

Soups are stored in physical repositories, called stores. Stores are akin to disk volumes on personal computers. The Newton always has at least one store the internal store. Additional stores reside on PCMCIA cards. The object storage system interface seamlessly merges soups that have the same name on internal and external stores in a union soup. This is a virtual soup that provides an interface similar to a real soup. For example, some of the address cards on a Newton may be stored in the internal Names soup and some may be stored in another Names soup on a PCMCIA card. When the card is installed, those names in the card soup are automatically merged with the existing internal names so the user, or an application, need not do any extra work to access those additional names. When the card is removed, the names simply disappear from the card le union soup. The object storage system is optimized for small chunks of data and is designed to operate in tight memory constraints. Soups are compressed, and retrieved entries are not allocated on the NewtonScript heap until a slot in the entry is accessed. You can nd information about the object storage system interface in the chapter Data Storage and Retrieval.

View System
Views are the basic building blocks of most applications. A view is simply a rectangular area mapped onto the screen. Nearly every individual visual item you see on the screen is a view. Views display information to the user in the form of text and graphics, and the user interacts with views by tapping on them, writing in them, dragging them, and so on. A view is dened by a frame that contains slots specifying view attributes such as its bounds, ll color, alignment relative to other views, and so on. The view system comprises that part of the system that you work with to manipulate views. There are routines to open, close, animate, scroll, highlight, and lay out views, to name just a few of the kinds of things you can do. Refer to the chapter Views for basic information about views and descriptions of all the routines you can use to interact with the view system.

System Services

1-7

CHAPTER

Overview

An application consists of a collection of views all working together. Each application has an application base view from which all other views comprising that application descend hierarchically. In turn, the base view of each application installed in the Newton descends from the system root view. (Think of the hierarchy as a tree structure turned upside down, with the root at the top.) Thus, each application base view is a child of the root view. We call a view in which child views exist the parent view of those child views. The system includes several different primitive view classes from which all views are ultimately constructed. Each of these view classes has inherently different behavior and attributes. For example, there are view classes for views that contain text, shapes, pictures, keyboards, analog gauges, and so on. You can learn more about the primitive view classes in the chapter Working with View Classes. As an application executes, its view frames receive messages from the system and exchange messages with each other. System messages provide an opportunity for a view to respond appropriately to particular events that are occurring. For example, the view system performs default initialization operations when a view is opened. It also sends the view a viewSetupFormScript message. If the view includes a method to handle this message, it can perform its own initialization operations in that method. Handling system messages in your application is optional since the system performs default behaviors for most events. The chapter Handling System Messages describes messages that views can receive from the system and explains what your application needs to do to handle them.

Recognition
The Newton recognition system uses a sophisticated multiple-recognizer architecture. There are recognizers for text, shapes, and gestures, which are normally simultaneously active. An arbitrator examines the results of the recognizers and returns the recognition match that has the highest condence. The user can temporarily turn off text and/or shape recognition to limit the possible results.

1-8

System Services

CHAPTER

Overview

Recognition is modeless. That is, the user does not need to put the system in a special mode or use a special dialog box in order to write. The user can write in any input eld at any time. The text recognizers can handle printed, cursive, or mixed handwriting. They normally work together with built-in dictionaries to choose words that accurately match what the user has written. Again, this is user-congurable, so the user can choose to temporarily disable the dictionaries so text is recognized letter-by-letter. The user can also add words to the dictionary. The shape recognizer recognizes both simple and complex geometric objects, cleaning up rough drawings into shapes with straight lines and smooth curves. The shape recognizer also recognizes symmetry, using that property , if present, to help it recognize and display objects. For each view in an application, you can specify which recognizers are enabled and how they are congured. For example, the text recognizer can be set to recognize only names, or names and phone numbers, or only words in a custom dictionary that you supply, among other choices. Most recognition events are handled automatically by the system view classes so you dont need to do anything in your application to handle recognition events, unless you want to do something special. For example, when a user writes a word in a text view, that view automatically passes the strokes to the recognizer, accepts the recognized word back, and displays the word. In addition, the view automatically handles correction for you. The user can double-tap on a word to pop-up a list of other possible matches for it, or to use the keyboard to correct it. Refer to the chapter Written Input and Recognition for information on controlling recognition in views, working with dictionaries, and other written input-related topics.

Intelligent Assistant
A key part of the Newton information architecture is the Intelligent Assistant. The Intelligent Assistant is a system service that attempts to complete actions for the user according to deductions it makes about the task that the user is currently performing. The Assistant is always instantly available to the user through the Assist button, yet remains non-intrusive.

System Services

1-9

CHAPTER

Overview

The Assistant knows how to complete several built-in tasks; they are Scheduling (adding meetings), Finding, Reminding (adding Todo items), Mailing, Faxing, Printing, Calling, and getting time information from the Time Zones map. Each of these tasks has several synonyms; for example, the user can write call, phone, ring, or dial to make a phone call. Applications can add new tasks so that the Assistant supports their special capabilities and services. The Newton unied data model makes it possible for the Assistant to access data stored by any application, thus allowing the Assistant to be well-integrated in the system. For details on using the Intelligent Assistant and integrating support for it into your application, see the chapter The Intelligent Assistant.

Communications
The Newton provides a number of built-in communication services. They include:
n n n

Synchronous and asynchronous serial connection Fax/data modem connection (MNP/V.42 and Class 1T30/T4) Point-to-point infrared communicationcalled beaming (Sharp 9600 and Apple IR enhanced protocols) AppleTalk ADSP protocol

The basis of the communications architecture is the endpoint object. An endpoint object provides the interface between the user and an underlying transport service. Endpoints are represented by frames. A single prototype endpoint provides a standard interface to all communication servicesserial, modem, beaming, and AppleTalk protocols, as well as third-party communication products. The endpoint object provides methods for:
n n n n

communicating with the underlying transport service setting options opening and closing connections sending and receiving data

1-10

System Services

CHAPTER

Overview

The endpoint encapsulates and maintains the details of the specic connection at hand, how to handle input, and so on. It includes methods that are executed in response to particular events, such as when input is available. For details on how to use the Newton communications facilities, refer to the chapter Communications.

Imaging and Printing


At the operating system level, the Newton imaging and printing software is based on an object-oriented, device-independent imaging model. The imaging model uses black-and-white since the Newton screen is a blackand-white screen. NewtonScript application programs dont call low-level imaging routines directly to do drawing or image manipulation. In fact, most drawing is handled for applications by the user interface components they incorporate, or when they call other routines that display information. However, there is a versatile set of high-level drawing routines that you can call directly to create and draw shapes, pictures, bitmaps, and text. When drawing, you can vary the pen thickness, pen pattern, ll pattern, and other attributes. For details on drawing, refer to the chapter Drawing. The Newton text imaging facility supports Unicode directly, so the system can be easily localized to display languages using different script systems. The system is extensible, so its easy to add additional fonts, font engines, and printer drivers. The high-level interface to printing on the Newton uses a model identical to that used for views. Essentially, you design a special kind of view called a print format to specify how printed information is to be laid out on the page. Print formats use a unique view template that automatically adjusts its size to the page size of the printer chosen by the user. When the user prints, the system handles all the details of rendering the views on the printer according to the layout you specied. The Newton offers the feature of deferred printing. The user can print even though he or she is not connected to a printer at the moment. An object

System Services

1-11

CHAPTER

Overview

describing the print job is stored in the Newton Outbox, and when a printer is connected later, the user can then select that print job for printing. Again, this feature is handled automatically by the system and requires no additional application programming work. For information on how to add printing capabilities to an application, refer to the chapter Routing.

Sound
The Newton includes a monophonic speaker and can play sounds sampled at rates up to 22 KHz. You can attach sounds to particular events associated with a view, such as showing it, hiding it, and scrolling it. You can also use sound routines to play sounds synchronously or asynchronously at any other time. Newton can serve as a phone dialer by dialing phone numbers through the speaker. The dialing tones are built into the system ROM, along with several other sounds that can be used in applications. Besides the sounds that are built into the system ROM, you can import external sound resources into an application through the Newton ToolKit development environment. For information about using sound in an application, see the chapter Working With Sound.

Book Reader
Book Reader is a system service that displays interactive digital books on the Newton screen. Digital books can include multiple-font text, bitmap and vector graphics, and on-screen controls for content navigation. Newton digital books allow the user to scroll pages, mark pages with bookmarks, access data directly by page number or subject, mark up pages using digital ink, and perform text searches. Of course, the user can copy and paste text from digital books, as well as print text and graphics from them.

1-12

System Services

CHAPTER

Overview

Newton Book Maker is a development tool that you use to create digital books for the Newton. Non-programmers can create source les for digital books using an ordinary word processor application; Book Maker accepts many popular word-processor les as source les. The text-based Book Maker command language allows you to provide additional services to the user or exercise greater control over page layout with minimal additional effort. Also, you can attach data, methods and templates to book content to provide customized behavior or work with the Intelligent Assistant. The Book Maker application can also be used to create on-line help for an application. The installation of on-line help in an application package requires some rudimentary NewtonScript programming ability; however, non-programmers can create on-line help content, again using only a word processor and some basic Book Maker commands. Refer to the book Newton Book Maker Users Guide for information on Book Reader, the Book Maker command language, and the use of the Newton ToolKit to create digital book packages and on-line help.

Other Services
Other Newton system services that applications can take advantage of include nd, ling, and routing.

Find
Find is a system service that allows users to search one or all applications in the system for occurrences of a particular string. Alternatively, the user can search for data time-stamped before or after a specied date. When the search is completed, the nd service displays an overview list of items found that match the search criteria. The user can tap on an item in the list and the system opens the corresponding application and displays the data containing the selected string. Users access the nd service by tapping the Find button. If you want to allow the user to search for data stored by your application, then you need to implement certain methods that respond to nd messages

System Services

1-13

CHAPTER

Overview

sent by the system. Youll need to supply one method that searches your applications soup(s) for data and returns the results in a particular format, and another method that locates and displays the found data in your application if the user taps on it in the nd overview. The system software includes routines and templates that help you support nd in your application. For details on supporting the nd service, refer to the chapter Additional System Services.

Filing
The ling service allows users to tag soup-based data in your application with labels used to store, retrieve and display the data by category. The labels used to tag entries are represented as folders in the user interface; however, no true hierarchical ling existsthe tagged entries still reside in the soup. Users access the ling service through a standard user interface element called the le folder button, which looks like a small le folder. When the user chooses a category for an item, the system noties your application that ling has changed. Your application must perform the appropriate application-specic tasks and redraw the current view, providing to the user the illusion that the item has been placed in a folder. When the user chooses to display data from a category other than the currently-displayed one, the system also noties your application, which must retrieve and display data in the selected category. The system software includes templates that help your application implement the ling button and the selector that allows the user to choose which category of data to display. Your application must provide methods that respond to ling messages sent by the system in response to user actions such as ling an item, changing the category of items to display, and changing the list of ling categories. For details on supporting the ling service, refer to the chapter Additional System Services.

Routing
The routing services allow users to send data somewhere. These services include printing, faxing, mailing, beaming, duplicating, deleting, and moving data between internal and card stores. Users access the routing

1-14

System Services

CHAPTER

Overview

services through a standard user interface element called the action button, which looks like a small envelope. Additionally, some routing services use the system Outbox to store and forward outgoing data. The Outbox and Inbox provide a common user interface for all outgoing and incoming data in the system. You may want to provide some or all of these standard routing capabilities in your application, or even add additional options that take advantage of special communication capabilities provided by your application. For details on supporting the built-in routing services and adding your own routing service, refer to the chapter Routing.

Application Components
At the highest level of system software are dozens of components that applications can use to construct their user interfaces. These reusable components neatly package commonly needed user interface objects such as buttons, lists, tables, input elds, and so on. These components incorporate NewtonScript code that makes use of other system services, and which an application can override to customize an object. These components are built into the Newton ROM. When you reference one of these components in your application, the code isnt copied into your applicationyour application simply makes a reference to the component in the ROM. This conserves memory at run time and still allows your application to easily override any attributes of the built-in component. Because you can build much of your application using these components, Newton applications tend to be much smaller in size than similar applications on desktop computers. A simple example of how you can construct much of an application using components is illustrated in Figure 1-2. This simple application accepts names and phone numbers and saves them into a soup. It was constructed in just a few minutes using three different components.

Application Components

1-15

CHAPTER

Overview

The application base view is implemented by a single component that includes the title bar at the top, the status bar at the bottom, the clock and the close box, and the outer frame of the application. The Name and Phone input lines are each created from the same component that implements a simple text input line. And the two buttons are created from the same button component. The only code you must write to make this application fully functional is to make the buttons perform their actions. That is, make the Clear button clear the input lines and make the Save button get the text from the input lines and save it to a soup.

Figure 1-2

Using components

The components available for use by applications are shown on the layout palette in Newton ToolKit. These components are known as protos. In addition to the built-in components, Newton ToolKit gives you the ability to create your own reusable components, called user protos. For information on all of the built-in components, refer to the chapter Working With Proto Templates.

1-16

Application Components

CHAPTER

Overview

Using System Software


Most of the routines and application components that comprise the Newton system software reside in ROM, provided in special chips contained in every Newton device. When your application calls a system routine, the operating system executes the appropriate code contained in ROM. This is different from traditional programming environments where system software routines are accessed by linking a subroutine library with the application code. That approach results in much larger applications and makes it harder to provide new features and x bugs in the system software. The ROM-based model used in the Newton provides a simple way for the operating system to substitute the code that is executed in response to a particular system software routine, or to substitute an application component. Instead of executing the ROM-based code for some routine, the operating system might choose to load some substitute code into RAM; then when your application calls the routine, the operating system intercepts the call and executes the RAM-based code. RAM-based code that substitutes for ROM-based code is called a system update. Newton system updates are stored in the storage memory domain, which is persistent storage. Besides application components, the Newton ROM contains many other objects such as fonts, sounds, pictures, and strings that might be useful to applications. Applications can access these objects by using special references called magic pointers. Magic pointers provide a mechanism for code written in a development system separate from the Newton to reference objects in the Newton ROM. Magic pointer references are resolved at run time by the operating system, which substitutes the actual address of the ROM object for the magic pointer reference. Magic pointers are constants dened by Newton ToolKit. For example, the names of all the application components, or protos, are actually magic pointer constants. You can nd a list of all the magic pointer constants in the NTK Denitions le, included with the Newton ToolKit.

Using System Software

1-17

CHAPTER

Overview

The NewtonScript Language


You write Newton applications in NewtonScript, a dynamic object-oriented language developed especially for the Newton platform, though the language is highly portable.NewtonScript is designed to operate within tight memory constraints, so is well suited to small hand-held devices like Newton. NewtonScript is used to dene, access, and manipulate objects in the Newton system. NewtonScript frame objects provide the basis for object-oriented features such as inheritance and message sending. The Newton ToolKit compiles NewtonScript into byte codes. The Newton system software contains a byte code interpreter that interprets the byte codes at run time. This has two advantages: byte codes are much smaller than native code, and Newton applications are easily portable to other processors, since the interpreter is portable. For a complete reference to NewtonScript, refer to The NewtonScript Programming Language.

1-18

The NewtonScript Language

CHAPTER

Views

Views are the basic building blocks of most applications. Nearly every individual visual item you see on the screen is a view, and there may even be views that are not visible. Views display information to the user in the form of text and graphics, and the user interacts with views by tapping on them, writing in them, dragging them, and so on. Different types of views have inherently different behavior, and you can include your own methods in views to further enhance their behavior. The primitive view classes provided in the Newton system are described in detail in the chapter Working with View Classes. This chapter describes the basic information you need to know about views and how to work with them in your application.

2-1

CHAPTER

Views

Templates and Views


This section discusses templates and views, and how views are derived from templates.

Templates
A template is a frame containing a description of an object. (In this chapter the objects we are talking about are views that can appear on the screen.) Templates contain data descriptions of such things as elds for the user to write into, graphic objects, buttons, and other interactive objects used to collect and display information. Additionally, templates can include methods, which are functions that give the view behavior.
Note

A template can also describe non-graphical objects like communication objects. Such objects have no visual representation and exist only as logical objects. For more information about communication objects, refer to the chapter Communications. u An application exists as a collection of templates, not just a single template. There is a parent template that denes the application window and its most basic features. From this parent template springs a hierarchical collection of child templates, each dening a small piece of the larger whole. Each graphical object, button, text eld, and so on is dened by a separate template. Each child template exists within the context of its parent template and inherits characteristics from its parent template, though it can override these inherited characteristics. Within the Newton object system, a template for a view exists as a special kind of frame; that is, a frame containing or inheriting a particular group of slots (viewClass, viewBounds, viewFlags, and some other optional slots) that dene the template's class, dimensions, appearance, and other

2-2

Templates and Views

CHAPTER

Views

characteristics. Templates are no different from any other frames, except that they contain or inherit these particular slots (in addition to others). For more information about frames, slots, and the NewtonScript language, refer to The NewtonScript Programming Language . Figure 2-1 on page 2-4 shows a collection of template frames that might make up an application. The frame at the top represents the highest level parent template. Each template that has children contains a viewChildren (or stepChildren) slot whose value is an array of references to its child templates.

Views
A template is a data description of an object. A view is the visual representation of that object that is created when the template is instantiated. The system reads the stored description in the template and creates a view on the screenfor example, a framed rectangle containing a title. Besides the graphical representation you see on the screen, a view consists of a memory object (a frame) that contains a reference to its template and also contains transient data used to create the graphical object. Any changes to view data that occur during run time are stored in the view, not in its template. This is an important pointafter an application has started up (that is, once the views are instantiated from their templates), all changes to slots occur in the view; the template is never changed. This distinction between templates and views with respect to changing slot values occurs because of the NewtonScript inheritance mechanism. During run time, templates, containing static data, are prototypes for views, which contain dynamic data. To understand this concept, it is imperative that you have a thorough understanding of the inheritance mechanism as described in The NewtonScript Programming Language. You can think of a template like a computer program stored on a disk. When the program starts up, the disk copy (the template) serves as a template; it is copied into dynamic memory where it begins execution. Any changes to program variables and data occur in the copy of the program in memory (the view), not in the original disk version.

Templates and Views

2-3

CHAPTER

Views

Figure 2-1

Template hierarchy

2-4

Templates and Views

CHAPTER

Views

However, the Newton system diverges from this metaphor in that the view is not actually a copy of the template. To save RAM use, the view contains only a reference to the template. Operations involving the reading of data are directed by reference to the template if the data is not rst found in the view. In operations in which data is written or changed, the data is written into the view. Because views are transient, any data written into them that needs to be saved permanently must be saved before the view disappears, since data is disposed of when the view is closed. A view is linked with its template through a _proto slot in the view. The value of this slot is a reference to the template. Through this reference, the view can access slots in its template. Templates may themselves contain _proto slots which reference other templates, called protos, on which they are built. Views are also linked to other views in a parent-child relationship. Each view contains a _parent slot whose value is a reference to its parent view; that is, the view that encloses it. The top level parent view of your application is called the application base view. (Think of the view hierarchy as a tree structure where the tree is turned upside down with its root at the top. The top level parent view is the root view.) Figure 2-2 on page 2-6 shows the set of views that have been instantiated from the templates shown in Figure 2-1. Note that this example is simplied in that it shows a separate template for each view. In practice, often multiple views share a single template. Also, this example doesn't show templates that are built on other protos.

Templates and Views

2-5

CHAPTER

Views

Figure 2-2

View hierarchy

2-6

Templates and Views

CHAPTER

Views

Figure 2-3 shows an example of what this view hierarchy might represent on the screen.

Figure 2-3
Parent View

Screen representation of view hierarchy

Child B Child C Child D

Child A

The application base view of each application exists as a child of the system root view. The root view is essentially the blank screen that exists before any other views are drawn. It is the ancestor of all other views that are instantiated.

Coordinate System
The view coordinate system is a two-dimensional plane. The (0, 0) origin point of the plane is assigned to the upper-left corner of the Newton screen, and coordinate values increase to the right and (unlike a Cartesian plane) down. Any pixel on the screen can be specied by a vertical coordinate and a horizontal coordinate. Figure 2-4 on page 2-8 illustrates the view system coordinate plane.

Coordinate System

2-7

CHAPTER

Views

Figure 2-4

View system coordinate plane

Views are dened by rectangular areas that are usually subsets of the screen. The origin of a view is usually its upper-left corner, though the origin of a view can be changed. The coordinates of a view are relative to the origin of its parent viewthey are not screen coordinates. It is helpful to conceptualize the coordinate plane as a two-dimensional grid. The intersection of a horizontal and vertical grid line marks a point on the coordinate plane. Note the distinction between points on the coordinate grid and pixels, the dots that make up a visible image on the screen. Figure 2-5 illustrates the relationship between the two: the pixel is down and to the right of the point by which it is addressed. As the grid lines are innitely thin, so a point is innitely small. Pixels, by contrast, lie between the lines of the coordinate grid, not at their intersections.

2-8

Coordinate System

CHAPTER

Views

Figure 2-5

Points and pixels

This gives them a denite physical extent, so that they can be seen on the screen.

Dening View Characteristics


A template that describes a view is stored as a frame that has slots for view characteristics. Here is a NewtonScript example of a template that describes a view: {viewClass: clView, viewBounds: RelBounds( 20, 50, 94, 142 ), viewFlags: vNoFlags, viewFormat:vfFillWhite+vfFrameBlack+vfPen(1), viewJustify: vjCenterH, viewFont: simpleFont10,

Dening View Characteristics

2-9

CHAPTER

Views

declareSelf: 'base, debug: "dialer", viewSetupDoneScript: func() :UpdateDisplay(), UpdateDisplay: func() SetValue(display, 'text, value), }; Briey, the syntax for dening a frame is: {slotName: slotValue , slotName: slotValue , ...}; where slotName is the name of a slot, and slotValue is the value of a slot. For more details on NewtonScript syntax, refer to The NewtonScript Programming Language. Frames serving as view templates have slots that dene the following kinds of view characteristics: Class The viewClass slot denes the class of graphical object from which the view is constructed. Behavior The viewFlags slot denes other primary view behaviors and controls recognition behavior. Location, size, and alignment The viewBounds and viewJustify slots dene the location, size, and alignment of the view and its contents. Appearance The viewFormat slot denes the frame and ll characteristics. The viewFillPattern and viewFramePattern slots control custom patterns. Transfer modes used in drawing the view are controlled by the viewTransferMode slot.

2-10

Dening View Characteristics

CHAPTER

Views

Animation Other attributes Inheritance links

The viewEffect slot denes an animation to be performed when the view is displayed or hidden. Some other slots dene view characteristics such as font, copy protection, and so on. The _proto, _parent, viewChildren, and stepChildren slots contain links to a views template, parent view, and child views.

These different categories of view characteristics are described in the following sections.

Class
The viewClass slot denes the view class. This information is used by the system when creating a view from its template. The view class describes the type of graphical object to be used to display the data described in the template. The view classes built into the system serve as the primitive building blocks from which all visible objects are constructed. The view classes are listed and described in Table 2-1.

Table 2-1 Constant

View classes Value Description

clView

74

The base view class. This class is used for a generic view that has no special characteristics. A view of this class is generally a container view that encloses other more specialized views. Such a higher-level view would include global data and methods shared by its child views. Used for pictures.
continued

clPictureView

76

Dening View Characteristics

2-11

CHAPTER

Views

Table 2-1 Constant

View classes (continued) Value Description

clEditView

77

Used for editing views that can accept both text and graphic user input. This view class typically has child views that are of class clParagraphView and clPolygonView. A static text view or a paragraph of text used in an edit view. When text is recognized, it is displayed in one of these views. Text is grouped into paragraphs so that many words can be shown in a single paragraph view. A graphic view used in an edit view. When a shape is recognized, it is displayed in one of these graphic views. Used to dene keyboard-like arrays of buttons that can be tapped. No other forms of input recognition are available. Used to dene a calendar view of a month that lets the user select a date range. Used for a view that displays another view as its contents. This can be used to show a page preview of a full-page view, for example. This view provides the scaling necessary to display the entire remote view. Used to display a list from which you can pick an item. The list can display both text and graphic items. This view class is supported through the protoPicker view proto.
continued

clParagraphView

81

clPolygonView

82

clKeyboardView

79

clMonthView

80

clRemoteView

88

clPickView

91

2-12

Dening View Characteristics

CHAPTER

Views

Table 2-1 Constant

View classes (continued) Value Description

clGaugeView

92

Used to dene a gauge-like view that can display a visual sliding bar indicator. The view can be read-only or changeable. With a changeable view, the user can drag the indicator to a new position. Used for a text outline with expandable headings that have indented subheadings. The user can tap headings to expand and collapse them and to choose items.

clOutline

105

For more detailed information about using each of these view classes in templates, see the chapter Working with View Classes

Behavior
The viewFlags slot denes behavioral attributes of a view other than those that derive from the view class. Each attribute is represented by a constant dened as a bit ag. Multiple attributes are specied by adding them together, like this: vVisible+vFramed Some of the viewFlags constants are listed and described in Table 2-2 on page 2-14. There are also several additional constants you can specify in the viewFlags slot that control what kinds of pen input (taps, strokes, words, letters, numbers, and so on) are recognized and handled by the view. These other constants are described in the chapter Written Input and Recognition. View behavior is also controlled through methods in the view that handle system messages. As an application executes, its views receive messages from the system, triggered by various events, usually the result of a user action. Views can handle system messages by having methods that are named after the messages. You control the behavior of views by providing such methods and including code that operates on the receiving view or other views.

Dening View Characteristics

2-13

CHAPTER

Views

Table 2-2 Constant

ViewFlags constants Value Description

vVisible

The view is visible. Usually used, except for invisible views. (Dont set this ag for your application base view, because you dont want it to be shown until the user taps its icon in the Extras Drawer.) If you Show, Hide, or Toggle a view, this ag is changed in the view by the system to reect the current state of the view. Identies a view that should receive scrolling and other high-level events. For example, when the user taps on the scroll arrows, the system searches all of the views to nd the frontmost view that has this bit set, and then sends the scroll event to that view. Generally, this ag is set for the application base view. Views with this ag set can be found with the special view symbols 'viewFrontMost or 'viewFrontMostApp. The view bounds are not xed, but are recalculated and will grow if the user enters more information than the view can hold. Used by views of the class clParagraphView and clPolygonView only, and only when they are enclosed in a view of the class clEditView. The view's contents, including child views, are clipped to its bounds when it is drawn. Note that the base view of all applications is automatically clipped, whether or not this ag is set. The view is a oating view; that is, it oats above its sibling views. A view without this ag will never come in front of a oating sibling view. The view cannot be changed, except that it can be scaled or distorted. It is read-only.
continued

vApplication

vCalculateBounds

vClipping

32

vFloating

64

vReadOnly

2-14

Dening View Characteristics

CHAPTER

Views

Table 2-2 Constant

ViewFlags constants (continued) Value Description

vWriteProtected

128

The same as vReadOnly, except that this ag propagates automatically to all of the views child views. Additionally, scaling and distortion of the view are not allowed. Prevents the system from sending to the view any of the system messages described in the chapter Handling System Messages (except for the viewChangedScript message, which is still sent). Setting this ag speeds up the processing for a view if it has no system message handling methods dened, because the system wont bother trying to send it messages. This ag is set internally for views of the classes clParagraphView and clPolygonView that are created dynamically as the user writes in a clEditView. Allows the view to receive pen input. The system sends the viewClickScript message to the view once for each pen tap (click) that occurs within the view. Refer to the chapter Written Input and Recognition for more information. There are no ag attributes for the view.

vNoScripts

134217728

vClickable

512

vNoFlags

For a detailed description of the system messages that views can receive, and information on how to handle them, see the chapter Handling System Messages.

Handling Pen Input


The use of the vClickable viewFlags constant to control pen input is important to understand, so it is worth covering here, even though it is discussed in more detail in the chapter Written Input and Recognition. The vClickable ag must be set for a view to receive input. If this ag is not set for a view, that view cannot accept any pen input.

Dening View Characteristics

2-15

CHAPTER

Views

If you have a view whose vClickable ag is not set, pen events, such as a tap, will fall through that view and be registered in a background view that does accept pen input. This can cause unexpected results if you are not careful. You can prevent pen events from registering in the wrong view by setting the vClickable ag for a view and providing a viewClickScript method in the view that returns true. This causes the view to capture all pen input within itself, instead of letting it fall through to a different view. If you want to capture pen events in a view but still prevent input ( and electronic ink), simply do not specify any other recognition ags besides vClickable. Several other viewFlags constants are used to control and constrain the recognition of text, the recognition of shapes, the use of dictionaries, and other input-related features of views. For more information, refer to the chapter Written Input and Recognition.

Location, Size, and Alignment


The location and size of a view are specied in the viewBounds slot of the view template. The viewJustify slot affects the location of a view relative to other views. The viewJustify slot also controls how text and shapes within the view are aligned. and limits how much text can appear in the view (one line, one word, and so on). The viewOriginX and viewOriginY slots control the offset of child views within a view.

viewBounds Slot
The viewBounds slot denes the size and location of the view on the screen. The value of the viewBounds slot is a frame that contains four slots giving the view coordinates (all distances are in pixels). For example: {left: leftValue , top: topValue , right: rightValue, bottom: bottomValue }

2-16

Dening View Characteristics

CHAPTER

Views

leftValue topValue rightValue bottomValue

The distance from the left origin of the parent view to the left edge of the view. The distance from the top origin of the parent view to the top edge of the view. The distance from the left origin of the parent view to the right edge of the view. The distance from the top origin of the parent view to the bottom edge of the view.

Note

The values in the viewBounds frame are interpreted as described here only if the view justication is set to the default values. Otherwise, the view justication setting changes how the viewBounds values are used. For more information, see the section viewJustify Slot beginning on page 2-20. u Note that all coordinates are relative to a views parent, they are not actual screen coordinates, as shown in Figure 2-6.

Figure 2-6

Bounds Parameters

Dening View Characteristics

2-17

CHAPTER

Views

When you are using the Newton ToolKit to lay out views for your application, the viewBounds slot is set automatically when you drag out a view in the layout window. If you are writing code in which you need to specify a viewBounds slot, you can use one of the global functions such as SetBounds or RelBounds, which are described later in this chapter in the section Finding the Bounds of Views beginning on page 2-70.

View Size Relative to Parent Size


A view is normally entirely enclosed by its parent view. We dont recommend creating a view whose bounds extend outside its parents bounds. If you do create such a view, for example containing a picture that you want to show just part of, you should also set the vClipping ag in the viewFlags slot of the parent view. If you do not set the vClipping ag for the parent view, the behavior is unpredictable. The portions of the view outside the parents bounds may or may not draw properly. All pen input is clipped to the parents bounds. Note that the base views of all applications (all root view children, in fact) are automatically clipped, whether or not the vClipping ag is set. If your application base view is very small and you need to create a larger oating child view, for example a dialog box, you should use the BuildContext function, described on page 2-62. This function creates a special view that is a child of the root view. To open the view, you send the Open message to it.

Using Screen-Relative Bounds


Newton is a family of products with varying screen sizes. If you want your application to be compatible with a variety of individual Newton products, you should design your application so that it sizes itself dynamically, accounting for the size of the screen on which it is running, which could be smaller or larger than the original Newton MessagePad screen. You may want to dynamically size the base view of your application so that it changes for different screen sizes, or you may want it to remain a xed size

2-18

Dening View Characteristics

CHAPTER

Views

on all platforms. In the later case, you should still check the actual screen size at run time to make sure there is enough room for your application. You can use the global function GetAppParams to check the size of the screen at run time. This function returns a frame containing the coordinates of the drawable area of the screen, as well as other information (see the chapter Utility Functions for a description). The frame returned looks like this: {appAreaLeft: 0, appAreaTop: 0, appAreaWidth: 240, appAreaHeight: 336, ...} The following example shows how to use the viewSetupFormScript method in your application base view to make the application a xed size, but no larger than the size of the screen. viewSetupFormScript: func() begin local b := GetAppParams(); self.viewbounds := RelBounds( b.appAreaLeft, b.appAreaTop, min(200, b.appAreaWidth), // 200 pixels wide max min(300, b.appAreaHeight)); // 300 pixels high max end We dont recommend that you size your application to the full extents of the screen. This might look odd if your application was run on a system with a much larger screen. We do recommend that you include a border around your application base view. That way, if it runs on a screen that is larger than the size of your application, the user will be able to clearly see its boundaries.

Dening View Characteristics

2-19

CHAPTER

Views

The important thing is to correctly size the application base view. Child views are positioned relative to the application base view. If you have a dynamically sizing application base view, make sure that the child views also are sized dynamically, so that they are laid out correctly no matter how the dimensions of the base view change. You can ensure this by using parentrelative and sibling-relative view justication, as explained in the next section, viewJustify Slot. One additional consideration you should note is that on a larger screen, it may be possible for the user to move applications around. You should not rely on the top-left coordinate of your application base view being xed. If you work with global coordinates in your application, make sure to check its current location. To do this, send the GlobalBox message to your application base view.

viewJustify Slot
The viewJustify slot is used to set the view alignment and is closely linked in its usage and its effects with the viewBounds slot. The viewJustify slot species how text and graphics are aligned within the view and how the bounds of the view are aligned relative to its parent or sibling views. (Sibling views are child views that have a common parent view.) In the viewJustify slot, you can specify one or more justication attributes, which are represented by constants dened as bit ags. You can specify one justication attribute from each of the following groups:
n

Horizontal alignment of view contents (applies to views of class clParagraphView and clPictureView only) Vertical alignment of view contents (applies to views of class clParagraphView and clPictureView only) Horizontal alignment of the view relative to its parent or sibling view Vertical alignment of the view relative to its parent or sibling view Text limits

n n n

2-20

Dening View Characteristics

CHAPTER

Views

For example, you could specify these justication attributes for a button view that has its text centered within the view and that is placed relative to its parent and sibling views: vjCenterH+vjCenterV+vjSiblingRightH+vjParentBottomV+ oneLineOnly If you dont specify an attribute from a group, the default attribute for that group is used. The view justication attributes and the defaults are listed and described in Table 2-3. The effects of these attributes are illustrated in Figure 2-7, following the table.
Note

You can apply both parent-relative and sibling-relative justication attributes for a view. When calculating the location of the view, the system rst applies parent-relative justication, and then applies sibling-relative justication to the result. However, do not set both parent-relative and sibling-relative full justicationthe results are unpredictable. u

Table 2-3 Constant

ViewJustify constants Value Description

Horizontal alignment of view contents

vjLeftH vjCenterH vjRightH vjFullH

0 2 1 3

Left alignment (default) Center alignment Right alignment Stretches the view contents to ll the entire view width
continued

Dening View Characteristics

2-21

CHAPTER

Views

Table 2-3 Constant

ViewJustify constants (continued) Value Description

Vertical alignment of view contents

vjTopV vjCenterV vjBottomV vjFullV

0 4 8 12

Top alignment (default) Center alignment Bottom alignment For views of the clPictureView class only; stretches the picture to ll the entire view height

Horizontal alignment of the view relative to its parent or sibling view 1

vjParentLeftH vjParentCenterH

0 16

The left and right view bounds are relative to the parent's left side (default) The difference between the left and right view bounds is used as the width of the view. If you specify zero for left, the view is centered in the parent view. If you specify any other number for left, the view is offset by that much from a centered position (for example, specifying left = 10 and right = width+10 offsets the view 10 pixels to the right from a centered position). The left and right view bounds are relative to the parent's right side, and will usually be negative. The left bounds value is used as an offset from the left edge of the parent and the right bounds value is used as an offset from the right edge of the parent (for example, specifying left = 10 and right = 10 leaves a 10-pixel margin on each side). Do not use sibling horizontal justication (default) The left and right view bounds are relative to the sibling's left side
continued

vjParentRightH vjParentFullH

32 48

vjSiblingNoH vjSiblingLeftH

0 2048

2-22

Dening View Characteristics

CHAPTER

Views

Table 2-3 Constant

ViewJustify constants (continued) Value Description

vjSiblingCenterH

512

The difference between the left and right view bounds is used as the width of the view. If you specify zero for left, the view is centered in relation to the sibling view. If you specify any other number for left, the view is offset by that much from a centered position (for example, specifying left = 10 and right = width+10 offsets the view 10 pixels to the right from a centered position). The left and right view bounds are relative to the sibling's right side The left bounds value is used as an offset from the left edge of the sibling and the right bounds value is used as an offset from the right edge of the sibling (for example, specifying left = 10 and right = 10 indents the view 10 pixels on each side relative to its sibling)

vjSiblingRightH vjSiblingFullH

1024 1536

Vertical alignment of the view relative to its parent or sibling view2

vjParentTopV vjParentCenterV

0 64

The top and bottom view bounds are relative to the parent's top side (default) The difference between the top and bottom view bounds is used as the height of the view. If you specify zero for top, the view is centered in the parent view. If you specify any other number for top, the view is offset by that much from a centered position (for example, specifying top = 10 and bottom = height10 offsets the view 10 pixels above a centered position). The top and bottom view bounds are relative to the parent's bottom side
continued

vjParentBottomV

128

Dening View Characteristics

2-23

CHAPTER

Views

Table 2-3 Constant

ViewJustify constants (continued) Value Description

vjParentFullV

192

The top bounds value is used as an offset from the top edge of the parent and the bottom bounds value is used as an offset from the bottom edge of the parent (for example, specifying top = 10 and bottom = 10 leaves a 10-pixel margin on both the top and the bottom) Do not use sibling vertical justication (default) The top and bottom view bounds are relative to the sibling's top side The difference between the top and bottom view bounds is used as the height of the view. If you specify zero for top, the view is centered in relation to the sibling view. If you specify any other number for top, the view is offset by that much from a centered position (for example, specifying top = 10 and bottom = height10 offsets the view 10 pixels above a centered position). The top and bottom view bounds are relative to the sibling's bottom side The top bounds value is used as an offset from the top edge of the sibling and the bottom bounds value is used as an offset from the bottom edge of the sibling (for example, specifying top = 10 and bottom = 10 indents the view 10 pixels on both the top and the bottom sides relative to its sibling)

vjSiblingNoV vjSiblingTopV vjSiblingCenterV

0 16384 4096

vjSiblingBottomV vjSiblingFullV

8192 12288

Text limits

noLineLimits oneLineOnly oneWordOnly

0 8388608 16777216

No limits, text wraps to next line (default) Allows only a single line of text, with no wrapping Allows only a single word. (If the user writes another word, it replaces the rst.)

1. If you are applying horizontal sibling-relative justication and the view is the rst child, it is positioned according to the horizontal parent-relative justication setting. 2. If you are applying vertical sibling-relative justication and the view is the rst child, it is positioned according to the vertical parent-relative justication setting.

2-24

Dening View Characteristics

CHAPTER

Views

If you want to restrict a view to accepting a single character only, you can use oneWordOnly and use a custom dictionary of single letters.

Figure 2-7

View justication effects


Vertical alignment of view contents

Horizontal alignment of view contents

Justify vjFullV

Dening View Characteristics

2-25

CHAPTER

Views

Figure 2-7

View justication effects (continued)

Horizontal alignment of the view relative to its parent view Parent View viewBounds: {Left:0, Top:25, Right:175, Bottom:75} viewBounds: {Left:0, Top:100, Right:175, Bottom:150} viewBounds: {Left:-175, T op:175, Right:0, Bottom:225} viewBounds: {Left:0, Top:250, Right:0, Bottom:300}

Horizontal alignment of the view relative to its sibling view

Sibling View Each of the paragraph views has the same viewBounds: {Left:0, Top:23, Right:185, Bottom:43}

2-26

Dening View Characteristics

CHAPTER

Views

Figure 2-7

View justication effects (continued)

Vertical alignment of the view relative to its parent view Parent View vjParentFullV viewBounds: {Left:165, Top:40, Right:205, Bottom:-40}

vjParentTopV viewBounds: {Left:5, Top:0, Right:45, Bottom:40} vjParentCenterV viewBounds: {Left:55, T op:0, Right:95, Bottom:40}

vjParentBottomV viewBounds: {Left:105, Top:-40, Right:145, Bottom:0}

Vertical alignment of the view relative to its sibling view Each of the paragraph views has the same viewBounds: {Left:31, T op:0, Right:215, Bottom:20}

Sibling View

Dening View Characteristics

2-27

CHAPTER

Views

viewOriginX and viewOriginY Slots


These optional slots are used to set the origin offset for a view. If these slots aren't found, the top-left corner of any child views is positioned relative to the top-left corner of the parent view rectangle, as you would expect. If you use these slots to specify an offset, the point you specify becomes the new origin. Child views are drawn offset by this amount. This is useful for displaying different portions of a view whose content area is larger than its view bounds. You can use the SetOrigin method to easily change the origin of a view, creating a scrolling effect. For more information, see the section Scrolling View Contents beginning on page 2-82.

Appearance
The viewFormat slot denes view attributes such as its ll color, frame color, frame type, and so on. Custom ll and frame patterns are dened using the viewFillPattern and viewFramePattern slots. The viewTransferMode slot controls the appearance of the view when it is drawn on the screen; that is, how the bits being drawn interact with bits on the screen.

viewFormat Slot
The viewFormat slot denes visible attributes of a view such as its ll color, frame type, and so on. In the viewFormat slot, you can specify one or more format attributes, which are represented by constants dened as bit ags. You can specify one format attribute from each of the following groups:
n n n

View ll color View frame color View frame thickness

2-28

Dening View Characteristics

CHAPTER

Views

n n n n

View frame roundedness View frame inset View shadow style View line style (these are solid or dotted lines drawn in the view to make it look like lined paper; this attribute applies only to views of the clEditView or clParagraphView class)

Multiple attributes are specied by adding them together like this: vfFillWhite+vfFrameBlack+vfPen(2)+vfLinesGray Note that the frame of a view is drawn just outside of the view bounding box, not within it. The ll for a view is drawn before the view contents are drawn and the frame is drawn after the contents are drawn.
IMPORTANT

Many views need no ll color, so you may be inclined to set the ll color to none when you create such a view. However, its best to ll the view with white, if the view can be dirtied and if you dont need a transparent view. This will increase the performance of your application because when the system is redrawing the screen, it doesnt have to update views behind those lled with a solid color such as white. However, dont ll all views with white, since there is some small overhead associated with lls; only use this technique if the view is one that is usually dirtied. Also, note that the application base view always appears opaque, as do all child views of the root view. That is, if no ll is set for the application base view, it will automatically appear to be lled with white. s

Dening View Characteristics

2-29

CHAPTER

Views

The view format attributes are listed and described in Table 2-4.

Table 2-4 Constant

ViewFormat constants Description

Value

vfNone

There are no format attributes set for the view (default)

View ll color

vfFillWhite vfFillLtGray vfFillGray vfFillDkGray vfFillBlack vfCustom<< vfFillShift


View frame color

1 2 3 4 5 14

Fill view with white Fill view with light gray Fill view with gray Fill view with dark gray Fill view with black Fill the view with the custom pattern specied in the viewFillPattern slot

vfFrameWhite vfFrameLtGray vfFrameGray vfFrameDkGray vfFrameBlack vfFrameMatte vfCustom<< vfFrameShift

16 32 48 64 80 240 224

White frame Light gray frame Gray frame Dark gray frame Black frame Thick gray frame bordered by a black frame, giving a matte effect Use the custom frame pattern specied in the viewFramePattern slot
continued

2-30

Dening View Characteristics

CHAPTER

Views

Table 2-4 Constant View frame thickness

ViewFormat constants (continued) Description

Value

vfPen(pixels)

pixels * 256

Sets the frame width. pixels species the pen thickness in pixels, from 0 through 15.

View frame roundedness

vfRound(pixels)

pixels * 16777216

Sets the corner radius for a rounded frame. pixels specifies the corner radius in pixels, from 0 through 15.

View frame inset

vfInset(pixels)

pixels * 65536

Sets the inset style for the frame; that is, the amount of white space (in pixels) between the view bounds and the frame. pixels species the inset, from 0 through 3.

View shadow style

vfShadow(pixels)

pixels * 262144

Sets the shadow style for the view. pixels species the thickness of the shadow in pixels that is shown on the bottom and right sides of the view frame. Specify a number from 0 through 3.

View line style (for clEditView and clParagraphView view classes only)

vfLinesWhite vfLinesLtGray vfLinesGray vfLinesDkGray vfLinesBlack vfCustom<< vfLineShift

4096 8192 12288 16384 20480 57344

Draw horizontal lines in white Draw widely dotted horizontal lines Draw dotted horizontal lines Draw dashed horizontal lines Draw solid black horizontal lines Use the custom line pattern specied in the viewLinePattern slot

Dening View Characteristics

2-31

CHAPTER

Views

Custom Fill and Frame Patterns


Custom ll and custom frame patterns are set for a view by using the vfCustom flag, as shown in Table 2-4, and by using following two slots: viewFillPattern Sets a custom ll pattern that is used to ll the view. viewFramePattern Sets a custom pattern that is used to draw the frame lines around the view, if the view has a frame. You can use custom ll and frame patterns by setting the value of the viewFillPattern and viewFramePattern slots to a binary data structure containing a custom pattern. A pattern is simply an eight-byte binary data structure with the class 'pattern. You can use this NewtonScript trick to create binary pattern data structures on the y: myPat := SetClass( Clone("\uAAAAAAAAAAAAAAAA"),'pattern) This code clones a string, which is already a binary object, and changes its class to 'pattern. The string is specied using hexadecimal character codes whose binary representation is used to create the pattern. Each two-digit hex code creates one byte of the pattern.

viewTransferMode Slot
The viewTransferMode slot species the transfer mode to be used for drawing in the view. The transfer mode controls how bits being drawn are placed over existing bits on the screen. The constants that you can specify for the viewTransferMode slot are listed and described in Table 2-5. The transfer mode is used to specify how bits are copied onto the screen when something is drawn in a view. For each bit in the item to be drawn, the system nds the existing bit on the screen, performs a Boolean operation on the pair of bits, and displays the resulting bit.

2-32

Dening View Characteristics

CHAPTER

Views

Table 2-5 Constant

ViewTransferMode constants Value Description

modeCopy

Simply replaces the pixels in the destination with the pixels in the source, painting over the screen without regard for whats already there. Replaces screen pixels under the black part of the source image with black pixels. Screen pixels under the white part of the source image are unchanged. Inverts screen pixels under the black part of the source image. Screen pixels under the white part of the source image are unchanged. Erases screen pixels under the black part of the source image, making them all white. Screen pixels under the white part of the source image are unchanged. Replaces screen pixels under the black part of the source image with white pixels. Screen pixels under the white part of the source image are made black. Screen pixels under the black part of the source image are unchanged. Screen pixels under the white part of the source image are made black. Screen pixels under the black part of the source image are unchanged. Screen pixels under the white part of the source image are inverted.
continued

modeOr

modeXor

modeBic

modeNotCopy

modeNotOr

modeNotXor

Dening View Characteristics

2-33

CHAPTER

Views

Table 2-5 Constant

ViewTransferMode constants (continued) Value Description

modeNotBic

Screen pixels under the black part of the source image are unchanged. Screen pixels under the white part of the source image are made white. This is a special transfer mode used for drawing views of the clPictureView class only. It causes the picture mask image to be erased rst and then the picture bit image is drawn over it using the modeOr transfer mode.

modeMask

The rst eight transfer modes are illustrated in Figure 2-8. The last transfer mode, modeMask, is a special one, and its effects are dependent on the particular picture being drawn and its mask. In Figure 2-8, the Source item represents something being drawn on the screen. The Destination item represents the existing bits on the screen. The eight patterns below these two represent the results for each of the standard transfer modes.

Opening and Closing Animation Effects


Another attribute of a view that you can specify is an animation that occurs when the view is opened or closed on the screen. If an effect is dened for a view, it occurs whenever the view is sent an Open, Close, Show, Hide, or Toggle message. Use the viewEffect slot to give the view an opening or closing animation. Alternately, you can perform one-time effects on a view by sending it one of these view messages: Effect, SlideEffect, RevealEffect, or Delete. These methods are described in the section Animating Views beginning on page 2-73.

2-34

Dening View Characteristics

CHAPTER

Views

Figure 2-8

Transfer modes
Source Destination (Screen)

modeCopy

modeOr

modeXor

modeBic

modeNotCopy

modenotOr

modeNotXor

modeNotBic

The viewEffect slot species an animation that occurs when a view is shown or hidden. If this slot is not present, the view will not animate at these times. There are several predened animation types. You can also create a custom effect using a combination of viewEffect ags from Table 2-6. To use one of the predened animation types, specify the number of animation steps, the time per step, and the animation type, with the following values: fxSteps(x) fxStepTime(x) In x specify the number of steps you want, from 1 to 15 In x specify the number of ticks that you want each step to take, from zero to 15 (there are 60 ticks per second)

Dening View Characteristics

2-35

CHAPTER

Views

Specify one of the following values to select the type of animation effect desired: fxCheckerboardEffect fxBarnDoorOpenEffect fxBarnDoorCloseEffect fxVenetianBlindsEffect fxIrisOpenEffect fxIrisCloseEffect fxPopDownEffect fxDrawerEffect fxZoomOpenEffect fxZoomCloseEffect fxZoomVerticalEffect A complete viewEffect specication might look like this: fxVenetianBlindsEffect+fxSteps(6)+fxStepTime(8). You can omit the fxSteps and fxStepTime constants and appropriate defaults will be used, depending on the type of the effect. Table 2-6 lists all of the view effects constants that you can use in the viewEffect slot to create custom animation effects. You combine these constants in different ways to create different effects. For example, the predened animation type fxCheckerboardEffect is dened as: fxColumns(8)+fxRows(8)+fxColAltPhase+fxRowAltPhase+fxDown It is difcult to envision what the different effects will look like in combination, so it is best to experiment with different combinations until you achieve the effect you want.

2-36

Dening View Characteristics

CHAPTER

Views

Table 2-6

ViewEffect constants

Constant

Value

Description

fxSteps(x)

(x-1)* 2097152 x*4194304

Sets the number of steps (x) that the animation should take to complete. Specify an integer from 1 to 15. Sets the amount of time (x) to take for each animation step, in ticks. There are 60 ticks per second, or 16.6 milliseconds per tick. Specify an integer from zero to 15. Sets the number (x) of columns in which to divide the view for animation purposes. Sets the number (x) of rows in which to divide the view for animation purposes. Indicates that you want the animation to include horizontal movement. (Note that you can also specify fxMoveV.) If specied, indicates that you want the rst column to begin moving towards the left. If not specied, the rst column begins moving towards the right. This ag can be used only if fxMoveH is specied. If specied, the direction of horizontal movement alternates for each column in the view. If not specied, all columns move in the same direction (left or right) as the rst column. This ag can be used only if fxMoveH is specied. If specied, the direction of horizontal movement alternates for each row in the view. If not specied, all rows move in the same direction (left or right) as the rst row. This ag can be used only if fxMoveH is specied. Indicates that you want the animation to include vertical movement. (Note that you can also specify fxMoveH.)
continued

fxStepTime(x)

fxColumns(x) fxRows(x) fxMoveH

x-1 (x-1)*32 65536

fxHStartPhase

1024

fxColAltHPhase

4096

fxRowAltHPhase

16384

fxMoveV

131072

Dening View Characteristics

2-37

CHAPTER

Views

Table 2-6

ViewEffect constants (continued)

Constant

Value

Description

fxVStartPhase

2048

If specied, indicates that you want the rst row to begin moving upwards. If not specied, the rst row begins moving downwards. This ag can be used only if fxMoveV is specied. If specied, the direction of vertical movement alternates for each column in the view. If not specied, all columns move in the same direction (up or down) as the rst column. This ag can be used only if fxMoveV is specied. If specied, the direction of vertical movement alternates for each row in the view. If not specied, all rows move in the same direction (up or down) as the rst row. This ag can be used only if fxMoveV is specied. Indicates that motion should be towards the left. (This ag is the same as specifying fxHStartPhase+fxMoveH.) Indicates that motion should be towards the right. (This ag is the same as specifying fxMoveH and not specifying fxHStartPhase.) Indicates that motion should be towards the top. (This ag is the same as specifying fxVStartPhase+fxMoveV.) Indicates that motion should be towards the bottom. (This ag is the same as specifying fxMoveV and not specifying fxVStartPhase.) If specied, causes a line to be drawn at the edge(s) from which the animation is being revealed. For some types of animation, this setting improves the effect.
continued

fxColAltVPhase

8192

fxRowAltVPhase

32768

fxLeft

66560

fxRight

65536

fxUp

133120

fxDown

131072

fxRevealLine

262144

2-38

Dening View Characteristics

CHAPTER

Views

Table 2-6

ViewEffect constants (continued)

Constant

Value

Description

fxWipe

524288

If specied, causes the view to be revealed in place rather than actually moved into place. In other words, the view is revealed just like a window is revealed by rolling a shade away. Without this ag, the view is actually moved into place. If specied, causes the animation to begin at the edge of the screen, ending up at the ultimate view location. Without this ag, the entire animation occurs within the bounds of the view being animated.

fxFromEdge

1048576

Other Characteristics
Other view characteristics are controlled by the following slots: viewFont Species the font used in the view. This slot applies only to views that hold text, that is, views of the class clParagraphView. For more information about how to specify the font, see the section Text View in the chapter Working with View Classes. When the template is instantiated, a slot named with the value of this slot is added to the view. Its value is simply a reference to itself. For example, if you specify declareSelf:'base, a slot named base is added to the view and its value is set to a reference to itself. Note that this slot is not inherited by the children of a view; it applies only to the view within which it exists.

declareSelf

Dening View Characteristics

2-39

CHAPTER

Views

Inheritance Links
These slots describe the template's location in the inheritance chain, including references to its proto, parent, and children. The following slots are not inherited by children of the template. _proto Contains a reference to a proto template. This slot is created and set automatically when you drag out a new view in NTK. Contains a reference to the parent template. This slot is created and set automatically when you drag out a new view in NTK. Note that its best to use the Parent function to access the parent view at run time, rather than directly referencing the _parent slot. Contains an array that holds references to each of the template's child templates. This slot is created and set automatically when you graphically create child views in NTK. This slot is for children that you add to a template. Contains an array that holds references to each of a system protos child templates. Because this slot is used by system protos, you should never modify this slot or create a new one with this name. If you do so, you may be inadvertently overriding the children of a system proto.

_parent

stepChildren

viewChildren

Here is the reason for the dual child view slots. The viewChildren slot is used by the system protos to store their child templates. If you create a view derived from one of the system protos and you change the viewChildren slot (for example, to add your own child templates programmatically), then you would actually be creating a new viewChildren slot that would override the one in the proto, and the child templates of the proto would be ignored. The stepChildren slot has been provided instead as a place for you to put your child templates, if you need to do so from within a method. By adding your templates to this slot, the viewChildren slot of the proto is not

2-40

Dening View Characteristics

CHAPTER

Views

overridden. Both groups of child views are created when the parent view is instantiated. If you are only creating views graphically using the Newton ToolKit palette, you dont need to worry about these internal details. The Newton ToolKit always uses the stepChildren slot for you. You may see either viewChildren, stepChildren, or both slots when you examine a template at run time in the Newton ToolKit Inspector window. Child templates can be listed in either slot, or both. When a view is instantiated, all of the child views from both of these two slots are also created. Note that the templates in the viewChildren slot are instantiated rst, followed by the templates in the stepChildren slot. If you are adding child views in a method that will not be executed until run time, you should use the stepChildren slot to do this. If there isnt a stepChildren slot, create one and put your views there.
IMPORTANT

Remember that the viewChildren and stepChildren arrays contain templates, NOT views. If you try to send a message like Hide to one of the objects listed in this array, nothing will happen because it is not a view. During run time, if you want to obtain references to the child views of a particular view, you must use the ChildViewFrames method. This method returns views from both the viewChildren and stepChildren slots. This method is described in the section Getting References to Views beginning on page 2-45. s

View Instantiation
View instantiation refers to the act of creating a view from its template. The process of view instantiation includes several steps and it is important to understand when and in what order the steps occur.

View Instantiation

2-41

CHAPTER

Views

Declaring a View
Before diving into the discussion of view instantiation, it is important to understand the term declaring. Declaring a view is something you do during the application development process using the Newton ToolKit (NTK). Declaring a view allows the view to be accessed symbolically from another view. In NTK, you declare a view using the Template Info command. (We say declaring a view, but at development time, of course, youre really just dealing with the view template.) In the Template Info dialog, you declare a view by checking the box entitled, Declare To, and then choosing another view in which to declare the selected view. The name you give to your view must be a valid symbol, and not a reserved word or the name of a system function or method. You always declare a view in its parent or in some other view farther up the parent chain. Its best, for efciency and speed, to declare a view in the lowest level possible in the view hierarchy; that is, in its parent view or as close to it as possible. You must declare a view at a level at or above other views that need access to it or that need to send it messages. Declaring a view simply puts a slot in the place you declare the view. The slot name is the name of the view you are declaring. The slot value, at run time, will hold a reference to the declared view. NTK always automatically declares the base view of your application in the system root view. Note that the application base view is declared in a slot named with its application symbol, specied in the Application Symbol eld of the Project Settings dialog in NTK. Why would you want to declare a view? When a view is declared in another view, it can be accessed symbolically from that other view. The NewtonScript inheritance rules already allow access from a view to its parent view, but there is no direct access from a parent view to its child views, or between child views of a common parent. Declaring a view provides this access. For example, if you have two child views of a common parent, and they need to send messages to each other, you need to declare each of them in the

2-42

View Instantiation

CHAPTER

Views

common parent view. Or, if a parent view needs to send messages to one of its child views, the child view must be declared in the parent view. One key situation requiring a declared view is when you want to send the Open message to show a nonvisible view. The Open message can only be sent to a declared view. Declaring a view has a small amount of system overhead associated with it. This is why the system doesnt just automatically declare every view you create. You should only declare views that you need to access from other views. For a more detailed technical description of the inner workings of declaring a view, see Appendix B, The Inside Story on Declare.

Creating a View
A view is created in two stages. First, a view memory object (a frame) is created in RAM. This view memory object contains a reference to its template and contains other transient run-time information. In the following discussion, well use the term, creating the view, to describe just this part of the process. Second, the graphical representation of the view is created and shown on the screen. In the following discussion, well use the term, showing the view, to describe just this part of the process A view is created and shown at different times, depending on whether or not it is a declared view.
n

If the view is declared in another open (shown) view, it is created when the view in which it is declared is sent the Open message. For example, a child view declared in the parent of its parent view is created when that grandparent view is opened. Note, however, that the child view is not necessarily shown at the same time it is created. If the view is not declared in any view, it is created and also shown when its immediate parent view is sent the Open message. (Note that if a non-declared views vVisible ag is not set, that view can never be created.)

View Instantiation

2-43

CHAPTER

Views

Here is the view creation sequence for a typical application installed in the Newton Extras Drawer and declared in the system root view: 1. When your application is installed on the Newton device, its base view is automatically created, but not shown. This is because it is declared in the root view, which is always open in the Newton system. 2. When the user taps on the icon representing your application in the Extras Drawer, the viewClickScript method for the icon sends the Toggle message to your applications base view (hereafter called the base view), identied in the root view by its application symbol. 3. A view is created (but not shown yet) for each template declared in the base view. Slots with the names of these views are created in the base view. These slots contain references to their corresponding views. 4. The viewSetupFormScript message is sent to the base view, several slots are read from the view template, and then the viewSetupChildrenScript message is sent to the base view. 5. Each child of the base view whose vVisible ag is set is created and shown using this same sequence of steps. (If a child view was previously created as a result of step 3, the view is simply shown. Otherwise, the view is both created and shown.) 6. The viewSetupDoneScript message is sent to the base view. 7. The base view is shown on the screen. As you can see from step 5, when a view is opened, all of the child views in the hierarchy under it are also shown (as long as they are agged as visible). A nonvisible child view can be subsequently shown by sending it the Open messageas long as it has been declared. For a more detailed description of the system messages sent during view instantiation and the state of the view at each step, see the section Initialization and Termination Messages beginning on page 5-2.

2-44

View Instantiation

CHAPTER

Views

Closing a View
When you send a view the Close message, the graphical representation of the view (and of all of its child views) is destroyed, but the view memory object is not necessarily destroyed. There are two possibilities:
n

If the view was declared, and the view in which it was declared is still open, the view memory object is preserved. So you can send the view another Open or Toggle message to reopen it at a later time. A view memory object is nally destroyed when the view in which it was declared is closed. That is, when a view is closed, all views declared in it are made available for garbage collection. If the view being closed was not declared, both its graphical representation and its view memory object are made available for garbage collection when it is closed.

Getting References to Views


Frequently, when performing view operations, you need access to the child or parent views of a view, or to the root view in the system. There are methods and functions you can use to return references to these related views. Especially note the ChildViewFrames method. This is an important method you must use if you need access to the child views of a view. To test whether an application is open or not, you can use the GetRoot function, together with the application symbol.

Getting References to Views

2-45

CHAPTER

Views

ChildViewFrames view:ChildViewFrames() Returns an array of views that correspond to the child views of the view to which this message is sent.
IMPORTANT

You must use this method to get to the child views of a view. If you just reference the viewChildren or stepChildren slots in the view, you will get references to the child templates, not the views. Of course, you can also directly reference any declared child view. s Parent view:Parent() Returns the parent view of the view to which this message is sent. This is the recommended method of getting a reference to a views parent view, rather than directly referencing the _parent slot. GetRoot GetRoot() Returns the system root view. All applications are normally declared in the root view under their application symbol. This means there is a slot in the root view whose name is the application symbol and whose value is that view. You can use this code to test if an application is open: GetRoot().applicationSymbol.viewCObject; If the application is open, this function will return a non-nil value, otherwise, nil is returned. The viewCObject slot in a view holds a reference to an object representing the visual depiction of the view. This reference is always present as long as a view is open, and never present when a view is closed.

2-46

Getting References to Views

CHAPTER

Views

GetView GetView(view) Returns the rst view found that corresponds to the specied view name or symbol. If no view is found, nil is returned. view The name of the view you want to get. Besides a view name, you can pass in the following special symbols (which are evaluated at run time):

'viewFrontMost, to return the frontmost view on the screen that has the vApplication flag set in its viewFlags slot 'viewFrontMostApp, to return the fr ontmost view on the screen that has the vApplication ag set in its viewFlags slot, but not including oating views (those with vFloating set in their viewFlags slot) 'viewFrontKey, to return the view on the screen that accepts keys (there can be only one view that is the key receiver)

Note that this function can be slow when passed a view name because it has to search through all views in the system. If you know that you'll need to refer to a view later when you create it, it's best to store a reference to it in a slot so that you can access it quickly when needed, rather than using this function to nd it. (Declaring the view will accomplish this.)

Displaying, Hiding, and Redrawing Views


To display a view (and its visible child views), send it one of the following view messages:
n n n

Opento open the view Toggleto open or close the view Showto show the view if it had previously been opened, then hidden

Displaying, Hiding, and Redrawing Views

2-47

CHAPTER

Views

To hide a view (and its child views), send it one of the following view messages:
n n n

Closeto hide and delete it from memory Toggleto close or open the view Hideto hide it temporarily

You can cause a view (and its child views) to be redrawn by using one of the following view messages or global functions:
n

Dirtyflags the view as dirty so it is redrawn during the next system idle loop RefreshViewsredraws all dirty views immediately SetValuesets the value of a slot and dirties the view SyncViewredraws the view if its bounds have changed

n n n

All of the methods and functions summarized here are described in the following subsections. Open view:Open() Creates the graphical representation of the view. This method then plays the show sound (stored in the showsound slot), brings the view to the front, and shows it and all of its child views. The view receives the following system messages: viewSetupFormScript, viewSetupChildrenScript, viewSetupDoneScript, viewDrawScript, and viewShowScript. Note that these same system messages (except for viewShowScript) are sent to all visible child views of the view as they are created and shown as well. For information about these system messages, refer to the chapter Handling System Messages. This method always returns true.

2-48

Displaying, Hiding, and Redrawing Views

CHAPTER

Views

Note that this message must be sent to a view, not to a template. To ensure that a view exists for the template, you must have declared it. For details on declaring a view, see the section View Instantiation beginning on page 2-41. You can use this code to test if a view is open: view.viewCObject; If the view is open, this code will return a non-nil value, otherwise, nil is returned. The viewCObject slot in a view holds a reference to an object representing the visual depiction of the view. This reference is always present as long as a view is open, and never present when a view is closed. Close view:Close() Closes the specied view. This means that if the view is currently visible, this method plays the hide sound (stored in the hidesound slot), calls the viewHideScript, hides the view and all of its child views, calls the viewQuitScript, and then deletes the view from memory. This method always returns true. Note that if the view is hidden (it was opened and then sent the Hide message), and you send it the Close message, it will be closed. This is because the view is still considered open even when it is hidden. You wont see anything change on the screen since the view is already invisible, but the view will be deleted from memory. Also, in this case, the hide sound is not played and the viewHideScript message is not sent. If the view has already been closed, nothing is done. If the view is a declared view, the view memory object is not deleted as a result of the Close message, as long as the view it is declared in is still open. Only the graphical representation of the view is deleted. If you want to reopen the view, send it an Open or a Toggle message.

Displaying, Hiding, and Redrawing Views

2-49

CHAPTER

Views

Note

If you need to close a view from a method within the view itself, you must send the Close message using the function AddDeferredAction so that the Close message is delayed until after the currently executing method nishes. For example, you could use code like this: begin local me := self; AddDeferredAction (func() me:close(), '[]); end
u

Toggle view:Toggle() If the view is currently closed, this method performs the same operations as if the view had been sent the Open message. If the view is currently open, this method performs the same operations as if the view had been sent the Close message. Note that if the view is hidden (it was opened and then sent the Hide message), and you send it the Toggle message, it will be closed. This is because the view is still considered open even when it is hidden. You wont see anything change on the screen since the view is already invisible, but the view will be deleted from memory. Also, in this case, the hide sound is not played. Toggle returns true if the view is to be opened, or nil if the view is to be closed, as a result of calling this method. Note that this message must be sent to a view, not to a template. To ensure that a view exists for the template, you must have declared it. For details on declaring a view, see the section View Instantiation beginning on page 2-41. Note that Toggle actually creates and destroys view objects (like Open and Close), while Show and Hide simply make existing views visible or invisible.

2-50

Displaying, Hiding, and Redrawing Views

CHAPTER

Views

Show view:Show() If the view is currently hidden, this method plays the show sound (stored in the showsound slot), brings the view to the front, shows it and all of its child views, and calls the viewShowScript. Note that you must specify a view; this method throws an exception if you specify a template. This method always returns true. You can use this method only if the view has previously been opened (you have sent it the Open or Toggle message) and then hidden (you have sent it the Hide message). Even though all children of the view being shown are also shown, the child views are not sent the viewShowScript message. This message is sent only to the view on which you use the Show method directly. Hide view:Hide() If the view is currently shown, this method plays the hide sound (stored in the hidesound slot), calls the viewHideScript, and hides the view and all of its child views. This method always returns true. Even though all children of the view being hidden are also hidden, the child views are not sent the viewHideScript message. This message is sent only to the view on which you use the Hide method directly. To show the view again, send it the Show message. Note that when a view is hidden, the graphical representation of the view in memory is not destroyed. All that actually happens is the bits are removed from the screen. The view is still considered open. This allows fast performance when the view is subsequently shown again.

Displaying, Hiding, and Redrawing Views

2-51

CHAPTER

Views

Dirty view:Dirty() Marks the view as needing redrawing. The view (and its visible child views) will be redrawn the next time the system idle task is executed. This method always returns true. If you need to force a redraw immediately on a single view, call RefreshViews immediately after you send the Dirty message to the view. In most cases, only the dirty view is updated. However, if you have more than one dirty view, calling RefreshViews can take much longer. The area of the screen that is redrawn is the rectangle that is the union of all the dirty views; and if this includes several intervening non-dirty views, it can waste time. Also, if there are multiple dirty views that are in different view hierarchies, their closest common ancestor view is redrawn, potentially causing many other views to be redrawn needlessly. When a view is redrawn as a result of the Dirty method, the system does not necessarily reread all of the slots in the view. For example, slots describing the view contents are not readthe contents are assumed to have not changed. If you were to directly change the text slot of a clParagraphView and then send it the Dirty message, you would not see the text in the view change. Usually, you want a view to redraw with its new contents, if the contents change. To do this, use the global function SetValue to change the contents of slots in the view. The SetValue function causes the system to reread all slots in the view before it is redrawn, and it automatically dirties the view so you dont have to send it the Dirty message. You can nd the description of SetValue on page 2-53. If you change the bounds of a view directly, Dirty will not cause the view to be redrawn with new bounds. To do that, send the view the SyncView message. For more details, see the description of SyncView on page 2-54.

2-52

Displaying, Hiding, and Redrawing Views

CHAPTER

Views

RefreshViews RefreshViews() Redraws all views immediately, if they need to be updated. This function always returns true. Note that if there are several views that need to be updated, this function results in slower performance relative to Dirty, which waits until idle time to redraw. SetValue SetValue(view, slotSymbol , value) Sets the value of a slot in a view. The view is agged as dirty, so it will be redrawn using the new information. view slotSymbol The view in which you want to change a slot value. A symbol naming the slot whose value you want to change. Note that you must specify a symbol (quoted identier), for example, 'mySlot. The new value of the slot.

value

This function always returns nil. You can pass in the following special symbols (which are evaluated at run time) for the view parameter:
n

'viewFrontMost, to indicate the frontmost view on the screen that has the vApplication ag set in its viewFlags slot 'viewFrontMostApp, to indicate the frontmost view on the screen that has the vApplication ag set in its viewFlags slot, but not including oating views (those with vFloating set in their viewFlags slot) 'viewFrontKey, to indicate the view on the screen that accepts keys (there can be only one view that is the key receiver)

Displaying, Hiding, and Redrawing Views

2-53

CHAPTER

Views

As expected, the view is redrawn immediately with its new settings if you set the value of one of the following slots: viewBounds, viewFormat, viewJustify, viewFont. Additionally, for these slots, the effect is as if you had sent the SyncView message to the view, including calling the viewSetupFormScript method (see the SyncView method, next). If the view exists, any dependent views (see the TieViews function on page 2-91) are notied, and the viewChangedScript message is sent to the view. If you specify a slot that does not exist in the view, the slot is created in the view. SyncView view:SyncView() Redraws a view after you change its viewBounds slot. Before the view is redrawn with new bounds, the viewSetupFormScript message is sent to the view. SyncView always returns true.

Dynamically Adding Views


Creating a view dynamically (that is, at run time) is a complex issue that has multiple solutions. Depending on what you really need to do, you can use one of the following solutions:
n

Dont create the view dynamically because its easier to accomplish what you want by creating a hidden view and then showing it later. Create the view by adding a new template to its parent views stepChildren array in the viewSetupChildrenScript method. Create the template and the view at run time by using the AddStepView function. Create the template and the view at run time by using the BuildContext function.

2-54

Dynamically Adding Views

CHAPTER

Views

If you want a pop-up list view, called a picker, use the DoPopup function to create and manage the view.

These techniques are discussed in the following sections. The rst four techniques are listed in order from easiest to most complex (and error prone) and we recommend that you use the easiest solution that will accomplish what you want. The last technique, for creating a picker view, should be used if you want that kind of view.

Showing a Hidden View


In many cases, you might think that you need to create a view dynamically. However, if the template can be dened at compile time, its easier to do that and ag the view as not visible. At the appropriate time, send it the Open message to show it. The typical example of this is a dialog box, which you can usually dene at compile time. Using Newton ToolKit (NTK), simply do not check the vVisible flag in the viewFlags slot of the view template. This will keep the view hidden when the application is opened. Also, it is important to declare this view in your application base view. For information on declaring a view, see the section View Instantiation beginning on page 2-41. When you need to display the view, send it the Open message using the name under which you have declared it (for example, myView:Open()). This solution even works in cases where some template slots cannot be set until run time. You can dynamically set slot values during view instantiation in any of the following view methods: viewSetupFormScript, viewSetupChildrenScript, and viewSetupDoneScript.

Adding to the stepChildren Array


If it is not possible to dene the template for a view at compile time, then the next best solution is to create the template (either at compile time or run time) and add it to the stepChildren array of the parent view using the

Dynamically Adding Views

2-55

CHAPTER

Views

viewSetupChildrenScript method. This way, the view system takes care of creating the view at the appropriate time (when the child views are shown). For example, if you want to dynamically create a child view, you would rst dene the view template as a frame. Then, in the viewSetupChildrenScript method of its parent view, you would add this frame to the stepChildren array of the parent view. To ensure that the stepChildren array is in RAM, use this code: if not HasSlot(self, 'stepChildren) then self.stepChildren := Clone(self.stepChildren); AddArraySlot(self.stepChildren, myDynamicTemplate); The if statement checks if the stepChildren slot already exists in the current view (in RAM). If it does not, it is copied out of the template (in ROM) into RAM. Then the new template is appended to the array. All of this takes place in the viewSetupChildrenScript method of the parent view, which is before the stepChildren array is read and the child views are created. If at some point after the child views have been created you want to modify the contents of the stepChildren array and then build new child views from it, you can use the RedoChildren view method. First, make any changes you desire to the stepChildren array, then send your view the RedoChildren message. All of the views current children will be closed and removed. A new set of child views will then be recreated from the stepChildren array. Also, note that reordering the stepChildren array and then calling RedoChildren is how you can reorder the child views of a view dynamically. For details on an easy way to create a template dynamically, see the subsection Creating Templates beginning on page 2-58.

2-56

Dynamically Adding Views

CHAPTER

Views

Using the AddStepView Function


If you need to create a template and add a view yourself at run time, use the function AddStepView. This function takes two parameters: the parent view to which you want to add a view, and the template for the view you want to create. The function returns a reference to the view it creates. Be sure to save this return value so you can access the view later. The AddStepView function also adds the template to the parents stepChildren array. This means that the stepChildren array needs to be in RAM, or AddStepView will fail. See the code in the previous section for an example of how to ensure that the stepChildren array is in RAM. The AddStepView function doesnt force a redraw when the view is created, so you must take one of the following actions yourself:
n n

Send the new view a Dirty message. Send the new views parent view a Dirty message. This is useful if youre using AddStepView to create several views and you want to show them all at the same time. If you created the view template with the vVisible bit cleared, the new view will remain hidden and you must send it the Show message to make it visible. This technique is useful if you want the view to appear with an animation effect (specied in the viewEffect slot in the template).

Do not use the AddStepView function in a viewSetupFormScript method or a viewSetupChildrenScript methodit wont work because thats too early in the view creation process of the parent for child views to be created. If you are tempted to do this, then you should instead be using the second method of dynamic view creation, in which you add your template to the stepChildren array and let the view system create the view for you. To remove a view created by AddStepView, use the RemoveStepView function. This function takes two parameters: the parent view from which you want to remove the child view, and the view (not its template) that you want to remove. Note that while this function closes the view, it does not remove the template from the stepChildren array of the parent view.

Dynamically Adding Views

2-57

CHAPTER

Views

You must remove the template yourself. If you do not do this, the parent view stepChildren array may accumulate several old templates that waste RAM and which may cause a surprise if the RedoChildren function is called. For details on an easy way to create a template dynamically, see the subsection Creating Templates beginning on page 2-58.

Using the BuildContext Function


Another function that is occasionally useful is BuildContext. It takes one parameter, a template. It makes a view from the template and returns it. The view's parent will be the root view. The template is not added to any viewChildren or stepChildren array. Basically, you get a freeagent view. Normally, you won't need to use BuildContext. It's useful when you need to create a view from code that isn't part of an application (that is, there's no base view to use as a parent). For instance, if your InstallScript or RemoveScript needs to prompt the user with a dialog, you would need to use BuildContext to create the dialog. BuildContext is also useful if you need to create a view, such as a dialog, that is larger than your application base view, since your base view cannot have child views that are larger than itself. For details on an easy way to create a template dynamically, see the following subsection, Creating Templates.

Creating Templates
The three immediately preceding techniques require you to create templates. You can do this using NewtonScript to dene a frame, but then you have to remember which slots to include and what kinds of values they can have. Its easy to make a mistake. An easy way of creating a template is to make a user proto in NTK and then use it as a template. That allows you to take advantage of the slot editors in

2-58

Dynamically Adding Views

CHAPTER

Views

NTK. At run time you can access the user proto from your code using the identier PT_filename. If there are slots whose value you can't compute ahead of time, it doesnt matter. Leave them out of the user proto, and then at run time, create a frame with those slots set properly and include a _proto slot pointing to the user proto. A typical example might be needing to compute the bounds of a view at run time. If you dened all the static slots in a user proto in the le called dynoTemplate, then you could create the template you need using code like this: template := {viewBounds: RelBounds(x, y, width, height), _proto: PT_dynoTemplate, } This really shows off the advantage of a prototype-based object system. You create a small object on the y and the system uses inheritance to get the rest of the needed values. Your template is only a two-slot object in RAM. The user proto resides in the package with the rest of your application. The conventional, RAM-wasting alternative would have been: template := Clone(PT_dynoTemplate); template.viewBounds := RelBounds(x, y, width, height); You should also note that for creating views arranged in a table, there is a function called LayoutTable which handles calculating all the bounds. It returns an array of templates.

Making a Picker View


To create a transient pop-up list view, or picker, you can use the function DoPopup. This kind of view pops up on the screen and is a list from which the user can make a choice by tapping it. As soon as the user chooses an item, the picker view is closed. You can also create a picker view by dening a template using the protoPicker view proto, described beginning on page 3-40.

Dynamically Adding Views

2-59

CHAPTER

Views

Functions for Dynamically Adding Views


The following functions are useful for creating and removing views at run time. AddStepView AddStepView(parentView, childTemplate) Dynamically instantiates a new view based on the specied child template and adds it to the parent's stepChildren array. You must send the Dirty message to the new view or to its parent view to cause the new view to be drawn. parentView childTemplate The parent view to which you want to add the new view. A template describing the new view you want to add.

This function returns the view if it was successfully created; otherwise, nil is returned. You can pass in the following special symbols (which are evaluated at run time) for the parentView parameter:
n

'viewFrontMost, to indicate the frontmost view on the screen that has the vApplication ag set in its viewFlags slot 'viewFrontMostApp, to indicate the frontmost view on the screen that has the vApplication ag set in its viewFlags slot, but not including oating views (those with vFloating set in their viewFlags slot) 'viewFrontKey, to indicate the view on the screen that accepts keys (there can be only one view that is the key receiver)

Because this function adds an item to the parents stepChildren array , you must ensure that the array is in RAM, or AddStepView will fail. You can use this code: if not HasSlot(parentView, 'stepChildren) then parentView.stepChildren := Clone(parentView.stepChildren);

2-60

Dynamically Adding Views

CHAPTER

Views

The if statement checks if the stepChildren slot already exists in the parent view (in RAM). If it does not, it is copied out of the template in ROM into RAM. Note that you can add an invisible view; that is, one with its vVisible ag not set. You might want to do this if you want the view to show itself with an effect. First add it invisibly, then send it the Show message. (If you just add it as a visible view, any view effect you specify is not done when it is rst displayed.) RemoveStepView RemoveStepView(parentView, childView) Removes a child view from its parent view. The child view is closed, if visible. parentView childTemplate The parent view from which you want to remove the child view. The child view you want to remove.

This function always returns nil. You can pass in the following special symbols (which are evaluated at run time) for the either the parentView or childView parameters:
n

'viewFrontMost, to indicate the frontmost view on the screen that has the vApplication ag set in its viewFlags slot 'viewFrontMostApp, to indicate the frontmost view on the screen that has the vApplication ag set in its viewFlags slot, but not including oating views (those with vFloating set in their viewFlags slot) 'viewFrontKey, to indicate the view on the screen that accepts keys (there can be only one view that is the key receiver)

Note that while this function closes the view, it does not remove the template from the stepChildren array of the parent view. You must remove the template yourself. If you do not do this, the parent view stepChildren array may accumulate several old templates that waste RAM and which may cause a surprise if the RedoChildren function is called.

Dynamically Adding Views

2-61

CHAPTER

Views

If the specied child view is a root-level view (a child of the root view), this function plays the hide sound (stored in the hidesound slot in the view), sends the view a viewHideScript message, sends the view a viewQuitScript message, and hides the view (and all of its child views). The view is not deleted from memory. It can be reopened by sending it the Open or Toggle message. If the specied child view is not a child of the root view, the same operations occur, except that the hide sound is not played and the viewHideScript message is not sent. BuildContext BuildContext(template) Dynamically instantiates a new view based on the specied template and adds it to the root view. template A template describing the new view you want to add.

This function returns the view that it creates. To display the newly created view, send it the Open message. If the viewFlags slot of the template includes the vVisible flag, you will also need to send the view the Dirty message to make it show up. Its best if you dont set the vVisible ag in the template, that way you can display the view with a simple Open message, and this also allows any view effect you specify to be done when the view is rst shown. The parent of the new view is set to the root view. The template is not added to the viewChildren or stepChildren array of any view. The _proto slot of the new view is set to the template that it was created from.

2-62

Dynamically Adding Views

CHAPTER

Views

DoPopup DoPopup(list, insetH, insetV , notifyView) Creates a dynamic pop-up list view, or picker, from which one item can be selected. list An array of items that you want to appear in the picker list. The elements in the array will be shown with the rst item at the top of the list, continuing down to the last item. Do not create a list with more items than can be shown on the screen at one time; scrolling the list is not supported. A horizontal and a vertical distance, respectively, in pixels. These values are used to dene a rectangle that is inset within the bounds of the view (the parent) from within which DoPopup is called. The left and right edges of the new rectangle are inset insetH pixels from the sides of the parent, and the top and bottom edges of the rectangle are inset insetV pixels from the top and bottom edges of the parent. The picker view will be created so that one of its corners corresponds to one of the corners of the inset rectangle. The system gures out exactly where to position the picker view, depending on how large it is and how much space is available around it. For example, it would normally be positioned so that its top-left corner corresponds to the top-left corner of the inset rectangle. However, if the rectangle is in the lower-right corner of the screen, there wont be enough room for the picker; instead it will be positioned with its lower-right corner corresponding to the lower-right corner of the inset rectangle.

insetH, insetV

Dynamically Adding Views

2-63

CHAPTER

Views

notifyView

The view that should be notied when an item from the picker is selected by the user, or when the picker is closed without a selection. You can specify the special variable, self, to refer to the view from within which DoPopup is called.

DoPopup returns the picker view that it creates. You can include the following items in the list array:
n n n

Strings Graphics (bitmaps) The 'pickSeparator symbol. This includes a separator line, which is not pickable, between the preceding and following items. A frame. This is used to specify a string or graphic item along with associated options. For example, you can indicate that some items are disabled (non-pickable), and you can place a mark next to an item if it is selected. You can specify the following slots in the frame: item pickable mark The string or bitmap reference Specify true if you want the item to be pickable, or nil for not pickable Specify the character you want to use to mark this item (for example, $). To use marks other than those represented on the keyboard, you must specify the character using its Unicode value. (You can use the constant kCheckMarkChar for a check mark character or the constant kPopChar for a diamond character in the Espy font.) If this item is the one selected, the mark appears to its left in the picker; otherwise, the mark is not displayed.

2-64

Dynamically Adding Views

CHAPTER

Views

You can pass in the following special symbols (which are evaluated at run time) for the notifyView parameter:
n

'viewFrontMost, to indicate the frontmost view on the screen that has the vApplication ag set in its viewFlags slot 'viewFrontMostApp, to indicate the frontmost view on the screen that has the vApplication ag set in its viewFlags slot, but not including oating views (those with vFloating set in their viewFlags slot) 'viewFrontKey, to indicate the view on the screen that accepts keys (there can be only one view that is the key receiver)

When an item in a picker is selected, the system sends the pickActionScript message to the view indicated by notifyView. You must dene pickActionScript as a method that accepts one parameter. The parameter passed to pickActionScript is the array index of the item number selected in the list (the rst item has an index of zero). If no item is selectedthat is, if the user taps outside the picker to close it the pickCancelledScript message is sent to the view indicated by notifyView. If you want to handle this message, define a method that accepts no parameters, since none are passed. SetItemMark and GetItemMark are two methods provided for picker views. You can use them within the pickActionScript method (or elsewhere) to set and get the mark for an item. You call these methods like this: dopopupView :SetItemMark() dopopupView :GetItemMark() where dopopupView is the view returned by the DoPopup function. For details on these methods, see the description of the protoPicker proto beginning on page 3-40. The picker view created by DoPopup is automatically closed after the user selects an item or taps outside the view.

Dynamically Adding Views

2-65

CHAPTER

Views

Making Modal Views


A modal view is one that puts the user into a mode. That is, the user is primarily restricted to interacting with the modal view. All taps outside the modal view are ignored while the modal view is open. (The user can write outside the modal view, however.) In the interest of good user interface design, you should avoid using modal views unless they are absolutely necessary. However, there are occasions when you may need one. Typically, modal views are used for dialog boxes. For example, if the user was going to delete some data in your application, you might want to display a modal dialog asking them to conrm or cancel the operation. The modal dialog would prevent them from going to another application until they provide an answer. You can display such a dialog containing OK and Cancel buttons by using the Confirm method. You can specify a message of your choosing to be displayed in the dialog. For more exibility, you can design your own modal view and use the ModalDialog method to open it. These methods are described in the following paragraphs. Conrm rootView:Confirm(titleStr, message, methodView, method ) Creates and displays an OK/Cancel dialog in an alert box. When the user taps on either the OK or Cancel buttons, the dialog sends a message to a view that you specify and then closes itself. titleStr message methodView A string that is the title of your application. This string is unused. A string that is the message to display in the dialog box. The view containing method.

2-66

Making Modal Views

CHAPTER

Views

method

A symbol that is the name of a method to be called after the dialog is dismissed. This method is passed one parameter, a Boolean value that indicates whether or not the user tapped the OK button. The parameter is set to true if the user tapped OK, or it is set to nil if the user tapped Cancel.

Confirm always returns true. The Confirm method belongs to the system root view, which all views can access through inheritance. So you can send the Confirm message either to the current view (for example, self:Confirm(...)) or directly to the root view (for example, GetRoot():Confirm(...)). An example of the Conrm dialog is shown in Figure 2-9.
Figure 2-9 Conrm dialog

Here is the code used to create the dialog shown in Figure 2-9: myTestButton := {... buttonClickScript: func() begin local msg := "Do you really really want to do this operation?"; self:Confirm("Testing app", msg, self:Parent(), 'confirmDone); end, ...}

Making Modal Views

2-67

CHAPTER

Views

theParent := {... confirmDone: func(confirmed) begin If confirmed then print("Dialog OKed"); else print("Dialog canceled"); end, ...} ModalDialog view:ModalDialog() This method opens a view, just like the Open method. The only difference is that the view is modal. This means that all taps outside the modal view are ignored while the modal view is open. (However, the user can write outside the modal view, on the notepad, for example.) The modal state is exited when the modal view is closed. This method always returns true, and it returns only after the view is closed. In order that the method from which you call ModalDialog from can return properly before the modal dialog is displayed, you must send the ModalDialog message using the global function AddDeferredAction, like this: AddDeferredAction(func() myView:ModalDialog(), '[]); One more important thing to know is that taps on buttons outside the modal dialog are allowed within the application of which it is a part For example, the user could tap the close box of your application. This behavior is not desirable, but its easy to prevent. Make the parent view of the modal dialog a clView that acts as a mask to prevent any taps from getting through to your application. This clView should have the following characteristics:
n n

It is transparent ( viewFormat Fill is set to None) It covers the full extent of the base application view (viewJustify ags are set to Parent Relative Full for both horizontal and vertical, and the viewBounds values are all zero)

2-68

Making Modal Views

CHAPTER

Views

It accepts taps (vClickable is set in the viewFlags slot).

Like Open, the ModalDialog method creates the graphical representation of the view. It then plays the show sound (stored in the showsound slot), brings the view to the front, and shows it (and all of its child views). The view receives the following system messages: viewSetupFormScript, viewSetupChildrenScript, viewSetupDoneScript, viewDrawScript, and viewShowScript. For information about these system messages, refer to the chapter Handling System Messages. Note that this message must be sent to a view, not to a template. To ensure that a view exists for the template, you must have declared it. For details on declaring a view, see the section View Instantiation beginning on page 2-41. Here is an example showing the use of the ModalDialog method: OpenItButton := {... // opens modal dialog view _proto: prototextbutton text: "Open Modal View", buttonClickScript: func() begin AddDeferredAction(func() mView:ModalDialog(), '[]); end, ...} ModalDialogView := {... viewclass: clView, viewflags: vApplication + vClickable, viewFormat: vfNone, viewJustify: vjParentFullH + vjParentFullV, viewBounds: SetBounds(0, 0, 0, 0), // so that the Close button knows who to close declareSelf: 'base, ...}

Making Modal Views

2-69

CHAPTER

Views

CloseModalButton := {... // child of the modal view _proto: prototextbutton text: "Close me", buttonClickScript: func() begin // closes ModalDialogView (identified as base) base:Close(); end, ...}

Finding the Bounds of Views


The following functions and view methods calculate and return a viewBounds frame. A viewBounds frame looks like this: {left: leftValue , top: topValue , right: rightValue, bottom: bottomValue } RelBounds RelBounds(left, top, width, height) Returns a viewBounds frame, if you know the top-left coordinate and the width and height of the view. This function calculates the right and bottom values and returns a bounds frame. The value returned would be used for the value of the viewBounds slot in a template. left top width height The left coordinate of the view. The top coordinate of the view. The width of the view. The height of the view.

2-70

Finding the Bounds of Views

CHAPTER

Views

SetBounds SetBounds(left, top, right, bottom) Returns a viewBounds frame when supplied with the four bounds values. The value returned would be used for the value of the viewBounds slot in a template. left top right bottom GlobalBox view:GlobalBox() Returns the rectangle, in global coordinates, of the specied view. The rectangle is returned in a viewBounds frame. If a valid view is not found, this method returns nil.
Note

The left coordinate of the view. The top coordinate of the view. The right coordinate of the view. The bottom coordinate of the view.

This function wont work if used in the viewSetupFormScript method of a view because the view bounds have not yet been set up. u LocalBox view:LocalBox() Returns a viewBounds frame containing the view bounds relative to the view itself. That is, the top left coordinates are both zero, the right coordinate is the width of the view, and the bottom coordinate is the height of the view.
Note

This function wont work if used in the viewSetupFormScript method of a view because the view bounds have not yet been set up. u

Finding the Bounds of Views

2-71

CHAPTER

Views

ButtonBounds ButtonBounds(width) Returns a viewBounds frame when supplied with the width of a button to be placed in the status bar. You can use this return value for the value of the button viewBounds slot. width The width of the button to place in the status bar.

For the rst button you place in the status bar, specify the width as a negative number. For example, if you want the button to be 30 pixels wide, specify 30. This signals that this is the rst button, and the bounds are calculated to place it at a standard offset (36 pixels) from the left side of the status bar. For subsequent buttons that you place in the same status bar, specify the width as a positive number. For subsequent buttons, you must also use the viewJustify flag vjSiblingRightH.
Note

This function is available in the Newton Toolkit development environment at compile time only. It is not available at run time. u PictBounds PictBounds(name , left, top) Returns a viewBounds frame for views containing pictures. This function opens the picture resource, nds the width and height of the picture and returns the proper bounds frame. The value returned would be used for the value of the viewBounds slot in a template. name left top A string that is the name of a PICT resource. The left coordinate of the view. The top coordinate of the view.

2-72

Finding the Bounds of Views

CHAPTER

Views

Note

This function is available in the Newton Toolkit development environment at compile time only. It is not available at run time. u

Animating Views
There are four view methods that perform special animation effects on views. They are summarized here:
n

Effect (performs any animation that can be specified in the viewEffect slot) SlideEffect (slides a whole view or its contents up or down) RevealEffect (slides part of a view up or down) Delete (crumples a view and tosses it into a trash can)

n n n

Note that these animation methods only move bits around on the screen. They do not change the actual bounds of a view, and they do not do anything to a view that would change its contents. When you use any of these methods, you are responsible for supplying another method that actually changes the view bounds or contents. Your method is called just before the animation occurs. These functions are described in detail in this section. Effect view:Effect(effect, offScreen, sound , methodName, methodParameters) Posts a message to the specied view to redraw it with an animation. However, the system does not actually do the animation until after it calls the method that you specify, in which you can do any operations required before the animation is done. For example, you might want to animate a view as you change its contents.

Animating Views

2-73

CHAPTER

Views

effect

Species an animation effect. You can specify any of the effect constants that are used in the viewEffect slot (described in the section Opening and Closing Animation Effects beginning on page 2-34 in this chapter). Species whether or not the view should appear to animate off of or onto the screen. Specify true to make the animation appear as if the view is moving off of the screen. Specify nil to make the animation appear as if the view is moving onto the screen. The name of a sound frame containing a sound that you want played concurrently with the animation. (If you don't want a sound, specify nil.) The method that you want called before the animation occurs. You must specify a symbol (for example, 'myScript). This method must be accessible from the view to which the Effect message is sent; that is, this method must reside in that view or be accessible from that view through inheritance. An array of parameters that are passed to your method.

offScreen

sound

methodName

methodParameters

The Effect method always returns nil. Here is an example of using this method. aView := {... doEffect: func() begin view1:Effect(fxZoomVerticalEffect, nil, ROM_plunk, 'effectScript,[]); end, ...} view1 := {... text: "",

2-74

Animating Views

CHAPTER

Views

effectScript: func() begin SetValue(view1, 'text, "This is a paragraph view..."); end, ...} SlideEffect view:SlideEffect(contentOffset, viewOffset , sound, methodName , methodParameters) Posts a message to the specied view to perform a vertical sliding animation on it. However, the system does not actually do the animation until after it calls the method that you specify, in which you can do any operations required before the animation is done. contentOffset The number of pixels to animate the view contents scrolling in a vertical direction. A positive number makes the view contents appear to move downwards. A negative number makes the view contents appear to move upwards. Note that only the bits on the screen are moved; the location of the actual view data is not affected. The number of pixels to animate the whole view moving up or down on the screen. Specify a positive number to make the view appear to move up on the screen. (This is the effect you get in Names, when you change from showing a Card to showing Card & Notesthe view expands upward to show more.) To make the view appear to move down, specify a negative number. If you dont want to make the view appear to move, but just want to scroll its contents, specify zero. (This is the effect you get in Dates, when you tap a scroll arrow to scroll the hours within a day.)

viewOffset

Animating Views

2-75

CHAPTER

Views

sound

The name of a sound frame containing a sound that you want played concurrently with the animation. (If you don't want a sound, specify nil.) The method that you want called before the animation occurs. You must specify a symbol (for example, 'myScript). This method must be accessible from the view to which the SlideEffect message is sent; that is, this method must reside in that view or be accessible from that view through inheritance. An array of parameters that are passed to your method.

methodName

methodParameters

The SlideEffect method always returns nil. Note that this method does not actually change the bounds of the view or the position of its contents. The bits are moved on the screen, but that is all that is done. If you want to change the bounds or the position of the contents, you must do so in the method that you supply. To animate a view scrolling in place, without changing its size, specify a positive or negative contentOffset and zero for viewOffset (for example, -50, 0). To slide a view up from the bottom, showing more of it, but keeping the data that was near the top still near the top, specify a negative contentOffset and a viewOffset that is the same as offset, but positive (for example, -50, 50). To shrink the view back down, specify a positive contentOffset and a negative viewOffset (for example, 50, -50). Here is an example of using this method. aView := {... slideUp: func() begin local amount := 100; view1:SlideEffect(-amount, amount, ROM_flip, 'myEffect, ['up, amount]); end,

2-76

Animating Views

CHAPTER

Views

slideDown: func() begin local amount := 100; view1:SlideEffect(amount, -amount, ROM_flip, 'myEffect, ['down, -amount]); end, ...} view1 := {... myEffect: func(direction, amount) begin local bounds := self.viewbounds; //copy viewbounds If direction = 'up then begin // only top needs changing bounds.top := bounds.top-amount; SetValue(view1, 'viewbounds, bounds); end Else // direction is down begin // only top needs changing bounds.top := bounds.top-amount; SetValue(view1, 'viewbounds, bounds); end end, ...} RevealEffect view:RevealEffect(distance, bounds, sound, methodName , methodParameters) Posts a message to the specied view to perform a revealing animation on it. However, the system does not actually do the animation until after it calls the method that you specify, in which you can do any operations required before the animation is done.

Animating Views

2-77

CHAPTER

Views

distance

The number of pixels to animate a portion of the view moving up or down on the screen. Specify a positive number to make the view portion appear to move upward on the screen this number of pixels. To make the view portion appear to move downward, specify a negative number. The distance parameter should be the height of the view content you want to reveal (or hide). The partial area of the view that you want to animate moving up or down. You should specify a viewBounds frame using coordinates local to the view to which you are sending this message. The portion of the view that you specify is copied above or below its present position, depending on the setting of distance. The name of a sound frame containing a sound that you want played concurrently with the animation. (If you don't want a sound, specify nil.) The method that you want called before the animation occurs. You must specify a symbol (for example, 'myScript). This method must be accessible from the view to which the RevealEffect message is sent; that is, this method must reside in that view or be accessible from that view through inheritance. An array of parameters that are passed to your method.

bounds

sound

methodName

methodParameters

A revealing effect is like a slide effect, except that it slides just a portion of the view either up or down, while leaving the rest of the view in place. This can be used to create an effect that reveals new information where the portion of the view moved from. The method you specify as a parameter should set up the new information to be revealed so that when the view is redrawn, the new information is visible. The RevealEffect method always returns nil. Here is an example of using this method.

2-78

Animating Views

CHAPTER

Views

aView := {... revealMore: func() // move view portion downwards begin local vb := view1:LocalBox(); vb.top := 60; vb.bottom := 80; view1:RevealEffect(40,vb,ROM_flip,'myEffect,['dn]); end, closeUp: func() // move view portion upwards begin local vb := view1:LocalBox(); vb.top := 60; vb.bottom := 120; view1:RevealEffect(-40,vb,ROM_flip,'myEffect,['up]); end, ...} view1 := {... myEffect: func(direction) begin If direction = 'up then // revealing less begin // Here you would change the view contents so it // removes that portion being hidden ... end Else // revealing more begin // Here you would change the view contents so it // includes the "revealed" information ... end end, ...}

Animating Views

2-79

CHAPTER

Views

Delete view:Delete(methodName, methodParameters) Posts a message to the specied view to perform an animation on it that crumples it and tosses it into a trash can that appears on the screen. The view is not actually deletedonly the animation is done. methodName The method that you want called before the animation occurs. You must specify a symbol (for example, 'myScript). This method must be accessible from the view to which the Delete message is sent; that is, this method must reside in that view or be accessible from that view through inheritance. An array of parameters that are passed to your method.

methodParameters

The Delete method always returns nil. If you want to delete the view or remove the data shown in it, you must do these things yourself in the method you supply. For example, the view may be showing an item from a soup. When the Delete animation is performed, you would typically want to clear the data from the view and possibly delete the data from the soup also. Alternatively, you might want to close the view. Here is an example of using this method. aView := {... // call Delete method doDeleteEffect: func(whatData) textView:Delete('myDelete, [whatData]); ...} parent_of_textView := {... myDelete: func(what) begin EntryRemoveFromSoup(whatData); //remove data from soup textview:Close(); // close the view being deleted end, ...}

2-80

Animating Views

CHAPTER

Views

Dragging a View
Dragging a view means allowing the user to move the view by tapping on it, holding the pen down, and dragging it to a new location on the screen. To drag a view, send the view a Drag message. Drag view:Drag(unit, dragBounds) This method is typically called from within a viewClickScript method. It tracks the pen on the display, and drags the view to follow it. unit dragBounds The current stroke unit passed by the viewClickScript message. A viewBounds frame describing the area, relative to the root view, within which the view can be dragged. If dragBounds is nil, the bounds of the root view (the entire screen) limit the dragging area.

This method always returns true. The display of electronic ink is turned off during the dragging operation.
Note

Because of a bug in the Drag method, after the method executes, the viewBounds slot of the view contains incorrect values. You need to x up the bounds to the correct values. The technique for doing this is shown in the following example. u Here is an example of using this view method: draggableView :={... viewFlags: vVisible + vClickable,

Dragging a View

2-81

CHAPTER

Views

viewClickScript: func(unit) begin local limits; limits := SetBounds(5,50, 230, 305); :Drag(unit, limits); // Need to clean up viewBounds values with this code // This code works only for views justified to the // top and left of their parent view local ParentBounds, myBounds; myBounds := :GlobalBox(); ParentBounds := :Parent():GlobalBox(); myBounds.left := myBounds.left - ParentBounds.left; myBounds.top := myBounds.top - ParentBounds.top; myBounds.right := myBounds.right - ParentBounds.left; myBounds.bottom:= myBounds.bottom - ParentBounds.top; self.viewBounds := myBounds; true; // return true because we've handled the tap end, ...}

Scrolling View Contents


There are different methods of scrolling a view, supported by view methods you call to do the work. Both methods described here operate on the child views of the view to which you send a scroll message. One method is used to scroll all the children of a view any incremental amount in any direction, within the parent view. Use the SetOrigin method to perform this kind of scrolling. The SetOrigin method changes the view origin by setting the values of the viewOriginX and viewOriginY slots in the view.

2-82

Scrolling View Contents

CHAPTER

Views

Another kind of scrolling is used for a situation in which there is a parent view containing a number of child views positioned vertically, one below the other. The SyncScroll method provides the ability to scroll the child views up or down the height of one of the views. This is the kind of scrolling you see on the built-in Notepad application. In this latter kind of scrolling, the child views are simply redrawn within the parent view by changing their view bounds. The viewOriginX and viewOriginY slots are not used. For information about techniques you can use to optimize scrolling so that it happens as fast as possible, see the subsection Scrolling beginning on page 2-108, in the section Optimizing View Performance. SetOrigin view:SetOrigin(originX , originY) Changes the view bounds offset to reect the new origin point, if it is different from the current origin, and dirties the view (so you dont have to send it the Dirty message). originX originY The X coordinate of the new view origin. The Y coordinate of the new view origin.

This method always returns nil. This method scrolls the child views of the view to which you send the SetOrigin message. The following table shows what parameters to pass to SetOrigin to scroll the child views in different directions:
originX originY Visual direction Scroll direction

zero zero positive negative

positive negative zero zero

Up Down Left Right

Down Up Right Left

This method sets the viewOriginX and viewOriginY slots in the view to the new values you specify.

Scrolling View Contents

2-83

CHAPTER

Views

The view origin determines where, within the view bounds, the actual view contents (child views) are displayed. Initially, the view origin is set to (0, 0). This means that the top left corner of the view contents (point (0, 0)) is positioned at the top left corner of the view bounds. If you change the view origin, the view contents are positioned so that the point you specify as the origin is placed at the top left corner of the view bounds. Thus, the contents are offset within the view. The current view origin coordinates are stored in the slots viewOriginX and viewOriginY within the view. When using SetOrigin to scroll a view, you typically want the contents of the view to be clipped to some particular area. For example, you might want to scroll a large map around within a view so that the user can see different parts of the map within the same view. To get this effect, make the parent view smaller than the child (the map, for example) that you want to scroll. The parent view should be as big as the part of the child you want to show at one time. Set the vClipping ag in the viewFlags slot of the parent view. When you send the SetOrigin message to the parent view, the child view will scroll and be clipped to the bounds of its parent view. Figure 2-10 shows an example of a world map before and after it has been scrolled. The map is enclosed in a parent view which is the rectangle around the map. The map was scrolled to the right with this code: parentView:SetOrigin(40,0).
Figure 2-10 SetOrigin example

Before Scrolling

After Scrolling Right

2-84

Scrolling View Contents

CHAPTER

Views

Here is an example of using this view method: ParentView := {... viewFlags: vVisible+vClipping, viewOriginX: 0, viewOriginY: 0, ...} ScrollRightButton := {... buttonPressedScript: func() begin parentView:setOrigin(parentView.viewOriginX+20, 0); RefreshViews(); end, ...} SyncScroll view:SyncScroll(what, index, upDown ) Scrolls the child views of a view vertically the increment of one child view in the direction indicated. what You can specify either an array or a soup cursor, depending on what kind of data is contained in the view you want to scroll. If all of the view children are contained in an array, then specify the array. If your view data consists of child views created from soup entries, then specify the soup cursor. Only used if you specify an array for what. This is the index of the child view in that array that is currently displayed at the top of the parent view that you are scrolling. Set to 1 to scroll up (visually, the views move downward on the screen), or set to 1 to scroll down (visually, the views move upward on the screen).

index

upDown

Scrolling View Contents

2-85

CHAPTER

Views

This method has different return values, depending on what you specify for what. If you specify an array, this method returns a new array of the child views that are visible within the parent view after scrolling; or, if there is nothing to scroll, nil is returned. If you specify a cursor, this method always returns nil. This method plays a scroll up or a scroll down sound effect, depending on which way the views are scrolling. The sound effect should be stored in the scrollUpSound or scrollDownSound slot of the view, respectively. A slot named height is required in each of the child views (or soup entries, if you are working with a cursor). This slot should contain the height of the view in its normal (expanded) state. The following information applies only if you specify an array for what.
n

This method uses two optional slots in the parent view: allCollapsed and collapsedHeight. These slots are used to control scrolling when the child views have both expanded and collapsed modes (such as in the notepad roll). The allCollapsed slot should hold a true value if all of the child views are in the collapsed mode, or a nil value if all of the child views are not collapsed. The collapsedHeight slot holds the standard height in pixels of a collapsed view. This method also uses one specic slot in each of the child views: collapsed. If there is a collapsed slot in a child view, and it holds a true value, the individual child view is assumed to be in the collapsed state.

The following information applies only if you specify a soup cursor for what.
n

This method may or may not move the cursor forward or backward in the soup. Scrolling does not always require advancing to the next or previous view, in which case the cursor would not be changed. For example, a single data item may be longer than the screen space allocated for it in a view, and so tapping the scroll arrow should scroll the view rather than advance to the next data item. In this case, the soup cursor would not be advanced since a new item need not be retrieved from the soup as a result of scrolling.

2-86

Scrolling View Contents

CHAPTER

Views

Before the scrolling animation is done and the views are redrawn, the viewSetupChildrenScript message is sent to the view that is being scrolled. The view being scrolled should use the viewSetupChildrenScript method to recalculate its stepChildren array so that the correct views are displayed when they are redrawn by the SyncScroll method.

Working With View Highlighting


A highlighted view is identied visually by being inverted. That is, black and white are reversed. To highlight or unhighlight a view, send the view the Hilite message. To highlight or unhighlight a single view from a group, send the view the HiliteUnique message. (The group is defined as all of the child views of one parent view.) To highlight a view when the current pen position is within it, send the view the TrackHilite message. The view is unhighlighted when the pen moves outside the view bounds or when it is lifted. If the view is a button, you can send the view the TrackButton message to accomplish the same thing. The view is also sent the buttonClickScript message if the pen is lifted inside the button. To get the view containing highlighted data, you can call the global function HiliteOwner, and to get the highlighted text you can use GetHiliteOffsets. To hilite some or all of the text in a paragraph, you can use the SetHilite method. These methods and functions are described in the following paragraphs.

Working With View Highlighting

2-87

CHAPTER

Views

Hilite view:Hilite(on) Highlights or unhighlights a view. on If true, highlights the view if it is not already highlighted; if nil, the view is unhighlighted.

This method always returns true. HiliteUnique view:HiliteUnique(on) Highlights or unhighlights a single view in a group of views. on If true, highlights the view; if nil, the view is unhighlighted.

This method always returns true. The view you specify will be the only view highlighted in its sibling group. That is, any other child views of the same parent that happen to be highlighted are unhighlighted, so that only a single view is highlighted at a time. TrackHilite view:TrackHilite(unit) This method is typically called from within a viewClickScript method. It tracks the pen on the display, highlighting the view when the pen is within its bounds, and unhighlighting the view when the pen is outside of it. unit The current stroke unit passed to you in the viewClickScript method.

This method returns true if the pen is lifted within the view bounds or nil if the pen is lifted outside the view bounds. This method repeatedly sends the buttonPressedScript message to the view while the pen is down and within the view bounds. The display of electronic ink is turned off while the pen is tracked.

2-88

Working With View Highlighting

CHAPTER

Views

TrackButton view:TrackButton(unit) Performs the same operations as TrackHilite, but protects against leaving the button highlighted if an error occurs. (The button is unhighlighted if an error occurs during the tracking.) unit The current stroke unit passed to you in the viewClickScript method.

This function internally calls TrackHilite. It returns true if the pen is lifted within the view bounds or nil if the pen is lifted outside the view bounds. Unlike TrackHilite, however, this function sends the buttonClickScript message to the view if the pen is lifted within the view bounds of the button. HiliteOwner HiliteOwner() Returns the view containing highlighted data. If there is more than one view containing highlighted data, the common parent of those views is returned. However, only one application at a time can have highlighted data. This function returns nil if no views contain highlighted data. This function works only with views of the class clEditView or clParagraphView. Views of the class clEditView can contain highlighted text or polygon data. Views of the class clParagraphView can contain only highlighted text. GetHiliteOffsets GetHiliteOffsets() Returns an array of arrays containing information about views that have highlighted data. The return value looks like this: [[view, start, end], [view, start, end], ...]

Working With View Highlighting

2-89

CHAPTER

Views

Each subarray contains information about one highlight. The rst value, view, is the view containing the highlight. The second value, start, is the starting character position of the highlight. A character position of zero indicates the beginning of the view, a position of one is after the rst character, and so on. The third value, end, is the ending character position of the highlight. A view can have only one range of highlighted characters. Discontiguous highlights within a view are not supported. Only one application at a time can have views with highlighted data; so all views returned by this function will belong to the same application. This function works only with views of the class clParagraphView. Other kinds of views containing highlighted data (views of the class clPolygonView, for example) will not be returned. SetHilite view:SetHilite(start, end, unique) Highlights some or all of the text in a view of the class clParagraphView. start The starting character position of the highlight. A character position of zero indicates the beginning of the view, a position of one is after the rst character, and so on. The ending character position of the highlight. A Boolean value. Specify true to make the specied text the only highlighted text in the view; any other highlighted text is unhighlighted. Specify nil to allow previously highlighted text to stay highlighted. In the later case, the highlighted is extended to include the newly specied highlighted text. Discontiguous highlights are not allowed.

end unique

This function returns true, unless view is invalid, in which case nil is returned.

2-90

Working With View Highlighting

CHAPTER

Views

Creating View Dependencies


You can make one view dependent upon another by using the global function TieViews. The dependent view is notied whenever the view it is dependent on changes. This dependency relationship is set up outside the normal inheritance hierarchy. That is, the views dont have to be related to each other in any particular way in the hierarchy. However, both views must be declared in a common view in their parent chain. This is required so that the views can access each other. TieViews TieViews(mainView , dependentView, methodName) Makes one view dependent on another so that when the main view changes, it noties the dependent view by sending a message to the dependent view. mainView dependentView methodName The main view. The view that you want to be notied when mainView changes. A symbol that is the name of the method to call in dependentView when mainView changes. This method is passed two parameters when it is called. The rst parameter is a reference to the view that changed and the second parameter is a symbol that is the name of the slot that changed.

This function returns true if it successfully registers the dependent view with the main view, otherwise, it returns nil.

Creating View Dependencies

2-91

CHAPTER

Views

You can pass in the following special symbols (which are evaluated at run time) for either the mainView or dependentView parameters:
n

'viewFrontMost, to indicate the frontmost view on the screen that has the vApplication ag set in its viewFlags slot 'viewFrontMostApp, to indicate the frontmost view on the screen that has the vApplication ag set in its viewFlags slot, but not including oating views (those with vFloating set in their viewFlags slot) 'viewFrontKey, to indicate the view on the screen that accepts keys (there can be only one view that is the key receiver)

TieViews creates a slot named viewTie in the main view. Its value is an array containing a pair of elements (one pair for each dependent view). The rst element in the pair is a reference to the dependent view and the second element is a symbol that is the name of the method to call in that view. The viewTie slot is used by the system to check for and locate dependent views. Here is an example of two views of the clParagraphView class. Any text entered in the rst view is duplicated in the second. mainView := {... viewClass: clParagraphView, viewFlags: vVisible+vClickable+vStrokesAllowed+ vGesturesAllowed+vCharsAllowed, viewSetupFormScript: func() begin TieViews(mainView, tieView, 'ItChanged); end, ...} tieView := {... viewClass: clParagraphView, viewFlags: vVisible, ItChanged: func(view, slot) begin local newtext := view.text; setvalue(self, 'text, newtext); end, ...}

2-92

Creating View Dependencies

CHAPTER

Views

View Synchronization
View synchronization refers to the process of synchronizing the graphical representation of the view with its internal data description. You need to do this when you add, delete, or modify the children of a view, in order to update the screen. Typically you would add or remove elements from the stepChildren array of a parent view, and then call one of the view synchronization functions to cause the child views to be redrawn, created, or closed, as appropriate. Remember that if you need to modify the stepChildren array of a view, the array must be copied into RAM; you cant modify the array in the view template, since that is usually stored in ROM. To ensure that the stepChildren array is in RAM, use this code: if not HasSlot(self, 'stepChildren) then self.stepChildren := Clone(self.stepChildren); To redraw all the child views of a view, you can send two different messages to a view: RedoChildren or SyncChildren. These work similarly, except that RedoChildren closes and reopens all child views, while SyncChildren only closes obsolete child views and opens new child views. These view methods are described in the following paragraphs. RedoChildren view:RedoChildren() Closes then reopens and redraws all of a view's child views. This method always returns true. As a result of the RedoChildren message, the following system actions occur: 1. The child views are sent viewQuitScript messages, and then they are closed.

View Synchronization

2-93

CHAPTER

Views

2. The parent view (the view to which you sent the RedoChildren message) is sent the viewSetupChildrenScript message, and the child templates are reread from the viewChildren and stepChildren slots of the parent view. 3. The child views are reopened, and in this process are sent the following messages: viewSetupFormScript, viewSetupChildrenScript, viewSetupDoneScript. 4. The parent view, and then the child views, are drawn and then are sent the viewDrawScript message. For more information about system messages, refer to Chapter 5, Handling System Messages. Note that because the RedoChildren method closes child views, any new data that you have stored in those views during run time will be lost. For example, if you have created a slot in a child view and stored a value in it, that slot and value will be lost when the view is closed and reopened. The view is reopened directly from its template, so of course, any data that was in the view memory object in RAM is lost. However, if a child view is declared in a view that is still open (typically the parent view), then, even though the child view is closed, its view memory object is not destroyed and any data stored in the view is preserved. This is the same as when you send the Close message to a declared view. For more information about declared views, see the section View Instantiation beginning on page 2-41. Because the RedoChildren method closes and reopens all child views, it is relatively slow. If you know that some of the child views are still visible within the parent, you can use SyncChildren instead, which will give better performance since it doesn't close views that are still visible. Here is an example of using the RedoChildren method: {... someFunction: func() self:RedoChildren(); ...}

2-94

View Synchronization

CHAPTER

Views

SyncChildren view:SyncChildren() Redraws all of a view's child views, with their new bounds, if the bounds have changed. This method always returns true. As a result of the SyncChildren message, the following system actions occur: 1. The viewSetupChildrenScript message is sent to the view to which the SyncChildren message was sent. 2. The child views are synchronized with the stepChildren and viewChildren arrays of the parent view to which this message was sent. If a view is no longer listed in the stepChildren or viewChildren array, then the viewQuitScript message is sent to it and it is closed. If a new view template is listed in one of these arrays, then the new child view is created and opened. As a result of its opening, the new view is sent the usual messages: viewSetupFormScript, viewSetupChildrenScript, and viewSetupDoneScript. 3. Internally, the system does a SyncView for each of the child views. As a result, the viewSetupFormScript message is sent to each child view, and each view whose bounds has changed is redrawn. Note that if a new child view is created, it will receive the viewSetupFormScript message twice, once in step 2 and once in step 3. The view to which you send the SyncChildren message is not dirtied. Usually this is not a problem, except in one case, in which you must send the view the Dirty message to cause it to be redrawn. If a child view is closed in step 2 and another child view is not drawn completely over it, the old child view will still be visible. Here is an example of using the SyncChildren method: {... addOneChild: func(childTemplate) begin // ensure that stepChildren array is in RAM

View Synchronization

2-95

CHAPTER

Views

if not HasSlot(self, 'stepChildren) then self.stepChildren := Clone(self.stepChildren); // add new template into the array AddArraySlot(self.stepChildren, childTemplate); // sync up the views self:SyncChildren(); end ...}

Laying Out Multiple Child Views


Three different methods are provided to help lay out a view that is a table or consists of some other group of child views. To lay out a view containing a table in which each cell is a child view, send the view the message LayoutTable. To lay out a view containing a vertical column of child views, you send the view the message LayoutColumn. These methods are described in the following paragraphs. LayoutTable view:LayoutTable(tableDefinition, columnStart, rowStart) Generates a table where each cell is a child of the parent view to which this message is sent. This method essentially calculates the bounds for each child view so that the children are laid out in a table-like format in the parent. tableDefinition columnStart A frame describing the table. The slots are described below. The column number of the cell that should be placed in the upper-left corner of the parent view. Specify an integer from zero (for the rst column) to one less than the total number of columns.

2-96

Laying Out Multiple Child Views

CHAPTER

Views

rowStart

The row number of the cell that should be placed in the upper-left corner of the parent view. Specify an integer from zero (for the rst row) to one less than the total number of rows.

This method returns an array of child templates that can be used as the value of the stepChildren slot in the parent template. If you send this message to a template or an invalid view, it returns nil. The viewBounds slots of the children are calculated so that the rst child is placed in the upper-left corner of the parent view. You can use the columnStart and rowStart parameters to change which child is the first child. By using these parameters to specify a different upper-left cell, you can display just a portion of the entire table. For example, to generate templates for all of the cells in a table, specify 0, 0 for columnStart and rowStart. This places the top left cell in the table in the top left corner of the parent view. This is illustrated in the rst view shown in Figure 2-11. To offset the table upwards and to the left, specify 1, 1. This places the second cell in the second row in the top left corner of the parent view. This is illustrated in the second view shown in Figure 2-11. Note, however, that cells are laid out sequentially beginning with the indicated cell. That is, cells 5 through 10 are all shown. The table isnt simply shifted up and to the right. Templates are not generated for cells that precede the starting cell. The rst template in the array returned by LayoutTable is the template for the rst cell indicated by columnStart and rowStart.
Figure 2-11 LayoutTable Results

The columnStart and rowStart parameters are set to 0, 0

The columnStart and rowStart parameters are set to 1, 1

Laying Out Multiple Child Views

2-97

CHAPTER

Views

TableDenition slots

tabAcross tabDown tabWidths tabHeights tabProtos

tabValues

tabValueSlot

tabSetup

The number of columns in the table The number of rows in the table An integer giving the xed width of the columns, in pixels, or an array of column widths An integer giving the xed height of the rows, in pixels, or an array of row heights A reference to a template used in creating the child views, or an array of references to templates. The array elements are mapped to the table of views beginning at the top-left cell of the table and continuing down the rst column, and then down the second column, and so on. If there are fewer array elements than table cells, after the last array element is mapped, the mapping continues with the rst element. A value that is used as the value of each of the child views. Alternately , an array of values that are mapped to table cells as above. A symbol naming the slot in each of the child views where its view value (specied in tabValues) is stored. (Remember to quote the symbol; as with 'text.) For example, if the table consists of child views based on the clParagraphView class, you would specify 'text for this slot, since the value of a clParagraphView is stored in the text slot. A method that is called before each of the child views is instantiated. It is passed three parameters: a reference to the child template, its column number in the table, and its row number in the table. This allows you to do special initialization operations to each child view before it is instantiated.

2-98

Laying Out Multiple Child Views

CHAPTER

Views

Here is an example of using the LayoutTable method. This example shows the code used to generate the rst table in Figure 2-11. {... viewclass: clView, viewBounds: {left: 42, top: 26, right: 193, bottom: 129}, tabAcross: 3, tabDown: 4, tabWidths: nil, tabHeights: nil, tabProtos:{viewclass: clParagraphView, viewBounds: nil, viewJustify: vjLeftH+vjCenterV+oneLineOnly, viewFlags: vVisible+vClickable, viewFormat: vfFillWhite+vfFrameBlack+vfPen(1), text:nil, viewFont: simpleFont10}, tabValues: nil, tabValueSlot: nil, viewSetupChildrenScript: func() begin local box, cells; box := self:localBox(); viewWidth := box.right - box.left; tabWidths := viewWidth DIV tabAcross; tabHeights := FontHeight(tabProtos.viewFont); tabValues := ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]; tabValueSlot := 'text; self.stepChildren := self:LayoutTable(self, 0, 0); end, ...};

Laying Out Multiple Child Views

2-99

CHAPTER

Views

LayoutColumn view:LayoutColumn(childViews , index) In the view to which this message is sent (the main view), LayoutColumn displays a subset of views from a larger array of views. childViews index The array of views from which you want to display a subset. The index of the view in the childViews array that you want to display at the top of the view to which you send this message.

This method returns a reference to an array of child views that ll the bounds of the main view, beginning with the view at index and containing as many subsequent views as it takes to ll the main view to the bottom. If the view to which this message is sent has not yet been instantiated, or if it is invalid, this method returns nil.

Working With Keyboard Views


This section describes the keyboard views built into the system and how to access them. Also described are functions and methods related to keyboard views. Built into the system root view are four different keyboards shown in Figure 2-12. You can access the built-in keyboards using these symbols:
n n n n

'alphaKeyboard for the full alphanumeric keyboard 'numericKeyboard for a number keyboard 'dateKeyboard for a keyboard that allows date and time entry 'phoneKeyboard for a keyboard that allows phone number entry

An on-screen keyboard can be opened by the user with a double tap on an input eld (as long as gestures are allowed). The kind of keyboard displayed is determined by what type of input is recognized by the eld. For example,

2-100

Working With Keyboard Views

CHAPTER

Views

Figure 2-12

Built-in Keyboards

Alpha Keyboard

Numeric Keyboard

Phone Keyboard

Date Keyboard

a eld in which only numbers are recognized would use the numeric keyboard. The user can also open a keyboard from the corrector pop-up list, shown when they are correcting a recognized word. If you want to open one of these keyboards programmatically, you can use code like this to send it the Open message: getroot().alphaKeyboard:open() The keystrokes entered by the user are sent to the current key receiver view. There can be only one key receiver at a time, and only views of the classes clParagraphView and clEditView can be key receiver views. When a keyboard is open, a blinking I-beam cursor is shown in the key receiver view at the location where characters will be inserted.

Working With Keyboard Views

2-101

CHAPTER

Views

The following paragraphs describe functions and methods related to keyboard views. SetKeyView SetKeyView(view, offset) Sets the view that is to receive keyboard input from an on-screen keyboard. view offset The view to receive keyboard input. The text caret (a blinking vertical line) is displayed at this character location. An offset of zero indicates the beginning of the view, an offset of one is after the rst character, and so on.

This function always returns nil. This function applies only to views of the class clEditView and clParagraphView. KeyboardInput view:KeyboardInput() Returns true if the view is the current key view (the view receiving keystrokes) and the keyboard is enabled (visible). Otherwise, this function returns nil. This method applies only to views of the class clEditView and clParagraphView. GetCaretBox GetCaretBox() Returns a bounds frame containing the global rectangle coordinates of the blinking text insertion caret, if it is displayed. If there is a text selection in a view, the caret is positioned before the rst character of the selection, though it may not be visible. If there is no text selection and the caret is not

2-102

Working With Keyboard Views

CHAPTER

Views

displayed, this function may still return a bounds frame giving the virtual position of the text caret. This is the last position of the caret when it was displayed, or the position where handwritten text would be inserted (usually immediately following existing text). If there is no key-receiving view, nil is returned. PostKeyString PostKeyString(view, keyString) Sends keystrokes to a view, as if they had been entered on a keyboard. view keyString The view to which to send keystrokes. A string containing the keystrokes to send.

This function always returns nil. KeyIn KeyIn(keyCode, down ) Allows you to programmatically change the state of the modier keys (Caps, Shift, and Option) on the alpha keyboard. keyCode The physical keycode of the key whose state you want to change. Caps Lock is 0x39, Shift is 0x38, and Option is 0x3A. Specify true to cause the equivalent of a key press. Specify nil to release the key.

down

The key will be highlighted on the alpha keyboard when the key is pressed ( down = true), and unhighlighted when the key is released (down = nil). Note that if the keyboard is open, you must send it the Dirty message after changing the key state in order for the visual change to occur. This is not necessary if you use the KeyIn function to change the key state before opening the keyboard.

Working With Keyboard Views

2-103

CHAPTER

Views

Miscellaneous View Operations


This section describes other miscellaneous view methods and functions. SetPopup view:SetPopup() After a view is shown, call this method to make the view a pop-up view; that is, a view that gets closed on the next pen tap (whether inside or outside of it). An example of where this feature is used is in the protoPicker view proto. This method always returns nil. Heres how you would typically call this method in your view template: viewSetupDoneScript: func() self:SetPopup(); GetViewFlags GetViewFlags(template) Returns the value of the viewFlags slot in the view corresponding to the specied template, or in the template itself, if its view has not yet been instantiated. template The template or view whose viewFlags slot you want to get.

You can pass in the following special symbols for the template parameter:
n

'viewFrontMost, to indicate the frontmost view on the screen that has the vApplication ag set in its viewFlags slot 'viewFrontMostApp, to indicate the frontmost view on the screen that has the vApplication ag set in its viewFlags slot, but not including oating views (those with vFloating set in their viewFlags slot)

2-104

Miscellaneous View Operations

CHAPTER

Views

'viewFrontKey, to indicate the view on the screen that accepts keys (there can be only one view that is the key receiver)

These symbols are evaluated at run time. Visible Visible(view) This function tests a view to see if it is visible or not. This function returns true if the view is visible or nil if the view is not visible. Note that a view can be open but not visible, so this function is not a valid test if a view is open. view The view that should be tested to see if it is visible.

You can pass in the following special symbols for the view parameter:
n

'viewFrontMost, to indicate the frontmost view on the screen that has the vApplication ag set in its viewFlags slot 'viewFrontMostApp, to indicate the frontmost view on the screen that has the vApplication ag set in its viewFlags slot, but not including oating views (those with vFloating set in their viewFlags slot) 'viewFrontKey, to indicate the view on the screen that accepts keys (there can be only one view that is the key receiver)

These symbols are evaluated at run time.

Optimizing View Performance


Drawing, updating, scrolling, and performing other view operations can account for a signicant amount of time used during the execution of your application. Here are some techniques you can use to help speed up the view performance of your application.

Optimizing View Performance

2-105

CHAPTER

Views

Using Drawing Functions


Use the drawing functions to draw lines, rectangles, polygons, and even text, in a single view, rather than creating these objects as several separate specialized views. This will increase drawing performance and reduce the system overhead used for each view you create. The drawing functions are described in the chapter Drawing.

View Fill
Many views need no ll color, so you may be inclined to set the ll color to none when you create such a view. However, its best to ll the view with white, if the view can be dirtied and if you dont need a transparent view. This will increase the performance of your application because when the system is redrawing the screen, it doesnt have to update views behind those lled with a solid color such as white. However, dont ll all views with white, since there is some small overhead associated with lls; only use this technique if the view is one that is usually dirtied.

Redrawing Views
A view is agged as dirty (needing redrawing) if you send it the Dirty message, or as a result of some other operation, for example, if you call the SetValue function for a view. All dirty views are redrawn the next time the system idle loop executes. Often this redrawing speed is sufcient since the system idle loop usually executes several times a second (unless a lengthly or slow method is executing). However, sometimes you want to be able to redraw a view immediately. The fastest way to update a single view immediately is to send it the Dirty message and then call the global function RefreshViews. In most cases, only the view you dirtied will be redrawn. If you call RefreshViews and there are multiple dirty views, performance can be signicantly slower, depending on where the dirty views are on the screen and how many other views are between them. In this case, what is

2-106

Optimizing View Performance

CHAPTER

Views

redrawn is the rectangle that is the union of all the dirty views (which might include many other non-dirty views). Also, if there are multiple dirty views that are in different view hierarchies, their closest common ancestor view is redrawn, potentially causing many other views to be redrawn needlessly. If you want to dirty and redraw more than one view at a time, it may be faster to send the Dirty message to the rst view, then call RefreshViews, send the Dirty message to the second view, then call RefreshViews, and so on, rather than just calling RefreshViews once after all views are dirtied. The performance is highly dependent on the number of views visible on the screen, the location of the dirty views, and their positions in the view heirarchy, so its best to experiment to nd the solution that gives you the best performance.

Memory Usage
Each view that you create has a certain amount of system overhead associated with it. This overhead exists in the form of frame objects allocated in a reserved area of system memory called the NewtonScript heap. The amount of space that a frame occupies is entirely dependent on the complexity and content of the view to which it corresponds. As more and more views are created, more of the NewtonScript heap is used, and overall system performance may begin to suffer as a result. This is not usually an issue with relatively simple applications. However, complex applications that have dozens of views open simultaneously may cause the system to slow down. If your application ts this description, try to combine and eliminate views wherever possible. Try to design your application so that it has as few views open at once as possible. This can increase system performance. You should also be aware of some important information regarding hidden and closed views and the use of memory. This information applies to any view that is hidden (it has been sent the Hide message) or to any declared view that is closed but where the view it is declared in is still open. In these cases, the view memory object for the view still exists, even though the view is not visible on the screen. If the hidden or closed view contains large data objects, these objects continue to occupy space in the NewtonScript heap. 2-107

Optimizing View Performance

CHAPTER

Views

You can reduce memory usage in the NewtonScript heap by setting to nil those slots that contain large objects and that you dont need when the view is hidden or closed. You can do this in the viewHideScript or viewQuitScript methods, and then reload these slots with data when the view is shown or opened again, using the viewShowScript or viewSetupFormScript methods. Again, the performance impact of these techniques is highly application-dependent and you should experiment to see what works best. Note that this information applies to the base view of your application, since it is automatically declared in the system root view. As long as it is installed in the Newton, slots that you set in the base view of your application will continue to exist, even after the application is closed. If you store large data objects in the base view of your application, you should set to nil those slots that arent needed when the application is closed, since they are wasting space in the NewtonScript heap. It is especially important to set to nil slots that reference soups and cursors, if they are not needed, since they use relatively much space. If your application is gathering data from the user that needs to be stored, store the data in a soup, rather than in slots in one of the application views. Besides, data stored in soups is protected, while slots in views are transient and will be lost during a system restart. For information on declaring views, refer to the section View Instantiation beginning on page 2-41. For information on storing data in soups, refer to the chapter Data Storage and Retrieval.

Scrolling
Scrolling the contents of a view can sometimes seem slow. Here are some techniques you can use to improve the speed:
n

Scroll multiple lines at a time, rather than just a single line at a time, when the user taps a scroll arrow. In general, reduce the number of child views that need to be redrawn, if possible. For example, make a list that is implemented as several paragraphs (separate views) into a single paragraph.

2-108

Optimizing View Performance

CHAPTER

Views

Set the view ll to white. For more information, see the subsection View Fill beginning on page 2-106

Summary of Functions and Methods


This section contains a summary of the functions and methods described in this chapter. Getting References to Views view:ChildViewFrames() view:Parent() GetRoot() GetView(template) Displaying, Hiding, and Redrawing Views view:Open() view:Close() view:Toggle() view:Show() view:Hide() view:Dirty() RefreshViews() SetValue(view, slotSymbol , value) view:SyncView() Dynamically Adding Views AddStepView(parentView, childTemplate) RemoveStepView(parentView, childView) BuildContext(template) DoPopup(list, insetH, insetV , notifyView)

Summary of Functions and Methods

2-109

CHAPTER

Views

Making Modal Views rootView:Confirm(titleStr, message, methodView, method ) view:ModalDialog() Finding the Bounds of Views RelBounds(left, top, width, height) SetBounds(left, top, right, bottom) view:GlobalBox() view:LocalBox() ButtonBounds(width) PictBounds(name , left, top) Animating Views view:Effect(effect, offScreen, sound , methodName, methodParameters) view:SlideEffect(contentOffset, viewOffset , sound, methodName , methodParameters) view:RevealEffect(distance, bounds, sound, methodName , methodParameters) view:Delete(methodName, methodParameters) Dragging a View view:Drag(unit, dragBounds) Scrolling View Contents view:SetOrigin(originX , originY) view:SyncScroll(childViews , index, upDown) Working With View Highlighting view:Hilite(on) view:HiliteUnique(on) view:TrackHilite(unit) view:TrackButton(unit) HiliteOwner() GetHiliteOffsets() view:SetHilite(start, end, unique)

2-110

Summary of Functions and Methods

CHAPTER

Views

Creating View Dependencies TieViews(mainView , dependentView, methodName) View Synchronization view:RedoChildren() view:SyncChildren() Laying Out Multiple Child Views view:LayoutTable(tableDefinition, columnStart, rowStart) view:LayoutColumn(childViews , index) Working With Keyboard Views SetKeyView(view, offset) view:KeyboardInput() GetCaretBox() PostKeyString(view, keyString) KeyIn(keyCode, down ) Miscellaneous View Operations view:SetPopup() GetViewFlags(template) Visible(view)

Summary of Functions and Methods

2-111

CHAPTER

Working With Proto Templates

There are several proto templates (or protos) built into the system, which you can use in creating your own templates. This chapter describes these built-in protos. Templates that you create inherit attributes and behavior from their protos. For example, one proto used throughout the system, and one that you will probably want to use, is the close box. This proto denes a simple picture view that is the close box. Its click-handling method sends the Close message to the view identied as base. Here is the NewtonScript frame that denes the close box proto: protoCloseBox := { _proto: protoPictureButton, viewJustify: vjParentBottomV+vjParentRightH, viewBounds: PixBounds(goAwayBitmap, -14, -14), viewFormat: 0, icon: goAwayBitmap, buttonClickScript: func() base:Close(), debug: "protoCloseBox", }

3-1

CHAPTER

Working With Proto Templates

When you create a template based on the close box proto, your template inherits all of the slots in the proto, thus all of its attributes and behavior. To use protos in creating your own templates, you select them from a palette in the Newton ToolKit. You can also use them programmatically, by specifying the proto name in the _proto slot of a template you write. The protos described in this chapter are built into the system. You can also create your own custom protos; for more information see the section Creating Custom Protos beginning on page 3-93. When using most protos, the instantiator (the template referencing the proto) must set the value of particular slots that exist in the proto as place holders. These slots set such things as the view bounds, the text of buttons, event handling methods, and so on. In each proto description that follows, the slots that must be set by the instantiator are listed, along with other optional slots. For more information about the slots containing general view-related information (viewBounds, viewFlags, viewFormat, and so on) refer to the section Dening View Characteristics beginning on page 2-9. In that section, you can also nd the numeric equivalents to all of the attribute constants (such as vVisible, vjParentCenterH, vfFillWhite and so on). Font constants are listed in Table 4-2 on page 4-12.
Note

If, in using any of the system protos, you need to programmatically add child views (from within a method), you must do this in the stepChildren slot of the parent view. Do not modify the viewChildren slot, if one exists. Modifying the viewChildren slot will cause any predefined child views of the proto to be deleted. u The protos described in this chapter are grouped into the following sections:
n n n

Container protos Input protos Control protos

3-2

CHAPTER

Working With Proto Templates

n n

Roll protos Miscellaneous protos

Within each section, the protos are listed in alphabetical order.

Container Protos
The protos described in this section serve primarily as containers. They have little or no predened content. You must supply content in the form of child templates added to the parent template.

protoApp
This proto is used to create a typical application view. It is simply a view with a title at the top and a status bar at the bottom. The user can tap on the clock icon to see the current time, or on the close box to close the application. Here is an example:

Container Protos

3-3

CHAPTER

Working With Proto Templates

These slots are of interest: title A string that is the title. This title appears in a title bar at the top of the view. viewBounds Set to the size and location where you want the view to appear. By default it is centered horizontally within its parent view. viewFlags The default setting is vVisible + vApplication. Do not change these ags, but you can add others if you wish. viewJustify Optional. The default setting is vjParentCenterH. viewFormat Optional. The default setting is vfFillWhite + vfFrameBlack + vfPen(1) + vfInset(1) + vfShadow(1). declareSelf Do not change. This slot is set by default to 'base. This identies the view to be closed when the user taps the close box. The protoApp is based on a view of the clView class. It has the following two child views:
n n

A title, itself based on the protoTitle proto. A status bar, itself based on the protoStatus proto.

Here is an example of a template using protoApp: myApp := {... _proto: protoApp, title: "My Application", // set bounds relative to screen size viewSetupFormScript: func() begin local b := GetAppParams(); self.viewBounds.top := b.appAreaTop + 2; self.viewBounds.left := b.appAreaLeft; self.viewBounds.bottom := b.appAreaHeight - 7; self.viewBounds.right := b.appAreaWidth - 21; end ...}

3-4

Container Protos

CHAPTER

Working With Proto Templates

IMPORTANT

If you want to place buttons on the status bar of your application base view (and that is the recommended place for buttons), we recommend that you create your own application base view from scratch, instead of using protoApp. This is because you dont have access to the status bar in protoApp, so you cant add buttons to it. You can use a view of the class clView as your application base view. Be sure to set vApplication in the viewFlags slot, and include a declareSelf slot whose value is the symbol 'base (so the close button closes the right view). Then add protoTitle and protoStatus child views. Finally, add your buttons to the status bar as children of the protoStatus view. You can use the compile-time function ButtonBounds to automatically place the buttons. For details, refer to the sample code on this topic published by the PIE Developer Technical Support (DTS) group. s

protoDrawer
This proto is used to create a view that acts like the Extras drawer. It slides up from the bottom of the screen when opened, and is accompanied by a drawer opening sound when it opens and a drawer closing sound when it closes. The proto has no content denedyou must add child views to it. These slots are of interest: viewBounds viewFlags viewFormat viewEffect showSound hideSound Set to the size and location where you want the view to appear. The default setting is vFloating + vApplication. Optional. The default setting is vfPen(2) + vfFrameBlack. Optional. The default setting is fxDrawerEffect. Optional. The default setting is ROM_draweropen. Optional. The default setting is ROM_drawerclose.

The protoDrawer is based on a view of the clView class.

Container Protos

3-5

CHAPTER

Working With Proto Templates

Here is an example of a template using protoDrawer: myDrawer := {... _proto: protoDrawer} // nothing else needed for drawer // add children to drawer

protoFloater
This proto is used to create a view that oats above all other non-oating sibling views within an application. The oater has a rounded matte frame and it is horizontally centered within its parent view. Here is an example:

These slots are of interest: viewBounds viewFlags viewJustify viewFormat Set to the size and location where you want the oater to appear. The default setting is vFloating. Do not change this ag, but you can add others if you wish. Optional. The default setting is vjParentCenterH. Optional. The default setting is vfFillWhite + vfFrameMatte + vfPen(5) + vfInset(1) + vfRound(5). Optional. The default effect is fxZoomOpenEffect. Optional. This slot holds a message that is used in an error alert if the scroll arrows are tapped and you have not provided a viewScrollUpScript or viewScrollDownScript method to handle the event. This error occurs only if the vApplication ag is set for this view (it is not set by default), and thus it is receiving scroll events. The default message is, This application does not support scrolling, which you can change if you want.

viewEffect noScroll

3-6

Container Protos

CHAPTER

Working With Proto Templates

noOverview

declareSelf

Optional. This slot holds a message that is used in an error alert if the overview button is tapped and you have not provided a viewOverviewScript method to handle the event. This error occurs only if the vApplication flag is set for this view (it is not set by default), and thus it is receiving overview events. The default message is, This application does not support Overview, which you can change if you want. Do not change. This slot is set by default to 'base. This identies the view to be closed when the user taps the close box, if you provide one as a child of this view.

The proto denes no contents for the oating view. You will need to add your own contents to the oater by adding child templates to it. By default, protoFloater does not support scrolling or overview. If you want your oater to support scrolling or overview (that is, to handle the scroll arrows and overview button), set the vApplication bit in the viewFlags slot, and provide the appropriate methods ( viewScrollUpScript, viewScrollDownScript, and viewOverviewScript) to handle scroll and overview messages. The protoFloater is based on a view of the clView class. It is provided with no child views. Here is an example of a template using protoFloater: floater:= {... _proto: protofloater, viewBounds: {left: -5, top: 104, right: 168, bottom: 162}, viewJustify: vjParentCenterH, viewflags: vVisible+vFloating, ...}; theText := {... // text child of the floating view _proto: protostatictext, text: "I'm floating . . ",

Container Protos

3-7

CHAPTER

Working With Proto Templates

viewBounds: {left: 40, top: 24, right: 144, bottom: 48}, viewfont: simpleFont12+tsBold, ...};

protoFloatNGo
This proto is identical to protoFloater, except that it includes a close box in the lower right corner of the oating view. This allows the user a way to close the view. Here is an example:

These slots are of interest: viewBounds viewFlags viewJustify viewFormat Set to the size and location where you want the oater to appear. The default setting is vFloating. Do not change this ag, but you can add others if you wish. Optional. The default setting is vjParentCenterH. Optional. The default setting is vfFillWhite + vfFrameMatte + vfPen(5) + vfInset(1) + vfRound(5). Optional. The default effect is fxZoomOpenEffect. Optional. This slot holds a message that is used in an error alert if the scroll arrows are tapped and you have not provided a viewScrollUpScript or viewScrollDownScript method to handle the event. This error occurs only if the vApplication ag is set for this view (it is not set by default), and thus it is receiving scroll events. The default message is, This application does not support scrolling, which you can change if you want.

viewEffect noScroll

3-8

Container Protos

CHAPTER

Working With Proto Templates

noOverview

declareSelf

Optional. This slot holds a message that is used in an error alert if the overview button is tapped and you have not provided a viewOverviewScript method to handle the event. This error occurs only if the vApplication flag is set for this view (it is not set by default), and thus it is receiving overview events. The default message is, This application does not support Overview, which you can change if you want. Do not change. This slot is set by default to 'base. This identies the view to be closed when the user taps the close box.

The proto denes no contents for the oating view. You will need to add your own contents to the oater by adding child templates to it. The protoFloatNGo is based on the protoFloater proto, which is based on a view of the clView class. It is provided with one child view that is a close box based on the protoCloseBox proto. Here is an example of a template using protoFloatNGo: floatngoView:= {... _proto: protofloatngo, viewBounds: {left: -2, top: 98, right: 158, bottom: 170}, viewJustify: vjParentCenterH, viewflags: vVisible+vFloating, ...}; theText := {... // text child of the floatngo view _proto: protostatictext, text: "Float'n Go view", viewBounds: {left: 22, top: 30, right: 134, bottom: 54}, viewfont: simpleFont12+tsBold, ...};

Container Protos

3-9

CHAPTER

Working With Proto Templates

Input Protos
Input protos are used to gather input from the user.

protoDateExpando
This proto is used for an expanded text-edit line that is added as a child of a protoExpandoShell when the user taps on the label corresponding to it. The protoDateExpando is based on the protoTextExpando and is very similar, except that it is designed to accept dates instead of any text. The date shown in the input eld is of the type returned by the function ShortDateStr. It looks like this: 11/19/93. These slots are of interest: label path A string that is the label shown to the left of the eld value. A symbol that is a path expression to the slot in the target frame from which the initial value for the eld is gotten, and in which the nal value is to be stored. If no initial value is found, two dashes are displayed (--). The slot identied by the path expression should contain a string that is a date. The target frame is specied in the target slot of the parent template, based on the protoExpandoShell proto. Set particular ags to limit recognition, if desired. The setting you specify in this slot is used for the viewFlags slot of the input field. The default setting is: vVisible + vClickable + vGesturesAllowed + vDateField. Optional. A date format specication as returned by the compile-time function GetDateStringSpec. This slot species what elements should be included in the

entryFlags

date

3-10

Input Protos

CHAPTER

Working With Proto Templates

specialClass

Setup1

Setup2

keyboard

date and how it should be formatted. The default date format is the one returned from this function call: GetDateStringSpec([[kElementYear, kFormatNumeric], [kElementMonth, kFormatNumeric], [kElementDay, kFormatNumeric]]) Optional. A symbol specifying a string subclass name. When the string in the expanded edit eld is changed and stored in the specied path, the string is set to this class. (The binary object containing the string is set to the specied class.) Optional. This method is called to set up the text for the eld label whenever the collapsed view of this eld is to be displayed (when the protoExpandoShell is rst shown, and whenever this eld is closed after being expanded). This method is passed one parameter, the target slot from the protoExpandoShell. This method should return a string, which is then used for the eld label. If you dont supply this method, the label slot is returned. Optional. This method is called to set up the text for the eld value whenever the collapsed view of this eld is to be displayed (when the protoExpandoShell is rst shown, and whenever this eld is closed after being expanded). This method is passed one parameter, the target slot from the protoExpandoShell. This method should return a string, which is then used for the text value of the eld. If you dont supply this method, the expression ShortDateStr(target.(path),date) is evaluated. Optional. A symbol which evaluates to a keyboard template. If specied, this keyboard view is opened automatically when this eld is expanded. The keyboard is automatically removed when a different eld is expanded. You can specify your own keyboard, or one of the following symbols corresponding to keyboards built into the system root view: 'alphaKeyboard, 'numericKeyboard, 3-11

Input Protos

CHAPTER

Working With Proto Templates

'dateKeyboard, 'phoneKeyboard. For more information about these keyboards, see the section Working With Keyboard Views beginning on page 2-100. Additionally, you can specify most other slots that are optional for a protoLabelInputLine, since protoDateExpando is based on protoTextExpando, which is based on protoLabelInputLine. The TextSetup and TextChanged methods are used by the protoDateExpando proto, so if you want to include those methods, you must call the inherited method at the end of yours (for example, inherited:?TextChanged()). Note that the protoDateExpando proto is not usually used by picking it from the view palette. You use this proto by writing a textual description of your template and referring to this proto in the _proto slot of your template frame. You write one template frame for each expanding item to be shown in the protoExpandoShell, and place them all in an array in the lines slot of the protoExpandoShell. Here is an example of an expanding item based on protoDateExpando in the lines slot of a template based on protoExpandoShell: [... {_proto: protoDateExpando, label: "Birthday", path: 'birthday}, ...]

protoExpandoShell
This proto is used for a container view that contains several expanding text editing lines, each consisting of a label to the left with a text value to its right. When a user taps on one of the editable lines, an editable text eld expands from it in which the user can write or edit existing text. The user can close the expanded text eld by tapping on another item or by tapping the close box in the eld.

3-12

Input Protos

CHAPTER

Working With Proto Templates

There is no visual representation of a protoExpandoShell view by itself. It serves only as a container for information supplied by views based on protoTextExpando, protoDateExpando, or protoPhoneExpando. Note that when all text lines in the protoExpandoShell view are collapsed, this view has no children. The text lines are displayed by drawing functionsthey are not child views. When an item is expanded, the protoExpandoShell view has a single child viewthe view corresponding to the protoTextExpando, protoDateExpando, or protoPhoneExpando item that is expanded. Here is an example of a protoExpandoShell view that contains some of these other protos:
Initial View (all elds collapsed) View after Zip eld is tapped

These slots are of interest: viewBounds target Set to the size and location where you want the expando shell view to appear. A reference to a frame containing the data to be used to ll in the value in each text line. This frame will also receive the data entered by the user. Usually, this must be set at run timeyou can set it in the viewSetupDoneScript method. An array of templates that describe the editable text lines to be shown in the view. Each of these templates

lines

Input Protos

3-13

CHAPTER

Working With Proto Templates

numLines

editHeight

editWidth

should use protoTextExpando, protoDateExpando, or protoPhoneExpando as its proto. See these proto descriptions for details. The number of items in the lines array that should be displayed. (You can specify a number smaller than the number of actual items, and only the number you specify will be shown. But do NOT specify a number greater than the actual number of items; this will cause an exception if the user taps in the space below the last shown item.) The height, in pixels, of the expanded edit eld that pops up when the user taps an item. You must specify this slot; there is no default. Optional. The width, in pixels, of the expanded edit eld that pops up when the user taps an item. If you dont include this slot, the default width is 220. Optional. The line spacing is the distance between the dotted lines shown in the expanded edit eld, in pixels. The default setting is 20. Optional. The height, in pixels, of each item line (in the collapsed state). If you dont include this slot, the default line height is 16. Optional. This is the amount, in pixels, to indent the text value (shown to the right of each label) in each line from the left edge of the view. If you dont include this slot, the default indent is 100. Optional. This is the font used for the labels to the left of each eld. The default is ROM_fontSystem9Bold. Optional. This is the font used for the text value shown to the right of each label. The default is userFont12. Optional. Species an item from the lines array to expand automatically when the view is rst opened. The default value of this slot is zero (the rst array item). If you dont want a line to open automatically, set this slot to nil.

viewLineSpacing

lineHeight

indent

labelStyle textStyle firstLine

3-14

Input Protos

CHAPTER

Working With Proto Templates

Optional. Species a string to be shown as the text for an item if it is empty. The default is two dashes (--). writeProtected Optional. If set to true, the view is write-protected. None of the text items can be expanded for editing. If you dont include this slot, the default is nil, which allows normal operation (editing). CloseEdit Optional. This method is called whenever an expanded editing eld is closed. This method is passed one parameterthe view that was closed; its return value is ignored. If you dont supply this method, there is no default processing that occurs; this mechanism simply gives you a chance to do any processing that you need to do when an expanded eld is closed. empty The following additional methods are dened internally: viewSetupFormScript, viewSetupChildrenScript, viewQuitScript, viewDrawScript, viewClickScript, FlushEdits, ExpandNone, ExpandKeys, and ExpandLine. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewSetupFormScript()), otherwise the proto may not work as expected. The protoExpandoShell is based on a view of the clParagraphView class. It has no predened child views, though you typically add several, based on the protoTextExpando, protoDateExpando, or protoPhoneExpando protos. Here is an example of a template using protoExpandoShell: myExpando := {... _proto: protoexpandoshell, viewBounds: {left: 13, top: 37, right: 221, bottom: 213}, viewflags: vVisible+vClickable, viewFormat: vfFrameBlack+vfPen(1)+vfInset(2), numLines: 7, editHeight: 50, indent: 50, editWidth: 200,

Input Protos

3-15

CHAPTER

Working With Proto Templates

viewSetupFormScript: func() begin self.target := self; self.phones := clone([]); //call this to preserve proto behavior inherited:?viewSetupFormScript() end, lines: [ {_proto:protoTextExpando, label:"Name", path:'data1, entryFlags: vVisible+vClickable+vGesturesAllowed+ vNameField+ vCapsRequired}, {_proto:protoTextExpando, label:"Address", path:'data2, entryFlags: vVisible+vGesturesAllowed+vClickable+ vAddressField}, {_proto:protoTextExpando, label:"City", path:'data3, entryFlags: vVisible+vGesturesAllowed+vClickable+ vCharsAllowed}, {_proto:protoTextExpando, label:"State", path:'data4, entryFlags: vVisible+vGesturesAllowed+vClickable+ vCharsAllowed}, {_proto:protoTextExpando, label:"Zip", path:'data5, entryFlags: vVisible+vGesturesAllowed+vClickable+ vNumbersAllowed},

3-16

Input Protos

CHAPTER

Working With Proto Templates

{_proto:protoPhoneExpando, path:'phones, phoneIndex:0}, {_proto:protoPhoneExpando, path:'phones, phoneIndex:1}, ], ...};

protoInputLine
This proto is used for a one-line input eld that is indicated by a dotted line to write on. It denes a simple paragraph view that accepts any kind of text input and is left-justied. Here is an example:

These slots are of interest: Set to the location where you want the input eld to appear. viewFlags Set particular view ags to limit recognition, if desired. The default setting is vVisible + vClickable + vGesturesAllowed + vCharsAllowed + vNumbersAllowed. text Optional. Set to a string that is the initial text, if any, to be shown in the input eld. The default is no text. During run time, this slot holds the current text that exists in the input eld. viewFont Optional. This sets the font for text the user writes in the input eld. The default is userFont12. viewJustify Optional. The default setting is vjLeftH + oneLineOnly. viewFormat Optional. The default setting is vfLinesGray. viewTransferMode Optional. The default mode is modeOr. viewBounds

Input Protos

3-17

CHAPTER

Working With Proto Templates

viewLineSpacing Optional. The line spacing is the height of the input line in pixels and it defaults to the setting of the parent view, or to 20, if there is no parent setting. viewLinePattern Optional. Sets a custom pattern that is used to draw the line in the view. A pattern is simply an eight-byte binary data structure with the class 'pattern. You can use this NewtonScript trick to create binary pattern data structures on the y: myPattern := SetClass( Clone("\uAAAAAAAAAAAAAAAA"),'pattern); This code clones a string, which is already a binary object, and changes its class to 'pattern. The string is specied with hex character codes whose binary representation is used to create the pattern. Each two-digit hex code creates one byte of the pattern. viewChangedScript Optional. This method is called whenever the value of the input eld is changed. The following additional methods are dened internally: viewSetupFormScript and viewSetupDoneScript. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewSetupFormScript()), otherwise the proto may not work as expected. The protoInputLine is based on a view of the clParagraphView class. It is provided with no child views. Here is an example of a template using protoInputLine: myInput := {... _proto: protoInputLine, viewJustify: vjParentRightH+vjParentBottomV, viewLineSpacing: 24, viewBounds: SetBounds( -55, -33, -3, -3), ...}

3-18

Input Protos

CHAPTER

Working With Proto Templates

protoLabelInputLine
This proto is used for a one-line input eld that includes a text label at the left of the input eld. It is similar to protoInputLine, except that it has a text label and it can optionally behave like a pop-up menu, called a picker. If you choose to implement the picker behavior, it means the user can tap on the label to pop up a menu of choices. If the user selects a choice from the picker, that choice is entered as the text in the input line, and it is marked with a check mark in the picker. Here is an example of a protoLabelInputLine with and without the picker option:

Simple protoLabelInputLine (no picker option) Picker option indicated by diamond Example of a picker displayed after label is tapped. Check mark indicates the currently selected choice.

These slots are of interest: viewBounds Set to the location where you want the view to appear. Note that the view should have a height equal to or greater than the value set for viewLineSpacing. Set particular ags to limit recognition, if desired. The setting you specify in this slot is used for the viewFlags slot of the input field. The default setting is vVisible + vClickable + vGesturesAllowed + vCharsAllowed + vNumbersAllowed. Set to a string that is the label text. Optional. Sets the font used for the label. The default is ROM_fontSystem9Bold. 3-19

entryFlags

label labelFont

Input Protos

CHAPTER

Working With Proto Templates

labelCommands

Optional. If this slot is supplied, the picker feature is activated and the label is shown with a diamond to its left to indicate that it is a picker. Specify an array of strings that should appear in a picker when the user taps on the label. The currently selected item in the list, if there is one, is marked with a check mark to its left. Optional. If the labelCommands slot is supplied, this slot species which item in that array should be initially marked with a check mark. Specify an integer, which is used as an index into the labelCommands array. If you omit this slot, no item is initially marked with a check mark. Optional. Set to the distance from the left edge of the view where the dotted input line should begin. The default is 4 pixels to the right of the label text. This slot is useful if you are specifying several labeled input elds in a column, and you want all the dotted input lines to line up beneath one another. If you specify this slot, be sure to leave enough room for the label text. Optional. The line spacing is the height of the input line in pixels and it defaults to the setting of the parent view, or to 20, if there is no parent setting.

curLabelCommand

indent

viewLineSpacing

viewLinePattern Optional. Sets a custom pattern that is used to draw the line in the view. A pattern is simply an eight-byte binary data structure with the class 'pattern. You can use this NewtonScript trick to create binary pattern data structures on the y: myPattern := SetClass( Clone("\uAAAAAAAAAAAAAAAA"),'pattern); This code clones a string, which is already a binary object, and changes its class to 'pattern. The string is specied with hex character codes whose binary representation is used to create the pattern. Each two-digit hex code creates one byte of the pattern.

3-20

Input Protos

CHAPTER

Working With Proto Templates

Optional. This method is called when the view is instantiated to set an initial value in the input eld. This method is passed no parameters and should return a string, which is set as the initial value in the input eld. If you dont supply this method, the input eld is initially empty. updateText Optional. You can call this method to programmatically change the value of the text in the input eld. This action is reversible by the user with the Undo button. This method takes one parameter, a string that is the new value of the input eld. Note that you dont normally need to call this method; the input eld is updated automatically when the user writes in it. textChanged Optional. This method is called whenever the value of the input eld is changed. It is passed no parameters. If you dont supply this method, no default action occurs. setLabelText Optional. You can call this method to dynamically change the label text after the view has already been opened. This method takes one parameter, a string that is the new label text. setLabelCommands Optional. You can call this method to dynamically set the labelCommands array. This method takes one parameter, an array of strings that should appear in the picker. labelClick Optional. This method is called when the user taps on the label. It is passed one parameter, the stroke unit that was passed to the viewClickScript method of the label. This message noties the view; then you have a chance to handle the event when the label is tapped. If you don't supply this method or if you choose not to handle the event, the default action is to display the picker, get the users choice, enter the chosen text into the input line, and dirty the input line to cause a redraw. This function must return either true or nil. If it returns true, the default action is not done; the assumption is that you have handled the event yourself. textSetup

Input Protos

3-21

CHAPTER

Working With Proto Templates

If it returns nil, the default action is still performed after this method returns. labelActionScript Optional. This method is called when an item is chosen from the picker. It is passed one parameter, which is the index of the item selected from the labelCommands array. This message noties the view; then you have a chance to handle the event when an item is chosen from the picker. If you don't supply this method or if you choose not to handle the event, the default action is to set the text in the input line to the string that was chosen from the picker. This function must return either true or nil. If it returns true, the default action is not done; the assumption is that you have handled the event yourself. If it returns nil, the default action is still performed after this method returns. Note that inking is automatically turned off when the label is tapped. The protoLabelInputLine is based on a view of the clView class. It has the following two child views declared in itself:
n

labelLine. This child view uses the protoStaticText proto. It is used for the static text label and it activates the picker if that feature is used. entryLine. This child view uses the protoInputLine proto. It is used for the input eld in which the user can write. The text value entered into this eld is stored in the text slot of this view. You can access this slot from the parent view using the expression entryLine.text. To ensure that the view is updated properly after you programmatically change a slot such as the text slot, use the SetValue function, like this:

SetValue(entryLine, 'text, "new text") Here is an example of a template using protoLabelInputLine: labelLine := {... _proto: protolabelinputline,

3-22

Input Protos

CHAPTER

Working With Proto Templates

viewBounds: {top: 90, left: 42, right: 194, bottom: 114}, label: "Who", labelCommands: ["Me", "You", "Us", 'pickseparator, "Them", "No one"], curLabelCommand: 0, ...};

protoPhoneExpando
This proto is used for an expanded text-edit line that is added as a child of a protoExpandoShell when the user taps on the label corresponding to it. The protoPhoneExpando is based on the protoTextExpando and is very similar, except that it is designed to accept phone numbers instead of any text. Also, the protoPhoneExpando implements the picker feature of the protoLabelInputLine on which it is indirectly based. When the edit field is expanded, the picker is used to select a description for the phone number such as Work, Home, and so on. The selected choice is then shown as the label for the eld. These slots are of interest: path A symbol that is a path expression to the slot in the target frame from which the initial value for the eld is gotten, and in which the nal value is to be stored. If no initial value is found, two dashes are displayed (--). The slot identied by the path expression should contain an array of phone number strings. There should be one array element for each protoPhoneExpando that uses the same target slot. You should specify a different phoneIndex for each protoPhoneExpando view, if you use more than one. You must ensure that the slot you specify exists in RAM, since this proto attempts to add to it. You may have to clone it in your viewSetupFormScript method to ensure this.

Input Protos

3-23

CHAPTER

Working With Proto Templates

phoneIndex

entryFlags

labelCommands

labelSymbols

The target frame is specied in the target slot of the parent template, based on the protoExpandoShell proto. Specify a number to be used as an index into an array stored in the target slot (identied by the path symbol). If you use more than one protoPhoneExpando view that stores data in the same target slot, make sure that each one uses a different index. Set particular ags to limit recognition, if desired. The setting you specify in this slot is used for the viewFlags slot of the input eld. The default setting is: vVisible + vClickable + vGesturesAllowed + vPhoneField. Optional. This slot contains an array listing the choices to appear on the picker. Here is the default array: ["Phone", "Home", "Work", "Fax", "Car", "Beeper", "Mobile", "Other"]. The string the user chooses is used as the label for the eld. Also, the matching symbol (see labelSymbols) is assigned to the string they enter. If no choice has yet been made, the rst array item is used as the eld label. Optional. This slot contains an array of symbols that are subclasses of the 'string class. These symbols are used to identify phone numbers stored in the target slot (see path). There is a direct correspondence between these symbols and the items listed in the picker. For example, if the user picks the second item in the picker, the phone number string they enter is assigned the second class symbol from the array. Here is the default array of symbols: [ 'phone, 'homePhone, 'workPhone, 'faxPhone, 'carPhone, 'beeperPhone, 'mobilePhone, 'otherPhone].

3-24

Input Protos

CHAPTER

Working With Proto Templates

Setup2

keyboard

Optional. This method is called to set up the text for the eld value whenever the collapsed view of this eld is to be displayed (when the protoExpandoShell is rst shown, and whenever this eld is closed after being expanded). This method is passed one parameter, the target slot from the protoExpandoShell. This method should return a string, which is then used for the text value of the eld. If you dont supply this method, the expression target.(path)[phoneIndex] is evaluated. Optional. A symbol which evaluates to a keyboard template. If specied, this keyboard view is opened automatically when this eld is expanded. The keyboard is automatically removed when a different eld is expanded. You can specify your own keyboard, or one of the following symbols corresponding to keyboards built into the system root view: 'alphaKeyboard, 'numericKeyboard, 'dateKeyboard, 'phoneKeyboard. For more information about these keyboards, see the section Working With Keyboard Views beginning on page 2-100.

Additionally, you can specify most other slots that are optional for a protoLabelInputLine, since protoPhoneExpando is based on protoTextExpando, which is based on protoLabelInputLine. The TextSetup, TextChanged, and LabelActionScript methods are used by the protoPhoneExpando proto, so if you want to include those methods, you must call the inherited method at the end of yours (for example, inherited:?TextChanged()). Additionally, the protoPhoneExpando uses an internal method named Setup1. Note that the protoPhoneExpando proto is not usually used by picking it from the view palette. You use this proto by writing a textual description of your template and referring to this proto in the _proto slot of your template frame.

Input Protos

3-25

CHAPTER

Working With Proto Templates

You write one template frame for each expanding item to be shown in the protoExpandoShell, and place them all in an array in the lines slot of the protoExpandoShell. Here is an example of some expanding items based on protoPhoneExpando in the lines slot of a template based on protoExpandoShell: [... {_proto: protoPhoneExpando, path: 'phones phoneIndex: 0}, {_proto: protoPhoneExpando, path: 'phones phoneIndex: 1}, ...]

protoTextExpando
This proto is used for an expanded text-edit line that is added as a child of a protoExpandoShell when the user taps on the label corresponding to it. Because this proto is based on the protoLabelInputLine proto, the expanded text line can be a simple entry eld or a picker (see protoLabelInputLine for details). The expanded text edit line includes a close box, which the user can tap to close the expanded edit eld. The protoTextExpando view is also alternatively closed if the user taps on a different label to edit a different eld. For an example of a view based on this proto, see protoExpandoShell. These slots are of interest: label path A string that is the label shown to the left of the eld value. A symbol that is a path expression to the slot in the target frame from which the initial value for the eld is gotten, and in which the nal value is to be stored. If no initial value is found, two dashes are displayed (--). The slot identied by the path expression should contain a string.

3-26

Input Protos

CHAPTER

Working With Proto Templates

entryFlags

specialClass

Setup1

Setup2

keyboard

The target frame is specied in the target slot of the parent template, based on the protoExpandoShell proto. Set particular ags to limit recognition, if desired. The setting you specify in this slot is used for the viewFlags slot of the input field. The default setting is vVisible + vClickable + vGesturesAllowed + vCharsAllowed + vNumbersAllowed. Optional. A symbol specifying a string subclass name. When the string in the expanded edit eld is changed and stored in the specied path, the string is set to this class. (The binary object containing the string is set to the specied class.) Optional. This method is called to set up the text for the eld label whenever the collapsed view of this eld is to be displayed (when the protoExpandoShell is rst shown, and whenever this eld is closed after being expanded). This method is passed one parameter, the target slot from the protoExpandoShell. This method should return a string, which is then used for the eld label. If you dont supply this method, the label slot is returned. Optional. This method is called to set up the text for the eld value whenever the collapsed view of this eld is to be displayed (when the protoExpandoShell is rst shown, and whenever this eld is closed after being expanded). This method is passed one parameter, the target slot from the protoExpandoShell. This method should return a string, which is then used for the text value of the eld. If you dont supply this method, the expression target.(Path) is evaluated. Optional. A symbol which evaluates to a keyboard template. If specied, this keyboard view is opened automatically when this eld is expanded. The keyboard is automatically removed when a different eld is expanded. You can specify your own keyboard, or one of the following symbols corresponding to

Input Protos

3-27

CHAPTER

Working With Proto Templates

keyboards built into the system root view: 'alphaKeyboard, 'numericKeyboard, 'dateKeyboard, 'phoneKeyboard. For more information about these keyboards, see the section Working With Keyboard Views beginning on page 2-100. Additionally, you can specify most other slots that are optional for a protoLabelInputLine, since protoTextExpando is based on that proto. The TextSetup and TextChanged methods are used by the protoTextExpando proto, so if you want to include those methods, you must call the inherited method at the end of yours (for example, inherited:?TextChanged()). Note that the protoTextExpando proto is not usually used by picking it from the view palette. You use this proto by writing a textual description of your template and referring to this proto in the _proto slot of your template frame. You write one template frame for each expanding item to be shown in the protoExpandoShell, and place them all in an array in the lines slot of the protoExpandoShell. Here is an example of some expanding items based on protoTextExpando in the lines slot of a template based on protoExpandoShell: [{_proto: protoTextExpando, label: "Name", path: 'name, entryFlags: vVisible+vClickable+vGesturesAllowed+ vNameField+vCapsRequired}, {_proto: protoTextExpando, label: "Address", path: 'address, entryFlags: vVisible+vClickable+vGesturesAllowed+ vAddressField},

3-28

Input Protos

CHAPTER

Working With Proto Templates

{_proto: protoTextExpando, label: "Zip", path: 'zip, entryFlags: vVisible+vClickable+vGesturesAllowed+ vNumbersAllowed, keyboard: 'numericKeyboard}, ...]

Control Protos
The protos described in this section implement controls such as buttons, check boxes, radio buttons, sliders, and so on.

protoActionButton
This proto is used to include the action button in a view. When the user taps on the action button, a pop-up menu is dynamically created and displayed. The menu contains those routing services that the current application has registered with the system. When an item from the menu is selected, the corresponding routing slip is displayed, and if conrmed, the item selected in the application is routed. Here is an example of the action button and menu:

Action Menu Action Button

Enabling routing for your application entails much more than just using the protoActionButton. For details on what is required, see the chapter Routing.

Control Protos

3-29

CHAPTER

Working With Proto Templates

These slots are of interest: viewBounds By default, the action button is placed in the upper right corner of its parent view. The default top left coordinate is (-42, 2). Set this slot if you want to change the icon's location. We recommend that you put the action button with other buttons on a status bar, if you have one. Optional. The default setting is vjCenterH + vjCenterV + vjParentRightH. Optional. The default setting is vfFillWhite + vfFrameBlack + vfPen(2) + vfRound(4).

viewJustify viewFormat

The following additional methods are dened internally: viewClickScript, buttonClickScript, pickActionScript, and pickCancelledScript. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewClickScript()), otherwise the proto may not work as expected. The protoActionButton uses the protoPictureButton as its proto; and protoPictureButton is based on a view of the clPictureView class.

protoCheckbox
This proto is used for a check box. This is a small dotted box that may include a check mark. It is labeled to the right with a text label. When the user taps on the check box, a check is drawn in it. If the user taps in a checked box, the check is removed. Here is an example:

These slots are of interest: viewBounds text Set to the size and location where you want the checkbox to appear. A string that is the check box text label.

3-30

Control Protos

CHAPTER

Working With Proto Templates

viewFormat

buttonValue

valueChanged

toggleCheck

viewFont viewValue

Optional. The default setting is vfNone. Typically you wouldnt want any frame or ll since the check box provides all of the visual content necessary. Optional. Set this slot to the value that you want the view to have when the check box is checked. The default, if you dont provide this slot, is true. Its best to use an immediate or a symbol for this value, since strings and other structured objects may fail an equivalence test even though their contents are equivalent to the comparison value. This is because internal comparisons on pointer objects are done using pointer equality, not content equality. Optional. This method is called whenever the value of the check box changes, to allow you to do additional processing. It is passed no parameters and the return value is ignored. Optional. You can call this method to programmatically toggle the check mark in the check box. If the check is shown, it is removed, and vice versa. The check box is redrawn appropriately. This method takes no parameters and always returns true. Optional. The default font for the text label is ROM_fontSystem9. Holds the current value of the checkbox. This slot is set to nil when it is unchecked and to the value specied in buttonValue when it is checked

The following additional methods are dened internally: viewSetupDoneScript, viewClickScript, viewChangedScript, and UpdateBitmap. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewSetupDoneScript()), otherwise the proto may not work as expected. Note that inking is automatically turned off when the checkbox is tapped.

Control Protos

3-31

CHAPTER

Working With Proto Templates

The protoCheckbox uses an internal proto called protoCheckBoxIcon as its proto; and protoCheckBoxIcon is based on a view of the clPictureView class. The protoCheckbox itself implements the checkbox icon portion of the proto. It has one child view, a clTextView, that implements the text label portion of the proto. A clTextView is simply a clParagraphView that is read-only and it supports no tabs or multi-styled text. The protoCheckBoxIcon proto identies itself as the base view ( declareSelf: 'base). Here is an example of a template using protoCheckBox: notifier :={ _proto: protoCheckBox, viewBounds: SetBounds( 40, 30, 200, 45), buttonValue: true, text: "Play Notify Sound" ...}

protoCloseBox
This is the close box typically used in a view as a mechanism for the user to close the view. When it is tapped, the view is closed. This proto is very similar to protoLargeCloseBox. The differences are that protoCloseBox is a slightly smaller icon and the frame is part of the bitmap. Here is an example:

These slots are of interest: viewFlags The default is vVisible + vReadOnly + vClickable.

3-32

Control Protos

CHAPTER

Working With Proto Templates

Set to the size and location where you want the close box to appear. If you do not set this slot, the close box defaults to the lower right corner of its instantiator's view. (The bitmap is placed at -14, -14 from the lower right corner.) viewJustify Optional. The default setting is vjParentBottomV + vjParentRightH. viewFormat Optional. The default setting is vfNone. Typically you wouldnt want any frame or ll since the close box picture provides the visual content. buttonClickScript This method is dened in the proto to send the Close message to the view identied as base. You don't need to redene this method unless you want to perform additional operations, such as disconnecting a communications link, before the view is closed. If you do redene this method, you should send the message inherited:?buttonClickScript() at the end of your method to preserve the view closing behavior. viewBounds Additionally, the view that is to be closed by the close box must contain the following slot: declareSelf: 'base Usually this would be the application base view. The protoCloseBox uses the protoPictureButton as its proto; and protoPictureButton is based on a view of the clPictureView class. Here is an example of a template using protoCloseBox: printerPicker := {... declareSelf: 'base, ...} child := {... // child of printPicker _proto: protoCloseBox,

Control Protos

3-33

CHAPTER

Working With Proto Templates

buttonClickScript: func() begin :closeNetwork(); inherited:?buttonClickScript(); end, ...}

protoFilingButton
This proto is used to include the ling button in a view. When the user taps the ling button, the system displays a dialog box containing a list of categories under which the user can choose to le the currently selected item. When the user taps the File button, the system sends the filingChanged message to your application. Here is an example of the ling button and dialog:

Filing Button

Filing Dialog

Enabling ling for your application entails much more than just using the protoFilingButton. For details on what is required, see the section Filing in the chapter Additional System Services. These slots are of interest: viewBounds Set to the size and location where you want the ling button to appear. We recommend that you put the ling button with other buttons on a status bar, if you have one. Optional. The default setting is vjCenterH + vjCenterV + vjSiblingLeftH.

viewJustify

3-34

Control Protos

CHAPTER

Working With Proto Templates

viewFormat

Optional. The default setting is vfFillWhite + vfFrameBlack + vfPen(2) + vfRound(4).

The following additional methods are dened internally: viewSetupFormScript, buttonClickScript, and Update. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewSetupFormScript()), otherwise the proto may not work as expected. The protoFilingButton uses the protoPictureButton as its proto; and protoPictureButton is based on a view of the clPictureView class. The protoFilingButton is used in conjunction with the protoFolderTab to implement ling for an application.

protoFolderTab
This proto is used to include a tab-like view showing what folder is currently being displayed, if your application supports ling. The protoFolderTab view should be placed at the top of your application view. When the user taps the title on the tab, this proto displays a pop-up list of folders. A check mark appears next to the currently-selected folder in this list; the user can tap an item in the list to select a new folder to be displayed. When a new folder is selected, the system sends the filterChanged message to your application and collapses the list, displaying the currently-selected folder name on the le folder tab. Here is an example of the folder tab and the pop-up list:
Folder Tab

Pop-up List of Folders

Control Protos

3-35

CHAPTER

Working With Proto Templates

Enabling ling for your application entails much more than just using the protoFolderTab. For details on what is required, see the section Filing in the chapter Additional System Services. The following methods are dened internally: viewDrawScript and UpdateFilter. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewDrawScript()), otherwise the proto may not work as expected. The protoFolderTab is based on a view of the clView class. The protoFolderTab has one child, the text label that pops up a folder list. This child is based on the protoTextButton proto. The protoFolderTab is used in conjunction with the protoFilingButton to implement ling for an application.

protoLabelPicker
This proto is used for a labeled pop-up menu, called a picker. When the user taps on the label or the current choice, the picker pops up. The currently selected item is shown with a check mark next to it. The user can select a different item from the picker and then that choice is shown next to the label. Here is an example:

Current choice shown next to label

Menu of choices pops up

These slots are of interest: viewBounds Set to the size and location where you want the label with its item to appear. Note that if you use horizontal sibling-relative justication, you normally would specify relative values for the left and right bounds. For this proto, however, you must specify left and right bounds values whose difference equals the actual view width. The bounds values are used to calculate the width of the view that holds the text item.

3-36

Control Protos

CHAPTER

Working With Proto Templates

A string that is the text label. An array of strings that are the choices to be displayed in the picker. The currently selected item in the list, if there is one, is marked with a check mark to its left. indent Optional. The distance, in pixels, to indent the picker from the beginning of the line (the beginning of the text label). If you don't include this slot, the picker will be placed 6 pixels to the right of the text label by default. viewFont Optional. The font for the text label. The default is ROM_fontSystem9Bold. labelActionScript Optional. If the user chooses an item from the picker, the new item is set as the text next to the label and then this method is called to allow you to do additional processing. The method is passed one parameter, which is the index of the item that was chosen from the labelCommands array. textSetup Optional. This method is called to get the initial choice that should be shown next to the label when the view is being created. This method is passed no parameters and should return a string. It you don't include this method, the rst item from the labelCommands array is used as the initial item. textChanged Optional. This method is called whenever the value of the item is changed. It is passed no parameters. If you dont supply this method, no default action occurs. updateText Optional. You can call this method to programmatically change the value of the text item. This method takes one parameter, a string that is the new value of the text item. Note that you dont normally need to call this method; the text item is updated automatically when the user makes a selection from the picker. pickerSetup Optional. This method is called when the user taps on the label. It is passed no parameters. This method gives you a chance to do your own processing, including setting up the labelCommands array. text labelCommands

Control Protos

3-37

CHAPTER

Working With Proto Templates

This method should return true if you want the default action to occur; that is, the picker is popped up. If you return nil, the picker is not popped up. You must do this or something else on your own. If you omit this method, the one dened by default simply returns true, so the default actions occur. popit Optional. You can send this message to programmatically pop up the picker. It takes one parameter, which controls the horizontal position of the picker. You should pass (indent2) for this parameter. entryLine.viewFont Optional. This is the viewFont slot in the entryLine child of the protoLabelPicker. It sets the font for the text eld to the right of the label. The default font is userFont10. The following additional methods are dened internally: viewSetupFormScript, viewHiliteScript, viewClickScript, pickActionScript, and pickCancelledScript. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewSetupFormScript()), otherwise the proto may not work as expected. Note that inking is automatically turned off when the view based on this proto is tapped. The protoLabelPicker uses protoStaticText as its proto; and protoStaticText is based on a view of the clParagraphView class. The protoLabelPicker itself implements the label portion of the proto. It has one child view, also a protoStaticText view, that implements the text value portion of the proto. This child view is named entryLine. Here is an example of a template using protoLabelPicker: myPicker := {... _proto: protoLabelPicker, viewBounds: RelBounds(10, 60, screenWidth-100, 16), text: "Using",

3-38

Control Protos

CHAPTER

Working With Proto Templates

indent: 40, labelCommands: ["Speaker", "Modem"], textSetup: func() myConfig.speakerSetting, LabelActionScript: func(index) myConfig.speakerSetting := labelCommands[index], ...}

protoLargeCloseBox
This is a picture button that contains an X icon. When tapped, it closes the view identied as base (usually the view the button appears in). This proto is very similar to protoCloseBox. The differences are that protoLargeCloseBox is a slightly bigger icon and the frame is not part of the bitmap, but is controlled by the viewFormat ags. Here is an example:

Large Close Box

These slots are of interest: viewFlags viewBounds The default is vVisible + vReadOnly + vClickable. Set to the size and location where you want the close button to appear. If you do not set this slot, the close button defaults to the lower right corner of its instantiator's view. (The bitmap is placed at -18, -18 from the lower right corner.) Optional. The default setting is vjParentBottomV + vjParentRightH + vjCenterH + vjCenterV.

viewJustify

Control Protos

3-39

CHAPTER

Working With Proto Templates

Optional. The default setting is vfFillWhite + vfFrameBlack + vfPen(2) + vfRound(4). buttonClickScript This method is dened in the proto to send the Close message to the view identied as base. You don't need to redene this method unless you want to perform additional operations, such as disconnecting a communications link, before the view is closed. If you do redene this method, you should send the message inherited:?buttonClickScript() at the end of your method to preserve the view closing behavior. viewFormat Additionally, the view that is to be closed by the close button view must contain the following slot: declareSelf: 'base Usually this would be the application base view. The protoLargeCloseBox uses the protoPictureButton as its proto; and protoPictureButton is based on a view of the clPictureView class. Here is an example of a template using protoLargeCloseBox: closer := {... _proto: protoLargeCloseBox, // no need to define anything else ...}

protoPicker
This proto is used for a pop-up menu, called a picker, that is typically displayed in response to some other user action. For example, the user might tap on a word, and as a result, you would send the Open message to the protoPicker view.

3-40

Control Protos

CHAPTER

Working With Proto Templates

The picker is a list of items (text lines, bitmaps, or separator lines) from which the user can choose one item by tapping on it. If an item is currently selected, it is shown with a check mark next to it in the list. Here is an example:

These slots are of interest: bounds Must contain a viewBounds-like frame specifying a rectangle. The picker view will be created so that one of its corners corresponds to one of the corners of the rectangle you specify. However, the system gures out exactly where to position the view, depending on how large it is and how much space is available around it. For example, it would normally be positioned so that its top-left corner corresponds to the top-left corner of the rectangle you specify. However, if you specify a location in the lower-right corner of the screen, there wont be enough room for the picker; instead it will be positioned with its lower-right corner corresponding to the lower-right corner of the rectangle you specify. Generally, a picker view is shown as a result of a tap on a button, word, or some other visible element. In most cases, simply specify the viewBounds slot of that element as the value of the bounds slot. This slot is ignored. Any value you place here will be overwritten by the system, which calculates the value of this slot when the view is opened. The bounds slot is used to control the position of the view. The size of the view is determined by the width of the widest item and the total height of all items. The default is vFloating + vReadOnly + vClickable.

viewBounds

viewFlags

Control Protos

3-41

CHAPTER

Working With Proto Templates

An array of items to be displayed in the picker list. Usually this is an array of strings to appear in the list, but the array can also contain references to bitmap data structures (even mixed with text items). To include a separator line between two items, specify the symbol 'pickseparator where you want the line to go. To provide additional options for an item in the list, specify the item as a frame containing the following slots: item The item string or bitmap reference pickable Specify true if you want the item to be pickable, or nil for not pickable. Non-pickable items appear in the list but are not highlighted and cant be selected. mark Specify a dollar sign followed by the character you want to use to mark this item. For example, $\uFC0B species the check mark symbol in the Espy font. (You can use the constant kCheckMarkChar to specify the check mark character.) Do not specify more items than can t on the screen, because this view does not scroll. pickActionScript Optional. This method is called when an item is selected from the picker list. The index of the selected item in the pickItems array is passed as a parameter to this method. If you dont supply this method, there is no default action. If no item is selected because the user taps outside the list, the pickCancelledScript method is called instead. Note that the pickActionScript method can be in the picker view itself or in a different view. If this method is in a different view, the name of that view should be stored in the callbackContext slot. pickItems

3-42

Control Protos

CHAPTER

Working With Proto Templates

pickCancelledScript Optional. This method is called if the picker is canceled by a tap outside of it and pickAutoClose is set to true. If you dont supply this method, there is no default action. Note that the pickCancelledScript method can be in the picker view itself or in a different view. If this method is in a different view, the name of that view should be stored in the callbackContext slot. viewFormat Optional. The default setting is vfFrameBlack + vfPen(2) + vfRound(4). viewJustify Optional. The default setting is vjCenterH + vjCenterV. viewFont Optional. The default font for text items in the list is ROM_fontSystem10Bold. viewEffect Optional. The default view effect is fxPopDownEffect. pickTextItemHeight Optional. The height in pixels that should be reserved for each text item in the picker list. Note that each text item may actually occupy a height that is less than this amount. In this case, the item is vertically centered within the space. The default setting is 13 pixels. pickLeftMargin Optional. The margin of blank space, in pixels, between the list entries and the view boundary on the left side. The default is 4. pickRightMargin Optional. The margin of blank space, in pixels, between the list entries and the view boundary on the right side. The default is 5. pickTopMargin Optional. The margin of blank space, in pixels, above each bitmap item in the list. The default is 2. pickBottomMargin Optional. The margin of blank space, in pixels, below each bitmap item in the list. The default is 2.

Control Protos

3-43

CHAPTER

Working With Proto Templates

Optional. If the value of this slot is true (the default), the picker is automatically hidden after the user selects an item by tapping it. If this slot is nil, the picker is not hidden after a selection is made. If you want to hide the view in this case, you must explicitly send it the Hide message. Regardless of the setting of this slot, the picker is automatically closed if the user cancels the list by clicking outside of it. pickItemsMarkable Optional. If the value of this slot is true, space for marks is reserved at the left side of the list. If this slot is nil (the default), no space for marks is reserved. Note that space is reserved for marks if any of the list items has a mark specied, regardless of the setting of this slot. pickMarkWidth Optional. The number of pixels of space to reserve for marks at the left side of the list. If you don't specify this value, and marks are used, the space defaults to 10 pixels. callbackContext Optional. The name of the view containing the pickActionScript and pickCancelledScript methods. If this slot is omitted, the picker view looks in itself for these methods. SetItemMark Optional. You can call this method to set the mark character for an item in the list. This method takes two parameters: the rst is the index of the item whose mark you want to set, and the second is the character you want to set as the mark character. Do not specify a string for the second parameter; you must specify a character (for example, $>). To set no mark for an item, specify nil for the character. GetItemMark Optional. You can call this method to get the mark character for an item in the list. This method takes one parameter, the index of the item whose mark you want to get. This method returns the mark character, or nil if the item has no mark character set. pickAutoClose

3-44

Control Protos

CHAPTER

Working With Proto Templates

Additionally, the viewSetupDoneScript method is dened internally. If you need to use this method, be sure to call the inherited method also (for example, inherited:?viewSetupDoneScript()), otherwise the proto may not work as expected. The protoPicker is based on a view of the clPickView class. Note that there can be only one open picker view at a time in the system. If one is open and the user opens another, then the rst one will close. Here is an example of a template using protoPicker: picker := {... _proto: protoPicker, bounds: {left:34, top:66, right:96, bottom:96}, viewFlags: vFloating+vReadOnly+vClickable, viewFormat: vfPen(2)+vfRound(4)+vfFrameBlack+ vfFillWhite, pickItems: ["one", {item:"two", pickable:true, mark:kCheckMarkChar}, "three", 'pickseparator, "four", {item:"five", pickable:true} ], pickActionScript: func(index) begin print("You picked"); print(pickItems[index]); end, pickCancelledScript: func() Print("pickCancelledScript"); ...}

Control Protos

3-45

CHAPTER

Working With Proto Templates

protoPictIndexer
This proto is used to create a view with a horizontal array of pictures, one of which the user can tap on. When the user taps on a picture, it is highlighted, and the system sends the IndexClickScript to signal which picture was selected. Here is an example:

protoPictIndexer View

These slots are of interest: Set to the size and location where you want the view to appear. icon The bitmap serving as the picture. This should be a single bitmap containing multiple objects or symbols that are all of the same width and arranged next to each other in a vertical row. iconBBox A bounds frame giving the bounds of the bitmap within the view. (The view can be bigger than the bitmap.) The width is the only important dimension calculated from this bounds frame. The width is used to calculate the size of the active rectangle; that is, the rectangle used to differentiate and highlight each of the objects in the bitmap. The width of the bitmap is divided into (widthnumIndices) equal rectangles that extend the full height of the view. numIndices The number of objects or symbols in the bitmap. IndexClickScript Optional. This method is called whenever the user taps on the bitmap. It is passed one parameter, the index of viewBounds

3-46

Control Protos

CHAPTER

Working With Proto Templates

viewJustify

viewFormat curIndex

the bitmap object selected. Note that the rst item has an index of zero. Optional. The default setting is vjCenterH + vjCenterV + vjParentFullH + vjParentBottomV. Optional. The default setting is vfFillWhite. This slot is set to the index of the currently selected item in the bitmap. Note that the rst item has an index of zero. This slot must initially be set to an integer.

The following additional methods are dened internally: viewSetupDoneScript, viewDrawScript, viewClickScript, Hiliter, Unhilite, and TrackPictHilite. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewSetupDoneScript()), otherwise the proto may not work as expected. The protoPictIndexer is based on a view of the clPictureView class. Here is an example of a template using protoPictIndexer: indexView := {... _proto: protopictindexer, viewBounds: {top: -25, left: 0, right: 0, bottom: 0}, viewJustify: vjCenterH+vjCenterV+vjParentFullH+ vjParentBottomV, viewFormat: vfFillWhite+vfPen(1)+vfFrameBlack, icon: shapesBitmap, //square, roundrect, circle, triangle iconBBox: {top: 0, left: 0, right: 100, bottom: 0}, numIndices: 4, indexClickScript: func(currIndex) begin SetValue(theText, 'text, shapeArray[currIndex]); end, // set highlight to first item on entry curIndex: 0, ...}

Control Protos

3-47

CHAPTER

Working With Proto Templates

protoPictRadioButton
This proto is used for a child view of a radio button cluster (based on protoRadioCluster). The protoPictRadioButton creates a small boxed view containing a picture. Typically, several of these views are placed adjacent to each other (four of them are placed vertically in the example shown). The one that is selected is indicated by some kind of highlighting that you must supply. Here is an example:

Selected button

These slots are of interest: Set to the size and location where you want the picture radio button to appear. icon The bitmap to be used as the button picture. buttonValue Set this slot to the value of the view when this picture radio button is selected. Each radio button in the cluster should have a different buttonValue. This value is stored in the radio button cluster clusterValue slot if this button is the one selected in the cluster. Its best to use an immediate or a symbol for this value, since strings and other structured objects may fail an equivalence test even though their contents are equivalent to the comparison value. This is because internal comparisons on pointer objects are done using pointer equality, not content equality. viewDrawScript You must supply this method to highlight the radio button in some manner when it is selected. You could do this by drawing an inner black border, as shown in the example illustration. Your code should begin like this: if viewValue then // do drawing here... viewBounds

3-48

Control Protos

CHAPTER

Working With Proto Templates

viewFormat

viewJustify viewValue

declareSelf

Optional. The default setting is vfFillWhite + vfFrameBlack + vfPen(2) + vfRound(4). To simply frame the view, as shown in the example illustration, use this setting: vfFillWhite + vfFrameBlack + vfPen(1). Optional. The default setting is vjCenterH + vjCenterV. Holds the current value of the radio button. It is set to nil when it is unselected and to the value specified in buttonValue when it is selected. The proto initializes this slot to nil. If you want one radio button initially selected, set this slot to buttonValue for that radio button. Do not change. This slot is set by default to 'base.

The following additional methods are dened internally: viewClickScript and UpdateBitmap. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewClickScript()), otherwise the proto may not work as expected. The protoPictRadioButton uses protoPictureButton as its proto, and protoPictureButton itself is based on a view of the class clPictureView. A radio button based on protoPictRadioButton must be a child view of a protoRadioCluster. You can't create stand-alone picture radio buttons using this proto. Here is an example of a template using protoPictRadioButton: pictRadio := {... _proto: protoPictRadioButton, //override frame viewFormat: vfFillWhite+vfFrameBlack+vfPen(1), icon: myPict, buttonValue: 3,

Control Protos

3-49

CHAPTER

Working With Proto Templates

viewDrawScript: func() begin //if button is selected then highlight it if viewValue then :DrawShape(MakeRect(0,0,15,15), nil); end, ...}

protoPictureButton
This proto is used for a picture that is a button; that is, the picture can be tapped by the user to cause an action to occur. Here is an example:
Picture Buttons

These slots are of interest: Set to the size and location where you want the button to appear. viewFlags The default is vVisible + vReadOnly + vClickable. icon The bitmap to be used as the button. buttonClickScript A method that is called when the button is tapped. This method is passed no parameters and the return value is ignored. buttonPressedScript Optional. This method is called repeatedly as long as the button is pressed (the pen is held down within it). This method is passed no parameters and the return value is ignored. viewFormat Optional. The default setting is vfFillWhite + vfFrameBlack + vfPen(2) + vfRound(4). (The examples in the picture above have viewFormat set to zero). viewBounds

3-50

Control Protos

CHAPTER

Working With Proto Templates

viewJustify

Optional. The default setting is vjCenterH + vjCenterV.

Note that the viewClickScript method is used internally in the protoPictureButton and should not be overridden. You should use the buttonClickScript method to handle a tap event. (The buttonClickScript message is sent from within the viewClickScript method specically to provide a mechanism for you to handle the event.) Note that inking is automatically turned off when the button is tapped. The protoPictureButton is based on a view of the clPictureView class. Here is an example of a template using protoPictureButton: pictButton := {... _proto: protoPictureButton, icon: namesBitmap, viewBounds: SetBounds( 2, 8, 34, 40 ), buttonClickScript: func() cardfile:Toggle() ...}

protoRadioButton
This proto is used for a radio button child view of a radio button cluster (based on protoRadioCluster). A radio button is a small oval bit map that is either empty or contains a solid bulls-eye when it is selected. It is labeled to the right with a text label. Here is an example:

Control Protos

3-51

CHAPTER

Working With Proto Templates

These slots are of interest: viewBounds text buttonValue Set to the size and location where you want the radio button to appear. A string that is the radio button text label. Set to the value of the view when the radio button is selected. Each radio button in the cluster should have a different buttonValue. This value is stored in the radio button cluster clusterValue slot if this button is the one selected in the cluster. Its best to use an immediate or a symbol for this value, since strings and other structured objects may fail an equivalence test even though their contents are equivalent to the comparison value. This is because internal comparisons on pointer objects are done using pointer equality, not content equality. Optional. The default setting is vfNone. Typically you wouldnt want any frame or ll since the radio button provides all of the visual content necessary. Holds the current value of the radio button. It is set to nil when it is unselected and to the value specified in buttonValue when it is selected. The proto initializes this slot to nil.

viewFormat

viewValue

The following additional methods are dened internally: viewSetupDoneScript, viewClickScript, and radioClickScript. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewSetupDoneScript()), otherwise the proto may not work as expected. Note that inking is automatically turned off when the radio button is tapped. The protoRadioButton uses protoCheckbox as its proto, and protoCheckbox itself has a proto and a child view. See the description of protoCheckbox for details. A radio button based on protoRadioButton must be a child view of a view based on protoRadioCluster. You can't create stand-alone radio buttons using this proto.

3-52

Control Protos

CHAPTER

Working With Proto Templates

protoRadioCluster
This proto is used to group a series of radio buttons into a cluster where only one can be on at a time. The individual radio buttons should be added as child views to the radio cluster view. There is no visual representation of a protoRadioCluster view by itself. It serves only as a container for child views based on protoRadioButton or protoPictRadioButton. See protoRadioButton for an example of what this proto looks like. These slots are of interest: Set to the size and location where you want the radio button cluster to appear. clusterValue Optional. You can specify the initially selected button by storing its buttonValue in this slot. During execution, this slot holds the current value of the radio button cluster by storing the buttonValue of the selected radio button. The default initial value is nil (no button selected). viewSetupFormScript Optional. If you want to set an initially selected button but need to calculate its value at run time, calculate the value and set clusterValue from within this method. clusterChanged Optional. This method is called whenever the value of the radio cluster is changed (that is, when a different radio button is turned on) to give you a chance to do any processing you want to do. This method is passed no parameters and the return value is ignored. setClusterValue Optional. You can call this method to programmatically change the selected radio button in a cluster. This method takes one parameter, the buttonValue of the radio button you want to select. This method does several things for you, including giving the user undo capability for the change, updating the screen appropriately, and calling the clusterChanged method for you. viewBounds

Control Protos

3-53

CHAPTER

Working With Proto Templates

declareSelf

Do not change. This slot is set by default to 'cluster. This symbol is used internally to identify the cluster view.

The protoRadioCluster is based on a view of the clView class. The proto itself is provided with no child views, though you add child views to it by placing radio buttons inside of it. The individual radio buttons use one of the following protos: protoRadioButton or protoPictRadioButton. These two protos are described in the following sections. Here is an example of a template using protoRadioCluster and the three radio buttons included in the cluster: textFaceCluster := {... _proto: protoRadioCluster, viewBounds: SetBounds( 70, 17, 130, 77), viewSetupFormScript: func() clusterValue := userConfiguration.userFont.face, clusterChanged: func() userConfiguration.userFont.face := clusterValue, ...} child1 :={ _proto: protoRadioButton, viewBounds: SetBounds( 0, 0, 60, 20), text: "Bold", buttonValue: 1 ...} child2 := {... _proto: protoRadioButton, viewBounds: SetBounds( 0, 20, 60, 40), text: "Underline", buttonValue: 4 ...}

3-54

Control Protos

CHAPTER

Working With Proto Templates

child3 := {... _proto: protoRadioButton, viewBounds: SetBounds( 0, 40, 60, 60), text: "Plain", buttonValue: 0 ...}

protoRCheckbox
This proto is used for a check box where the text is to the left of the check box. Otherwise, this proto is identical to protoCheckbox. Here is an example:

These slots are of interest: viewBounds text indent viewFormat Set to the size and location where you want the checkbox to appear. A string that is the check box text label. Optional. The number of pixels to indent the checkbox to the right of the text. The default indent is 16. Optional. The default setting is vfNone. Typically you wouldnt want any frame or ll since the check box provides all of the visual content necessary. Optional. Set this slot to the value that you want the view to have when the check box is checked. The default, if you dont provide this slot, is true. Its best to use an immediate or a symbol for this value, since strings and other structured objects may fail an equivalence test even though their contents are equivalent to the comparison value. This is because internal comparisons on pointer objects are done using pointer equality, not content equality.

buttonValue

Control Protos

3-55

CHAPTER

Working With Proto Templates

valueChanged

toggleCheck

viewFont viewValue

Optional. This method is called whenever the value of the check box changes to allow you to do additional processing. It is passed no parameters and the return value is ignored. Optional. You can call this method to programmatically toggle the check mark in the check box. If the check is shown, it is removed, and vice versa. The check box is redrawn appropriately. This method takes no parameters and always returns true. Optional. The default font for the text label is ROM_fontSystem9. Holds the current value of the checkbox. This slot is set to nil when it is unchecked and to the value specied in buttonValue when it is checked

The following additional methods are dened internally: viewSetupDoneScript, viewClickScript, viewChangedScript, and UpdateBitmap. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewSetupDoneScript()), otherwise the proto may not work as expected. Note that inking is automatically turned off when the checkbox is tapped. The protoRCheckbox uses an internal proto called protoCheckBoxIcon as its proto; and protoCheckBoxIcon is based on a view of the clPictureView class. The protoRCheckbox itself implements the checkbox icon portion of the proto. It has one child view, a clTextView, that implements the text label portion of the proto. A clTextView is simply a clParagraphView that is read-only and it supports no tabs or multistyled text. The protoCheckBoxIcon proto identies itself as the base view ( declareSelf: 'base). Here is an example of a template using protoRCheckBox: rightCheckView :={ _proto: protoRCheckBox,

3-56

Control Protos

CHAPTER

Working With Proto Templates

viewBounds: SetBounds( 40, 30, 200, 45), buttonValue: true, text: "Right Checkbox" ...}

protoRecToggle
This proto is used to create a small view containing the text and shape recognition buttons, as are shown on the status bar of the Notepad. These buttons are used to turn on or off text and shape recognition for elds that have the vAnythingAllowed recognition ag set. When the user writes or draws in a eld, the system checks if the vAnythingAllowed ag is set for that eld. If it is, then the state of the recognition buttons controls what can be recognized in that eld. If both buttons are turned off, then no recognition is done. When this view is opened, the buttons will be set to reect the global settings in the Newton system; these are the same settings shown in the Notepad. If the user changes the button settings, they are changed for the entire system. Wherever this proto is used, it controls and reects the global state of the recognizers, so the settings stay in synchronization across all applications. Another feature of the protoRecToggle proto is that the user can doubletap on the protoRecToggle view to instantly open the Recognizers item in Preferences. This provides an easy way for the user to change other recognition settings. Here is an example:

protoRecToggle View

You dont have to set any slots when you use the protoRecToggle proto. It is designed to be added as a child of a view based on the protoStatus proto. When used in this way, it is automatically positioned in the status bar; its viewBounds slot is ignored. Note that you must add it as the rst button

Control Protos

3-57

CHAPTER

Working With Proto Templates

to the status bar so that other buttons are positioned correctly, since it will always position itself rst no matter in what order you add it. The protoRecToggle proto is based on a view of the clView class. It has two child views that implement the text and shape recognition buttons. Here is an example of a template using protoRecToggle: // Make a child of a protoStatus view recButtons := {_proto: protoRecToggle} // nothing else needed

protoSlider
This proto is used to create a user-settable gauge view, which looks like an analog bar gauge with a draggable diamond-shaped knob. Here is an example:

Knob

If you want to have a read-only gauge, use the protoGauge proto. These slots are of interest: Set to the size and location where you want the gauge to appear. viewValue Set this slot to give the gauge an initial value, if you know it ahead of time. If you need to calculate the initial value at run time, set this slot within the viewSetupFormScript. This value must be an integer between minValue and maxValue, inclusive. During execution, the viewValue slot stores the current gauge setting by interpolating between minValue and maxValue. viewSetupFormScript Required. Use this method to set the initial value of the viewValue slot at run time, or to do any other processing you need to do before the view is instanviewBounds

3-58

Control Protos

CHAPTER

Working With Proto Templates

changedSlider

minValue

maxValue

tiated. If you do not want to do anything in this method, you MUST still supply it, but just dene it as nil. Required. This method is called once each time the gauge is moved, after the pen is lifted from it. The current gauge setting is available in the viewValue slot. If the gauge was moved but reset back to its original value before the pen was lifted, this method is not called. This method is passed no parameters and the return value is ignored. If you do not want to do anything in this method, you MUST still supply it, but just dene it as nil. Optional. This species the minimum gauge value; the number set as the viewValue when the gauge reads fully to the left side. The default is zero, which you can change if you wish. Optional. This species the maximum gauge value; the number set as the viewValue when the gauge reads fully to the right side. The default is 100, which you can change if you wish. Optional. The default is true, which displays the gray background. If you set this slot to nil, the gray background is not displayed. Optional. This method is called whenever the value of the viewValue slot changes. It is provided so you can dynamically track the changes as the slider is moved and take action based on the current value. This method is called repeatedly as the gauge knob is dragged. This method is passed no parameters and the return value is ignored.

gaugeDrawLimits

trackSlider

The following additional methods are dened internally: viewChangedScript and viewFinalChangeScript. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewChangedScript()), otherwise the proto may not work as expected.

Control Protos

3-59

CHAPTER

Working With Proto Templates

Note that you cannot dynamically change the value of the minValue and maxValue slots at run time, except within the viewSetupFormScript method. If you need to change the value of these slots, you must close the view, change the values, then reopen the view. The protoSlider uses the protoGauge as its proto; and protoGauge is based on a view of the clGaugeView class. Here is an example of a template using protoSlider: SoundSetter := {... _proto: protoSlider, viewBounds: RelBounds( 12, -21, 65, 9), viewJustify: vjParentBottomV, maxValue: 4, viewSetupFormScript: func() self.viewValue := userConfiguration.soundVolume, changedSlider: func() begin SetVolume(viewValue); :SysBeep(); end, ...}

protoTextButton
This proto is used for a rounded rectangle button with text inside it. The text is centered vertically and horizontally. Here is an example:

3-60

Control Protos

CHAPTER

Working With Proto Templates

These slots are of interest: Set to the size and location where you want the button to appear. viewFlags The default setting is vVisible + vReadOnly + vClickable. text A string that is the text inside the button. buttonClickScript A method that is called when the button is tapped. This method is passed no parameters and the return value is ignored. buttonPressedScript Optional. This method is called repeatedly as long as the button is pressed (the pen is held down within it). This method is passed no parameters and the return value is ignored. viewFont Optional. The default font for the text is ROM_fontSystem9Bold. viewFormat Optional. The default setting is vfFillWhite + vfFrameBlack + vfPen(2) + vfRound(4). viewJustify Optional. The default setting is vjCenterH + vjCenterV + oneLineOnly. To make a button with multiple text lines, instead of oneLineOnly, use the noLineLimits flag. viewTransferMode Optional. The default transfer mode is modeOr. viewBounds Note that the viewClickScript method is used internally in the protoTextButton and should not be overridden. You should use the buttonClickScript method to handle a tap event. (The buttonClickScript message is sent from within the viewClickScript method specically to provide a mechanism for you to handle the event.) Note that inking is automatically turned off when the button is tapped. The protoTextButton is based on a view of the clTextView class. This view is simply a clParagraphView that is read-only and it supports no tabs or multi-styled text.

Control Protos

3-61

CHAPTER

Working With Proto Templates

Here is an example of a template using protoTextButton: aButton := {... _proto: protoTextButton, viewFont: ROM_fontSystem12Bold, text: "Hit me", buttonClickScript: func() Print("ouch!"); // a handy way to fit a button around a string viewSetupFormScript: func() viewbounds := RelBounds( 150, 60, StrFontWidth( self.text, viewFont )+12, FontHeight( viewFont ) ); ...}

Roll Protos
These protos are used to implement roll views. A roll view is a view that consists of several discrete subviews, arranged vertically, one above the other. The roll can be viewed in overview mode, where each subview is represented by a single-line description. Any single view or all views can be expanded to full-size.

protoRoll
This proto is used to create a roll-like view that includes a series of individual items (other views) which the user can see either as a collapsed list of one-line overview descriptions or as full-size views. When one of the overview lines is tapped, all of the full-size views are displayed, with the one that was tapped shown at the top of the protoRoll view. Each view occupies the full width of the protoRoll and the views are arranged one above the other.

3-62

Roll Protos

CHAPTER

Working With Proto Templates

The user can then scroll through all of the expanded views by using the universal scrollers (up and down arrows). The user can also tap the Overview button (the dot between the up and down arrows) to get back to the overview list, and then select another item. In the collapsed view, the items in the overview list are preceded by bullets. Here is an example:

These slots are of interest: items An array of templates that correspond to the items in the list. Each of these should use protoRollItem as its proto. See the section on protoRollItem for details. Because this slot cannot usually be set until run time, you should set it in the viewSetupFormScript method. The default setting is vApplication + vClipping. Do not change these ags, but you can add others if you wish. By default, the bounds are set to the entire screen, beginning 16 pixel lines down from the top. This would leave room for a title at the top if the protoRoll was placed inside of a protoApp. Optional. If this slot is set to a non-nil value, the roll is initially displayed in a collapsed state; that is, only the list of one-line overviews is displayed. If this slot is nil, the roll is initially displayed in an expanded state. The default is nil. This slot is used only when allCollapsed is set to nil; that is, when the roll is initially displayed in an expanded state. Items from the items array are displayed in the roll beginning with the item at this index.

viewFlags

viewBounds

allCollapsed

index

Roll Protos

3-63

CHAPTER

Working With Proto Templates

declareSelf

Do not change. This slot is set by default to 'roll. This identies the view that should receive scroll and overview events. This view must also be immediately enclosed by a parent view that has the vApplication view ag set, in order for scrolling and overview handling to operate properly.

The following additional methods are dened internally: viewSetupChildrenScript, viewScrollUpScript, viewScrollDownScript, viewOverviewScript, GetOverview, and ShowItem. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewSetupChildrenScript()), otherwise the proto may not work as expected. The protoRoll is based on a view of the clView class. It has no predened child views, though they are dynamically created at run time from the view templates you place in the items slot. A limitation of the protoRoll is that the overview view (collapsed view) cannot be scrolled by the user; and it can display a maximum of 16 items. Items beyond those shown can be accessed by expanding the 16th item and scrolling the expanded views to the desired one. Here is an example of a template using protoRoll: myRoll := {... _proto: protoroll, declareSelf: 'roll, allCollapsed: true, index: 0, items: [ {_proto:protoRollItem, height:50, overview:"Overview of item 1", viewBounds:{left:0,top:0,right:0,bottom:50},

3-64

Roll Protos

CHAPTER

Working With Proto Templates

stepChildren:[{_proto:protoStaticText, text:"This is the first test roll item", viewBounds:{left:0,top:0,right:0,bottom:0}, viewfont:ROM_fontSystem12 }], }, {_proto:protoRollItem, height:200, overview:"Overview of item 2", viewBounds:{left:0,top:0,right:0,bottom:200}, stepChildren:[{_proto:protoStaticText, text:"This is the second test roll item", viewBounds:{left:0,top:0,right:0,bottom:0} }], }, {_proto:protoRollItem, height:200, overview:"Overview of item 3", viewBounds:{left:0,top:0,right:0,bottom:200}, stepChildren:[{_proto:protoStaticText, text:"This is the third test roll item", viewBounds:{left:0,top:0,right:0,bottom:0} }], }, {_proto:protoRollItem, height:50, overview:"Overview of item 4", viewBounds:{left:0,top:0,right:0,bottom:50}, stepChildren:[{_proto:protoStaticText, text:"This is the fourth test roll item", viewBounds:{left:0,top:0,right:0,bottom:0} }], }], ...};

Roll Protos

3-65

CHAPTER

Working With Proto Templates

protoRollBrowser
This proto is similar to protoRoll, except that the protoRollBrowser is an entirely self-contained application. It is based on the protoApp proto, so it has a title and a status bar. It doesnt need to be contained in another view. The protoRollBrowser works exactly like the protoRoll in other respects. Here is an example of a protoRollBrowser view in collapsed and expanded states:
Collapsed View Expanded View

These slots are of interest: viewBounds Set to the size and location where you want the roll to appear. By default it is centered horizontally within its parent view.

3-66

Roll Protos

CHAPTER

Working With Proto Templates

title

rollItems

rollCollapsed

rollIndex

viewJustify viewFormat

declareSelf

A string that is the title. This title appears in a title bar at the top of the roll. (It uses protoTitle to create the title.) An array of templates that correspond to the items in the list. Each of these should use protoRollItem as its proto. See the section on protoRollItem for details. Because this slot cannot usually be set until run time, you should set it in the viewSetupFormScript method. Optional. If this slot is set to a non-nil value, the roll is initially displayed in a collapsed state; that is, only the list of one-line overviews is displayed. If this slot is nil, the roll is initially displayed in an expanded state. The default is true. This slot is used only when rollCollapsed is set to nil; that is, when the roll is initially displayed in an expanded state. Items from the items array are displayed in the roll beginning with the item at this index. Optional. The default setting is vjParentCenterH. Optional. The default setting is vfFillWhite + vfFrameBlack + vfPen(1) + vfInset(1) + vfShadow(1). Do not change. This slot is set by default to 'base. This identies the view to be closed when the user taps the close box.

The protoRollBrowser uses the protoApp proto. The protoRollBrowser has the following three child views:
n

A roll view, based on the protoRoll proto. This view occupies most of the parent view, except for the title and status bar areas. A title, based on the protoTitle proto. A status bar, based on the protoStatus proto.

n n

Roll Protos

3-67

CHAPTER

Working With Proto Templates

A limitation of the protoRollBrowser is that the overview view (collapsed view) cannot be scrolled by the user; and it can display a maximum of 16 items. Items beyond those shown can be accessed by expanding the 16th item and scrolling the expanded views to the desired one. Here is an example of a template using protoRollBrowser: myRollBrowser := {... _proto: protorollbrowser, title: "My RollBrowser", rollCollapsed: true, declareSelf: 'base, rollitems: [ {_proto:protoRollItem, height:50, overview:"Overview of item 1", viewBounds:{left:0,top:0,right:0,bottom:50}, stepChildren:[{_proto:protoStaticText, text:"This is the first test roll item", viewBounds:{left:0,top:0,right:0,bottom:0}, viewfont:ROM_fontSystem12 }], }, // ... and so on ], ...};

protoRollItem
This proto is used for one of the views in a roll (based on protoRoll or protoRollBrowser). You should specify an array containing one or more views based on protoRollItem. Each item in the array represents one of the views in the roll. These slots are of interest: overview A string that is the one-line overview to be displayed for this view when the roll is collapsed and only the overview list is shown.

3-68

Roll Protos

CHAPTER

Working With Proto Templates

height viewBounds

stepChildren

viewFormat viewJustify

Set to the height of the view, in pixels. Typically, you set the bounds to 0, 0, 0, height. The rst three bounds parameters are not needed because the view is positioned below the previous child and fully horizontally justied within the roll. However, you can specify values other than zero to indent the view from the sides of its parent or to separate it from its preceding sibling, but keep in mind how the viewJustify setting affects the interpretation of the viewBounds values. For more information, see the section viewJustify Slot beginning on page 2-20. An array containing one or more child views that belong to the view that is this particular roll item. These are shown when this item is expanded (tapped by the user, or scrolled to after the roll has already been expanded). Typically, each child view uses a proto and can include whatever slots are important for use with its particular proto. For each child view, you MUST specify a viewbounds frame that contains a zero for each slot. Optional. The default setting is vfFillWhite + vfFrameBlack + vfPen(1). Optional. The default setting is vjSiblingBottomV + vjParentFullH.

The protoRollItem is based on a view of the class clView. Note that the protoRollItem proto is not used by picking it from the view palette in NTK. You use this proto by writing a textual description of your template, referring to this proto in the _proto slot of your template frame. You write one template frame for each item to be shown in the roll, and place them all in an array in the items slot of the roll. See protoRoll for an example.

Roll Protos

3-69

CHAPTER

Working With Proto Templates

Miscellaneous Protos
This section describes other protos.

protoBorder
This is simply a view lled with black. This view can be used as a border, or as a line, or anywhere a black rectangle is needed. Here is an example:

These slots are of interest: viewBounds viewFlags viewFormat Set to the size and location where you want the border to appear. The default setting is vVisible. Optional. The default setting is vfFillBlack.

The protoBorder is based on a view of the clView class. Here is an example of a template using protoBorder: theBorder := {... _proto: protoBorder, viewBounds: SetBounds( 0, 0, 0, 2 ), // 2-pixel wide line viewJustify: vjParentFullH, ...}

protoDivider
This proto is used to create a divider bar that extends the whole width of its parent view. The divider bar consists of a text string near the left end of a thick line. Here is an example:

3-70

Miscellaneous Protos

CHAPTER

Working With Proto Templates

These slots are of interest: viewBounds Set to the size and location where you want the divider bar to appear. By default, the divider extends the whole width of its parent view (see viewJustify). The default setting is vVisible + vReadOnly. In most cases you wont need to change this. A string that is the text on the divider bar. Optional. The default font is ROM_fontSystem9Bold. Optional. The height of the divider view defaults to the height of the font used. If you want a taller divider view, set this slot to a greater value. Optional. The default setting is vjParentFullH. Optional. The default setting is vfNone. In most cases you wont need to change this.

viewFlags title viewFont titleHeight

viewJustify viewFormat

Additionally, the viewSetupChildrenScript method is dened internally. If you need to use this method, be sure to call the inherited method also (for example, inherited:?viewSetupChildrenScript()), otherwise the proto may not work as expected. The protoDivider is based on a view of the clView class. It has the following two child views declared in itself:
n

divider. This child view uses the protoBorder proto. It is used for the solid black line. dividerText. This child view is based on a view of the clTextView class (simply a clParagraphView that is read-only and it supports no tabs or multi-styled text). It is used for the text label on the divider bar.

Here is an example of a template using protoDivider: protoCoverBorder := {... _proto: protoDivider, viewFont: ROM_fontSystem18Bold, title: "COVER SHEET", }

Miscellaneous Protos

3-71

CHAPTER

Working With Proto Templates

protoGauge
This proto is used to create a read-only gauge view, which looks like an analog bar gauge. Here is an example:

If you want to have a user-settable gauge, use the protoSlider proto. These slots are of interest: Set to the size and location where you want the gauge to appear. viewValue Set this slot to give the gauge an initial value, if you know it ahead of time. If you need to calculate the initial value at run time, set this slot within the viewSetupFormScript. This value must be an integer between minValue and maxValue, inclusive. During execution, the viewValue slot stores the current gauge setting by interpolating between minValue and maxValue. viewSetupFormScript Required. Use this method to set the initial value of the viewValue slot at run time, or do any other processing you need to do before the view is instantiated. If you do not want to do anything in this method you MUST still supply it, but just dene it as nil. minValue Optional. This species the minimum gauge value; the number set as the viewValue when the gauge reads fully to the left side. The default is zero. maxValue Optional. This species the maximum gauge value; the number set as the viewValue when the gauge reads fully to the right side. The default is 100. gaugeDrawLimits Optional. The default is true, which displays the gray background. If you set this to nil, the gray background is not displayed. viewBounds

3-72

Miscellaneous Protos

CHAPTER

Working With Proto Templates

Note that you cannot change the value of the minValue and maxValue slots at run time, except within the viewSetupFormScript method. If you need to change the value of these slots, you must close the view, change the values, then reopen the view. The protoGauge is based on a view of the clGaugeView class. Here is an example of a template using protoGauge: BatteryGauge := {... _proto: protoGauge, viewBounds: RelBounds( 157, -21, 55, 9), viewJustify: vjParentBottomV, viewSetupFormScript: func() self.viewvalue := BatteryLevel(0), ...}

protoGlance
This proto is used for a text view that closes itself automatically after it has been shown for a brief period. Also, if the user taps on the view, it will be closed immediately. Here is an example:

These slots are of interest: viewBounds text viewJustify viewFormat viewFont Set to the size and location where you want the view to appear. A string that is the text to appear in the view. Optional. The default setting is vjCenterV + vjLeftH. Optional. The default setting is vfFillWhite + vfPen(2) + vfFrameBlack + vfInset(1). Optional. The default font is ROM_fontSystem9Bold.

Miscellaneous Protos

3-73

CHAPTER

Working With Proto Templates

Optional. The default effect is fxRight + fxRevealLine. viewIdleFrequency Optional. This sets the length of time that the view is to remain open, in milliseconds. The default is 3000 milliseconds (three seconds). Specify an integer greater than zero. viewEffect The following additional methods are dened internally: viewSetupDoneScript, viewClickScript, and viewIdleScript. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewClickScript()), otherwise the proto may not work as expected. The protoGlance is based on a view of the clTextView class. This kind of view is simply a clParagraphView that is read-only and it supports no tabs or multi-styled text. Typically a protoGlance view is hidden until the user performs an action such as tapping on a button. Then, send the Open message to the protoGlance view to cause it to show itself. Here is an example of a template using protoGlance (and the button that opens the glance view): myGlance := {... _proto: protoglance, text: "Just a glance...", viewIdleFrequency: 5000, viewfont: ROM_fontSystem9Bold, viewJustify: vjCenterV+vjCenterH, ...}; showGlance := {... // Button that opens the glance view _proto: prototextbutton, text: "Show it", buttonClickScript: func() myGlance:Open(), };

3-74

Miscellaneous Protos

CHAPTER

Working With Proto Templates

protoKeyboard
This proto is used to create a keyboard view that oats above all other views. It is centered within its parent view and appears in a location that won't obscure the key-receiving view (that is, the view to which the keystrokes from the keyboard are to be sent). The user can drag the keyboard view by its edge to a different location, if desired. Here is an example:

This proto enables a blinking text insertion bar in the key-receiving view while the keyboard is displayed. Characters corresponding to tapped keys are inserted in the key-receiving view at the insertion bar location. The blinking insertion bar is disabled when the keyboard view is closed. These slots are of interest: saveBounds Set to the size and location where you want the keyboard view to appear. (This is used as the viewBounds value for the keyboard view.) Note that the keyboard view may be displayed above or below the location you specify, if it must be moved so as not to obscure the key-receiving view. (You can freeze it in place by using the freeze slot.) Optional. If set to true, prevents automatic movement of the keyboard view. This slot is set to nil by default, allowing movement of the keyboard view so as not to obscure the key-receiving view, if it would be blocked by the bounds you specied for the keyboard.

freeze

The following additional methods are dened internally: viewSetupFormScript, viewClickScript, and viewQuitScript. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewClickScript()), otherwise the proto may not work as expected.

Miscellaneous Protos

3-75

CHAPTER

Working With Proto Templates

This proto is used in conjunction with protoKeypad to implement a oating keyboard. This proto denes the parent view, and protoKeypad is a child view that denes the key characteristics. The protoKeyboard itself uses the protoFloater proto, which in turn is based on a view of the class clView.

protoKeypad
This proto is used to dene key characteristics for a keyboard view ( clKeyboardView class). These slots are of interest: keyDefinitions An array that denes the layout of the keys. Refer to the clKeyboardView description in the section Keyboard View (clKeyboardView) beginning on page 4-21. viewFont Optional. The default font is ROM_fontSystem9Bold. viewFormat Optional. The default setting is vfFillWhite. keyArrayIndex Optional. Set by this proto to zero. keyHighlightKeys Optional. Set by this proto to nil. keyResultsAreKeycodes Optional. Set by this proto to true. keyReceiverView Optional. Set by this proto to 'viewFrontKey. keySound Optional. Set by this proto to typewriter. keyPressScript Optional. This method is called whenever a key is pressed. The key result of the key pressed is passed as a parameter to this method. If this method is not supplied, the key result is converted (if possible) into a sequence of characters which are posted as key events to the key receiver view. The protoKeypad is based on a view of the class clKeyboardView. For more information about the key slots listed above, refer to the section Keyboard View (clKeyboardView) beginning on page 4-21.

3-76

Miscellaneous Protos

CHAPTER

Working With Proto Templates

You use this proto along with protoKeyboard to implement a oating keyboard. The view using the protoKeypad proto should be a child of the view using the protoKeyboard proto.

protoLabeledBatteryGauge
This proto is used to create a read-only gauge view that graphically shows the amount of power remaining in the system battery. The battery level is checked every 10 seconds and the gauge is updated, if necessary. If the Newton is plugged in and the battery is charging, a charging symbol is shown instead of the gauge. Here is an example:
Battery gauge Battery charging

This slot is of interest: viewBounds Set to the size and location where you want the gauge to appear. The gauge lls the entire width of the view.

The following additional methods are dened internally: viewSetupDoneScript, viewSetupChildrenScript, viewIdleScript, and ReadBattery. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewSetupDoneScript()), otherwise the proto may not work as expected. The protoLabeledBatteryGauge uses an internal proto, protoBatteryGauge, as its prototype; and protoBatteryGauge is based on a view of the clView class. The protoBatteryGauge has two children, the gauge or charging symbol and the label. Here is an example of a template using protoLabeledBatteryGauge: BatteryGauge := { viewBounds: {left: 58, top: 106, right: 186, bottom: 130}, _proto: protolabeledbatterygauge, // no other slots needed };

Miscellaneous Protos

3-77

CHAPTER

Working With Proto Templates

protoPrintFormat
This proto is used to create a routing format for printing, faxing, mailing, or other similar kinds of routing. The view based on this proto is automatically sized to t the dimensions of a page on the output device to which it is being routed. The data to be routed are placed as child views of the protoPrintFormat view. For more information about routing and how to create and use routing formats, see the chapter Routing. These slots are of interest: printNextPageScript Required. You must supply this method that is called by the system after it has routed a page. This method is passed no parameters. It should return nil if there are no more pages to route, or true if there are more pages to route. Typically, in this method, you set up new child views and send the RedoChildren message (which sends the viewSetupChildrenScript message) to create the new child views representing the next page of data to route. viewFlags The default setting is vVisible + vReadOnly. viewSetupChildrenScript Optional. Typically, you use this method to set up the child views containing the data to be routed. When this method is called initially, you should set up the child views for the rst page to be routed, typically by setting the value of the stepChildren array. If you follow the guidelines for the printNextPageScript method by using RedoChildren, as a result the viewSetupChildrenScript method will be called for each subsequent page as well. Before you do anything in this method, dont forget to call the inherited method ( inherited:?viewSetupChildrenScript) so that the pageWidth and pageHeight slots are set. viewJustify Optional. The default setting is vjParentFullH + vjParentFullV. 3-78

Miscellaneous Protos

CHAPTER

Working With Proto Templates

viewFont pageWidth pageHeight

Optional. The default font is userFont12. The viewSetupFormScript method of the proto sets this slot to the width, in pixels, of the view. The viewSetupFormScript method of the proto sets this slot to the height, in pixels, of the view

The following additional methods are dened internally: viewSetupFormScript and viewSetupChildrenScript. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewSetupFormScript()), otherwise the proto may not work as expected. The protoPrintFormat is based on a view of the class clView.

protoSetClock
This proto is used to create a clock with which the user can set a time. The user sets the hour by tapping the inner circle where the hour hand should be positioned and by tapping the outer circle where the minute hand should be positioned. Here is an example:

These slots are of interest: viewBounds hours minutes TimeChanged The clock size is xed at 64 by 64 pixels. Initially set to nil. This slot is updated with the new hour when the user sets the hour hand. Initially set to nil. This slot is updated with the new minute time when the user sets the minute hand. This message is sent to the view when the user changes the time on the clock. It takes no parameters. If nothing else, you should at least include the following code so that the clock draws properly: self:Dirty().

Miscellaneous Protos

3-79

CHAPTER

Working With Proto Templates

viewFlags viewFormat

The default setting is vVisible + vClickable + vStrokesAllowed. Optional. The default setting is vfNone.

The following additional methods are dened internally: viewDrawScript, viewStrokeScript, Diff, Distance, DrawHand, DrawHilite, and FastEnoughAtan. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewDrawScript()), otherwise the proto may not work as expected. The protoSetClock is based on a view of the clPictureView class. Here is an example of a template using protoSetClock: clock := {... _proto: protosetclock, hours: nil, // updated when a new time is set minutes: nil, // updated when a new time is set timeChanged: func() begin // do this so the old hands are erased... self:Dirty(); // this is just for fun, put your own stuff here... print("H:" && hours && "M:" && minutes); end, viewSetupFormScript: func() // show the current time begin local t:=Time(); self.hours:=(t DIV 60) MOD 24; self.minutes:=t MOD 60; end, ...};

3-80

Miscellaneous Protos

CHAPTER

Working With Proto Templates

protoStaticText
This proto is used for static text. It denes a one-line paragraph view that is read-only and left-justied. Here is an example:
Static text

These slots are of interest: viewBounds Set to the location where you want the text to appear. viewFlags The default setting is vVisible + vReadOnly. In most cases you wont need to change this. text A string that is the text you want to display. viewFont Optional. The default font is ROM_fontSystem9Bold. This slot is ignored if the styles slot is present. viewJustify Optional. The default setting is vjLeftH + oneLineOnly. viewFormat Optional. The default is vfNone. viewTransferMode Optional. The default transfer mode is modeOr. tabs Optional. An array of as many as eight tab-stop positions, in pixels. For example: [10, 20, 30, 40]. styles Optional. An array of alternating run lengths and font information, if multiple font styles are used for the text. The rst element is the run length (in characters) of the rst style run, and the second element is the font style of that run. The third element is the run length of the second style run, and so on. All of the run lengths must add up to the total text length. If the text is all in a single

Miscellaneous Protos

3-81

CHAPTER

Working With Proto Templates

font, the font in the viewFont slot species the font style, and the styles slot is not needed. For information on how to specify a font in the styles array, see the section Specifying a Font beginning on page 4-11. The protoStaticText is based on a view of the clParagraphView class. Here is an example of a template using protoStaticText: heading := {... viewbounds: RelBounds( 30, 15, 170, 50), _proto: protoStaticText, viewJustify: vjCenterH+vjTopV, viewFont: ROM_fontSystem10, text: "Pick your favorite color:", ...}

protoStatus
This proto is used to create a status bar at the bottom of a view. The status bar includes a large close button at the right side and an analog clock at the left side. If the user taps on the analog clock, a digital clock is displayed for three seconds. Here is an example:

The viewJustify ags for this view are set so that the status bar always appears at the bottom of its parent view and it always occupies the full width of the parent view. Instantiators are not required to set any slots. However, the application base view in which the protoStatus view is included must include this slot: declareSelf: 'base This identies the view that should be closed when the close box in the status bar is tapped.

3-82

Miscellaneous Protos

CHAPTER

Working With Proto Templates

The protoStatus is based on another proto called protoStatusBar, which is based on a view of the clView class. The protoStatusBar contains the following two child views:
n

A small round analog clock that appears at the side left of the view. The clock is based on a view of the clView class. A digital clock display that slides out from the analog clock when the user taps on the analog clock. This view is hidden automatically after three seconds. This view is based on the protoGlance proto.

The protoStatus itself has one child view, the close button, which appears at the right side of the view. The close button is based on the protoLargeCloseBox proto. Here is an example of a template using protoStatus: theStatus := {_proto: protostatus} // nothing else needed // base app must include this slot: declareSelf: 'base

protoStatusBar
This proto is used to create a status bar at the bottom of a view. It is identical to protoStatus, except it does not include a close button. Here is an example:

The viewJustify ags for this view are set so that the status bar always appears at the bottom of its parent view and it always occupies the full width of the parent view. Instantiators are not required to set any slots. The protoStatusBar is based on a view of the clView class. The protoStatusBar contains the following two child views:
n

A small round analog clock that appears at the side left of the view. The clock is based on a view of the clView class.

Miscellaneous Protos

3-83

CHAPTER

Working With Proto Templates

A digital clock display that slides out from the analog clock when the user taps on the analog clock. This view is hidden automatically after three seconds. This view is based on the protoGlance proto.

protoTable
This proto is used to create a simple one-column table of text. Each of the table items can be selected (highlighted) by tapping on it. Here is an example:

These slots are of interest: Set to the size and location where you want the table to appear. def The table denition frame. Initially, you should set this to protoTableDef which is the proto frame. Then in the viewSetupFormScript method, you can change individual items. The protoTableDef frame is documented beginning on page 3-87. viewSetupFormScript In this method you should clone the table denition frame, def, if you want to change any of the values in the frame at run time. scrollAmount Optional. The table will scroll one row at a time when the user taps a scroll button. If you want it to scroll more rows at a time, specify the number of rows here. viewFormat Optional. The default setting is vfFillWhite + vfPen(1) + vfFrameBlack. currentSelection Contains a string that is the text of the currently selected cell. If multiple selections are allowed, this string is the text of the last cell selected. viewBounds

3-84

Miscellaneous Protos

CHAPTER

Working With Proto Templates

An array of indexes of selected cells. These are indexes into the def.tabValues array. declareSelf Do not change. This slot is set by default to 'tabbase. This identies the view for scrolling and other internal purposes. selectThisCell This method is dened internally and is called when the user taps on a cell in the table.The method is passed a single parameterthe child view representing the cell that was tapped. If you want to be notied whenever the user taps on a cell, you can override this method. However, you MUST call the inherited method before doing anything else in your own method. The example beginning on page 3-86 shows how to do this. selectedCells The following additional methods are dened internally: viewSetupChildrenScript, viewScrollDownScript, viewScrollUpScript, and updateSelection. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewSetupChildrenScript()), otherwise the proto may not work as expected. The protoTable includes viewScrollUpScript and viewScrollDownScript methods to handle scrolling. However, a view based on protoTable wont receive these system messages directly. To support scrolling, your application base view (which typically receives these messages from the system) should simply pass them along to the protoTable view.
Note

Because of the way scrolling is handled in the proto, it is possible that the last item in the table may not show up in the view when the table is scrolled to the bottom. You can x this problem by overriding the viewScrollDownScript method in the proto with a new method. The new viewScrollDownScript method is shown in the following example. u

Miscellaneous Protos

3-85

CHAPTER

Working With Proto Templates

Here is an example of a template using protoTable: theTable := {... _proto: protoTable, def: protoTableDef, viewSetupFormScript: func() begin def := Clone (def); def.tabValues := ["foo", "bar", "baz", "qux", "4", "5", "6", "7", "8", "9"]; // tabWidths must be =< the view width-2 def.tabWidths := viewBounds.right-viewBounds.left-2; def.tabDown := 10; end, selectThisCell: func(viewTapped) begin // first you MUST call the inherited method inherited:selectThisCell(viewTapped); // here you can do your own things ... end, // Use this method to fix scroll-down problem viewScrollDownScript: func() begin local biggestTop; local temp := ((viewBounds.bottom - viewBounds.top) / def.tabHeights); temp := if (temp - Floor(temp)) < 0.5 then Floor(temp) else Floor(temp) + 1 ; biggestTop := Max(0, def.tabDown - temp);

3-86

Miscellaneous Protos

CHAPTER

Working With Proto Templates

if vOrg < biggestTop then begin vOrg := vOrg + scrollAmount; if vOrg > biggestTop then vOrg := biggestTop ; tabbase:RedoChildren(); :updateSelection(); end; end, ...}; Here is the denition of protoTableDef: protoTableDef := { tabAcross: 1, tabDown: 0, tabWidths: 50, tabHeights: 0, tabProtos: protoTableEntry, tabValues: nil, tabValueSlot: 'text, tabSetup: func(childView, hIndex, vIndex) begin childView.hIndex := hIndex - 1;// Save for selection childView.vIndex := vIndex - 1; end, tabUniqueSelection: true // set to false for multiple selection indentX: 2, }

Miscellaneous Protos

3-87

CHAPTER

Working With Proto Templates

Here is a description of the slots in protoTableDef: The number of columns in the table. This must be set to one (1). Multi-column tables are not supported by protoTable. tabDown The number of rows in the table. tabWidths An integer giving the width of the single table column, in pixels. tabHeights An integer giving the height of a row, in pixels (constant for all rows). tabProtos Each row in the table is child view of the table. This slot holds either a reference to a template used to create the child views, or an array of references to templates. The default, protoTableEntry, is documented beginning on page 3-89. tabValues A value that is used as the value of each of the child views. Alternately , an array of values that are mapped to table cells. tabValueSlot A symbol naming the slot in each of the child views where that childs view value (specied in tabValues) is stored. (Remember to quote the symbol; for example, 'text.) For example, if the table consists of child views based on the clParagraphView class (the default), you would specify 'text for this slot, since the value of a clParagraphView is stored in its text slot. tabSetup A method that is called before each of the child views is instantiated. It is passed three parameters: a reference to the child view, the childs column number in the table, and the childs row number in the table. This allows you to do special initialization operations to each child view before it is instantiated. If you choose to override this method, call the inherited method also, like this: inherited:?tabSetup(childView, hIndex, vIndex). tabUniqueSelection A Boolean value. Set to true to allow only a single cell to be selected. Set to nil to allow multiple cells to be tabAcross

3-88

Miscellaneous Protos

CHAPTER

Working With Proto Templates

indentX
IMPORTANT

selected. Note that the proto does not support deselecting a selected cell by tapping it again. Reserved for internal use. Do not change.

If you allow multiple cell selection, your program will fail unless you ensure that the selectedCells slot is in RAM, since the proto attempts to add to this array. To make sure the slot is in RAM, use this code in the viewSetupFormScript method: self.selectedCells:=Clone(selectedCells);. s Here is a list of the important slots in protoTableEntry: clTextView (This view is simply a clParagraphView that is read-only and it supports no tabs or multistyled text.) viewFlags vVisible + vClickable + vReadOnly viewJustify vjLeftH + vjCenterV + oneLineOnly viewTransferMode modeOr text Holds the text shown in this view. viewClickScript Sets currentSelection in the parent view (the table) to the value of the text slot. Sends the selectThisCell message. viewHiliteScript Highlights self. viewClass The protoTextList is similar to the protoTable in that both can be used to present a scrolling list of text items to the user. However, protoTextList uses only a single view to hold all of the text items, while protoTable uses separate views for each item. Each proto has its advantages and disadvantages. The protoTextList may be faster because it uses just a single view, but the protoTable may be more versatile since each item is a separate view.

Miscellaneous Protos

3-89

CHAPTER

Working With Proto Templates

protoTextList
This proto is used to create a scrollable list of text items from which the user can choose an item by tapping it. The selected item is highlighted in the list. The user scrolls the list by tapping and dragging the pen either above or below the list. Here is an example:

These slots are of interest: viewBounds Set to the size and location where you want the list to appear. The value you set for the bottom bound is ignored. The bottom bound setting is calculated based on viewLines and viewFont. viewLines The number of lines to show in the list. This controls the height of the list view. listItems An array of strings that are the list items. One string is shown on each line in the list. This slot must be set in the viewSetupFormScript method. viewSetupFormScript In this method, you must do two things: set the value of the listItems slot and call the internal method SetupList. selection Optional. This slot controls what is highlighted when the list is rst displayed. If you set it to nil, nothing is highlighted. You can set it to the index of an item in the listItems array to highlight that item. The default setting is zero, highlighting the rst item. buttonClickScript Optional. This method is called after the pen is placed down and then lifted within the list. It is not called if the pen is lifted outside the bounds of the list. This method is passed one parameteran index into listItems of the selected item. 3-90

Miscellaneous Protos

CHAPTER

Working With Proto Templates

viewFont viewFormat

Optional. The default font is ROM_fontSystem9. Optional. The default setting is vfFillWhite + vfFrameBlack + vfPen(1).

The following additional methods are dened internally: viewClickScript, viewScrollDownScript, viewScrollUpScript, DoScrollScript, HiliteLine, DrawHilite, SetupList, and GetViewHeight. If you need to use one of these methods, be sure to call the inherited method also (for example, inherited:?viewClickScript()), otherwise the proto may not work as expected. The protoTextList is based on a view of the clView class. The protoTextList has a single child view, based on a view of the clTextView class, that displays the items in the list. You can add or remove items from the list during run time by adding or removing items from the listItems array and then sending the view the SetupList and RedoChildren messages, in that order. The protoTextList is similar to the protoTable in that both can be used to present a scrolling list of text items to the user. However, protoTextList uses only a single view to hold all of the text items, while protoTable uses separate views for each item. Each proto has its advantages and disadvantages. The protoTextList may be faster because it uses just a single view, but the protoTable may be more versatile since each item is a separate view. Here is an example of a template using protoTextList: theList := {... _proto: prototextlist, viewLines: 6, listItems: nil, viewSetupFormScript: func() begin // list of soups in internal store listItems := getstores()[0]:getsoupnames(); :SetupList(); // Always must call this internal method end,

Miscellaneous Protos

3-91

CHAPTER

Working With Proto Templates

viewfont: simpleFont10, buttonClickScript: func(textIndex) begin print("Selected the following index =" &&textIndex); end, ...};

protoTitle
This proto is used to create a title centered in a black rounded rectangle at the top of a view. Here is an example:
Title

These slots are of interest: A string that is the title. Optional. The default font is ROM_fontSystem10Bold. Optional. The height of the title view (black rectangle) defaults to the height of the font used. If you want a taller title view, set this slot to a greater value. viewJustify Optional. The default setting is vjParentCenterH + vjParentTopV + vjCenterV + vjCenterH. viewFormat Optional. The default setting is vfFillBlack + vfRound(3). viewTransferMode Optional. The default transfer mode is modeBic. title viewFont titleHeight Additionally, the viewSetupFormScript method is dened internally. If you need to use this method, be sure to call the inherited method also (for example, inherited:?viewSetupFormScript()), otherwise the proto may not work as expected. 3-92

Miscellaneous Protos

CHAPTER

Working With Proto Templates

The protoTitle is based on a view of the clTextView class. This kind of view is simply a clParagraphView that is read-only and it supports no tabs or multi-styled text. Here is an example of a template using protoTitle: myTitle := {... _proto: protoTitle, titleHeight: 18, title: "Preferences" ...}

Creating Custom Protos


In developing your own views, you may nd that you frequently use certain kinds of basic templates for which there are no built-in protos. In such cases, you can create your own protos and use them just as you would use the built-in protos. To help you see what an actual proto denition looks like, here are the protoCloseBox and protoStaticText templates: protoCloseBox := { _proto: protoPictureButton, viewJustify: vjParentBottomV+vjParentRightH, viewBounds: PixBounds(goAwayBitmap, -14, -14), viewFormat: 0, icon: goAwayBitmap, buttonClickScript: func() base:Close(),

Creating Custom Protos

3-93

CHAPTER

Working With Proto Templates

debug: "protoCloseBox", } protoStaticText := { viewClass: clParagraphView, viewBounds: nil, viewFlags: vVisible+vReadOnly, viewFormat: vfNone, viewJustify: vjLeftH+oneLineOnly, viewFont: ROM_fontsystem9Bold, viewTransferMode: modeOr, styles: nil, tabs: nil, text: "", debug: "protoStaticText", } In these examples, you can see that protos sometimes use other protos. Also, for slots that need to be set by the instantiator, a dummy value (nil) is used. Protos provide only the bare minimum of slots needed. Instantiators should provide implementation-specic slots, and can override any of the slots in the proto by redening them. Refer to Newton ToolKit Users Guide for specic instructions on how to create custom protos using the Newton ToolKit.

3-94

Creating Custom Protos

CHAPTER

Working With Proto Templates

Summary of Prototypes
This section contains a list of the prototypes described in this chapter Container Protos protoApp protoDrawer protoFloater protoFloatNGo Input Protos protoDateExpando protoExpandoShell protoInputLine protoLabelInputLine protoPhoneExpando protoTextExpando Control Protos protoActionButton protoCheckbox protoCloseBox protoFilingButton protoFolderTab protoLabelPicker protoLargeCloseBox protoPicker protoPictIndexer protoPictRadioButton protoPictureButton protoRadioButton protoRadioCluster

Summary of Prototypes

3-95

CHAPTER

Working With Proto Templates

protoRCheckbox protoRecToggle protoSlider protoTextButton Roll Protos protoRoll protoRollBrowser protoRollItem Miscellaneous Protos protoBorder protoDivider protoGauge protoGlance protoKeyboard protoKeypad protoLabeledBatteryGauge protoPrintFormat protoSetClock protoStaticText protoStatus protoStatusBar protoTable protoTextList protoTitle

3-96

Summary of Prototypes

CHAPTER

Working with View Classes

This chapter includes a detailed description of each of the primitive view classes available in the system. Every view that can be created on the Newton is ultimately based on one of these view classes. In many cases, you will be able to use system protos (as described in the chapter Working With Proto Templates) in developing your templates. However, protos are not available for every possible need, so you will also need to know how to use the primitive view classes themselves to build some of your own templates. The slots common to all views ( viewBounds, viewFlags, viewFormat, viewJustify, and so on) are listed where they are used in the different view classes, but these slots are not described in detail in this chapter. You can nd detailed descriptions of these slots in the section Dening View Characteristics beginning on page 2-9.

Generic Container View (clView)


The clView view class is the base view class. It implements a generic view that has no special characteristics or specic kind of data associated with it. This view class does not support recognition, gestures, or user input of any kind. 4-1

Generic Container View (clView)

CHAPTER

Working with View Classes

This view class is typically used as a simple container view that includes other more specialized views. Most applications use a view of this type as the application base view. It serves to group all of the other views into a single hierarchy. These slots are of interest for a view of the clView class: viewBounds viewFlags viewFormat Set to the size and location where you want the view to appear. The default setting is vVisible. Optional. The default setting is nil.

Note that while the clView does not allow user input directly, the user can drag a clParagraphView or clPolygonView child out of a clEditView and drop it into the clView. The dragged and dropped view then becomes a child of the clView. However, once this occurs, the user can no longer edit the child view, because all entry ags are removed. Dragging to a clView works only if the clView has one of the recognition ags other than vClickable set. When a clView is used as the base view of an application, it typically includes many application-specic slots containing global data and methods for use by its child views (which automatically inherit parental slots if they are not overridden). Here is an example of a template dening a view of the clView class: sampleApp := {... viewClass: clView, viewBounds: {left:0, top:0, right:200, bottom:200}, viewFlags: vApplication+vClickable, viewFormat: vfFrameBlack+vfPen1+vfShadow1, viewJustify: vjParentCenterH, viewEffect: fxUp+fxSteps(8), declareSelf: 'base, // for closebox child // methods and other view-specific slots viewSetupFormScript: func()... ...}

4-2

Generic Container View (clView)

CHAPTER

Working with View Classes

General Input View (clEditView)


The clEditView view class is used for a view that can display and/or accept text and graphic data. Views of the clEditView class contain no data directly; instead, they have child views that contain the individual data items. Text items are contained in child views of the class clParagraphView and graphics are contained in child views of the class clPolygonView. A view of the clEditView class includes these features:
n

Automatic creation of clParagraphView or clPolygonView children as the user writes or draws in the view. These child views hold the data the user writes. Text and shape recognition, selection, and gestures such as scrubbing, copying to clipboard, pasting from clipboard, duplicating, and others, as controlled by the setting of the viewFlags slot. The initial recognition is handled by the clEditView. A child clParagraphView or clPolygonView is created and that child view handles subsequent editing of the data. Drag and drop handling. A child view can be dragged (moved or copied) out of the clEditView and dropped into another clEditView or clView, whose child it then becomes. Clipboard support. A clParagraphView or clPolygonView child view can be dragged (moved or copied) to the clipboard, from where it can be pasted into another clEditView or clView, whose child it becomes. Automatic resizing of clParagraphView and clPolygonView child views to accommodate added input. This feature is controlled by the vCalculateBounds flag in the viewFlags slot of those child views. Automatic addition of new words to existing paragraphs when they are written nearby. That is, words gravitate to become part of nearby paragraph views, unless they are written well away from any paragraph.

Views of the class clEditView are intended to be used for user input of text, shape, and ink data. Consequently, views of this class expect that any

General Input View (clEditView)

4-3

CHAPTER

Working with View Classes

child views have been dened and created at run time, not predened by templates created in NTK. If you need to include predened child views in a clEditView, use the viewSetupChildrenScript method of the clEditView to define the child views and set up the stepChildren array. You might need to do this, for example, if you store the data for child views in a soup, and you need to retrieve the data and rebuild the child views at run time. These slots are of interest for a view of the clEditView class: viewBounds viewFlags Set to the size and location where you want the view to appear. The default setting is vVisible. You will most likely want to set additional ags to control the recognition behavior of the view. Optional. The default setting is vfFillWhite+vfFrameBlack+ vfPen(1).

viewFormat

A view of the clEditView class can appear simply as a blank area in which the user can write information. Usually however, this type of view contains a series of horizontal dotted lines, like lined writing paper. The lines indicate to the user that the view accepts input. To create the lined paper effect, these slots must be set appropriately: viewFormat viewLineSpacing This sets the spacing between the lines, in pixels. viewLinePattern Optional. Sets a custom pattern that is used to draw the lines in the view. In the viewFormat slot editor in NTK, you must also set the Lines item to Custom to signal that you are using a custom pattern. (This sets the vfCustom<<vfLinesShift ag in the viewFormat slot.) Must include one of the vfLines ags. This activates the line display.

4-4

General Input View (clEditView)

CHAPTER

Working with View Classes

A pattern is simply an eight-byte binary data structure with the class 'pattern. You can use this NewtonScript trick to create binary pattern data structures on the y: myPattern := SetClass( Clone("\uAAAAAAAAAAAAAAAA"),'pattern); This code clones a string, which is already a binary object, and changes its class to 'pattern. The string is specied with hex character codes whose binary representation is used to create the pattern. Each two-digit hex code creates one byte of the pattern. The default font used for a clParagraphView created by a clEditView is the font set by the user on the Styles palette in the system. This is obtained from the userFont slot of the userConfiguration global variable. The default pen width for a clPolygonView created by a clEditView is the width set by the user on the Styles palette. This is obtained from the userPenSize slot of the userConfiguration global variable.
Note

Child views that are automatically created by a clEditView have the vNoScripts flag set in their viewFlags slot. This flag prevents system messages from being sent to a view. Normally, this is desirable for these automatically created views, which have no system message-handling methods, because the system can save time by not sending system messages to them. If later you want to use one of these views in a way that requires it to receive system messages, youll have to change the viewFlags slot to remove the vNoScripts flag. u Here is an example of a template dening a view of the clEditView class: editor := {... viewClass: clEditView, viewBounds: {left:0, top:0, right:200, bottom:200}, viewFlags: vVisible+vAnythingAllowed, viewFormat: vfFillWhite+vfFrameBlack+vfPen(1)+ vfLinesLtGray,

General Input View (clEditView)

4-5

CHAPTER

Working with View Classes

viewLineSpacing: 20, // methods and other view-specific slots viewSetupFormScript: func()... ...}

Text View (clParagraphView)


The clParagraphView class is used to display text or to accept text input. It includes these features:
n

Text recognition, correction, and editing, such as scrubbing, selection, copying to clipboard, pasting of text from clipboard, duplicating, and other gestures, as controlled by the setting of the viewFlags slot Automatic word-wrapping Clipping of text that wont t in the view. (An ellipsis is shown to indicate text beyond what is visible.) Use of different fonts (styles) within the same paragraph Tab-stop alignment of text. A tab is recognized only as the rst character in a line, if the line is started well to the right of the start of the preceding line. Other tabs must be entered from the on-screen keyboard or imported in data from outside sources. List format. The user can force text to stay on a new line by beginning the line with a dash or by making a narrow list of items. Automatic resizing to accommodate added text (when this view is enclosed in a clEditView). This feature is controlled by the vCalculateBounds flag in the viewFlags slot. Automatic addition of new words written near the view (when this view is enclosed in a clEditView). That is, words gravitate to become part of nearby paragraphs, unless they are written away from any other paragraph.

n n

n n

4-6

Text View (clParagraphView)

CHAPTER

Working with View Classes

These slots are of interest for a view of the clParagraphView class: viewBounds text viewFont Set to the size and location where you want the view to appear. A string that is the text currently contained in the view. Required, unless the styles slot is specied. The viewFont slot sets the font used to display text in the view. Note that if the view template itself does not contain this slot, it is inherited through proto inheritance only, not parent inheritance. See the section Specifying a Font beginning on page 4-11, for a detailed description of how to specify a font. If the text in the view has multiple fonts, then the styles slot is used to specify the font, instead of the viewFont slot. The default setting for the viewFont slot is simpleFont18. The default setting is vVisible. You will most likely want to set additional ags to control the recognition behavior of the view. Optional. The default setting is vfFillWhite+ vfFrameBlack+vfPen(1)+vfLinesGray. Optional. The default setting is vjLeftH+vjTopV+ vjParentLeftH+vjParentTopV+noLineLimits. Note that this view class does not support vertical justication of the view text. So any of these ags would be ignored: vjCenterV, vjBottomV, and vjFullV. Optional. An array of up to eight tab-stop positions, in pixels. For example: [10, 20, 30, 40]. These positions are relative to the left boundary of the view. Optional. An array of alternating run lengths and font information, if multiple font styles are used. The rst element is the run length (in characters) of the rst style run, and the second element is the font style of the rst run. The third element is the run length of the second style run, and so on. All of the run lengths must add up to the total text length. If the text is all in a single font, the font in the viewFont slot species the font style,

viewFlags

viewFormat viewJustify

tabs

styles

Text View (clParagraphView)

4-7

CHAPTER

Working with View Classes

and the styles slot is not needed. For information on how to specify a font in the styles array, see the section Specifying a Font beginning on page 4-11. See the code sample at the end of this section for an example. textFlags Optional. Can contain one or more of the following bit ags (which can be added together) to control special features: vNoSpaces Prevents spaces from being included in text written in the paragraph view. This is useful, for example, in numeric elds where you want the user to be able to enter a number without having spaces recognized between digits that may have been written spaced apart or added later. vWidthIsParentWidth Causes the right boundary of the view to extend to the right boundary of its parent view. (Only applies when the view is enclosed in a clEditView.) Note that once the user resizes the view, however, this feature is disabled for that view. The assumption is that if the user resized the view, he or she wants it to stay a particular size and not to change. noLineCompaction Prevents text written on a new line from being wrapped up to the previous line. That is, all text written on a new line stays on the new line. copyProtection Species restrictions on copying the view by dragging it into another view or by using the clipboard. This slot applies only to views of the class clParagraphView. If this slot is not present, there are no copy restrictions. In this slot you can specify one or more copy protection attributes, which are represented by constants dened as bit ags. The copy protection attributes are listed and described in Table 4-1. 4-8

Text View (clParagraphView)

CHAPTER

Working with View Classes

Table 4-1 Constant

CopyProtection constants Value Description

cpNoCopies cpReadOnlyCopies cpOriginalOnlyCopies

1 2 4

The view cannot be copied. The view can be copied, but the copy cannot be modied. The original view can be copied, but copies of it cannot be copied. When a copy is made, the copys copyProtection slot is changed to 1 (cpNoCopies) to prevent further copying. The view can be copied, but on one Newton device only. Copies cannot be exported to a different Newton device.

cpNewtonOnlyCopies

When used for input, a view of this class can appear simply as a blank area in which the user can write information, but usually it contains one or more horizontal dotted lines, like lined writing paper. This indicates to the user that the view accepts input. To create the lined paper effect, these slots must be set appropriately: viewFormat Must include one of the vfLines ags in the viewFormat slot. This turns on the line display and selects the line style. This sets the spacing between the lines, in pixels. viewLinePattern Optional. Sets a custom pattern that is used to draw the lines in the view. In the viewFormat slot editor in NTK, you must also set the Lines item to Custom to signal that you are using a custom pattern. (This sets the vfCustom<<vfLinesShift ag in the viewFormat slot.)

viewLineSpacing

Text View (clParagraphView)

4-9

CHAPTER

Working with View Classes

A pattern is simply an eight-byte binary data structure with the class 'pattern. You can use this NewtonScript trick to create binary pattern data structures on the y: myPattern := SetClass( Clone("\uAAAAAAAAAAAAAAAA"),'pattern); This code clones a string, which is already a binary object, and changes its class to 'pattern. The string is specied with hex character codes whose binary representation is used to create the pattern. Each two-digit hex code creates one byte of the pattern. For information about how to control recognition of characters, numbers, gestures, and so on, refer to the chapter Written Input and Recognition. Note that you don't need to create paragraph views yourself if you are accepting user input inside a clEditView. You simply provide a clEditView and when the user writes in it, the view automatically creates paragraph views to hold text. Here is an example of a template dening a view of the clParagraphView class: dateSample := {... viewClass: clParagraphView, viewBounds: {left:50, top:50, right:200, bottom:70}, viewFlags: vVisible+vReadOnly, viewFormat: vfFillWhite, viewJustify: oneLineOnly, text: "January 24, 1994", // 8 chars of one font, 3 chars of another, 5 chars // of another styles: [8, 18434, 3, 12290, 5, 1060865], ...}

4-10

Text View (clParagraphView)

CHAPTER

Working with View Classes

Specifying a Font
You specify a font by providing a font frame or a reference to a font frame. A font frame has this format: {family: familyName, face: faceNumber, size: pointSize} For familyName , you can specify a symbol corresponding to an available font. The symbols corresponding to the built-in fonts include: 'espy, 'geneva, and 'newYork. For faceNumber, you can specify the following values: 0 1 2 4 8 128 256 Normal font Bold font Italic font Underline font Outline font Superscript font Subscript font

For pointSize, specify an integer giving the point size. The system provides several constants which you can use to specify one of the built-in fonts. These constants are listed in Table 4-2. The fonts shown in the table can be specied by the constant (usable at compile time only), by their font frame, or by an integer value that packs all of the font information into an integer (sometimes this is what you see at run time if you examine a viewFont slot in the NTK Inspector). The integers in Table 4-2 are derived by packing font family, face, and size information into a single integer value. Recall that integers are 30 bits in length. The lower 10 bits are used to hold the font family, the middle 10 bits are used to hold the font size, and the upper 10 bits are used to hold the font face.

Text View (clParagraphView)

4-11

CHAPTER

Working with View Classes

Table 4-2

Built-in font constants Integer Value

Constant

Font Frame

ROM_fontsystem9 ROM_fontsystem9bold ROM_fontsystem9underline ROM_fontsystem10 ROM_fontsystem10bold ROM_fontsystem10underline ROM_fontsystem12 ROM_fontsystem12bold ROM_fontsystem12underline ROM_fontsystem14 ROM_fontsystem14bold ROM_fontsystem14underline ROM_fontsystem18 ROM_fontsystem18bold

{family:'espy, face:0, size:9} {family:'espy, face:1, size:9} {family:'espy, face:4, size:9} {family:'espy, face:0, size:10} {family:'espy, face:1, size:10} {family:'espy, face:4, size:10} {family:'espy, face:0, size:12} {family:'espy, face:1, size:12} {family:'espy, face:4, size:12} {family:'espy, face:0, size:14} {family:'espy, face:1, size:14} {family:'espy, face:4, size:14} {family:'espy, face:0, size:18} {family:'espy, face:1, size:18}

9216 1057792 4203520 10240 1058816 4204544 12288 1060864 4206592 14336 1062912 4208640 18432 1067008
continued

4-12

Text View (clParagraphView)

CHAPTER

Working with View Classes

Table 4-2

Built-in font constants (continued) Integer Value

Constant

Font Frame

ROM_fontsystem18underline simpleFont9 simpleFont10 simpleFont12 simpleFont18 fancyFont9 or userFont9 fancyFont10 or userFont10 fancyFont12 or userFont12 fancyFont18 or userFont18

{family:'espy, face:4, size:18} {family:'geneva, face:0, size:9} {family:'geneva, face:0, size:10} {family:'geneva, face:0, size:12} {family:'geneva, face:0, size:18} {family:'newYork, face:0, size:9} {family:'newYork, face:0, size:10} {family:'newYork, face:0, size:12} {family:'newYork, face:0, size:18}

4212736 9218 10242 12290 18434 9217 10241 12289 18433

These three parts added together specify a single font in one integer value. You can use the constants listed in Table 4-3 at compile time to specify all of the needed information. To use them, add one constant from each category together to yield a complete font specication. At run time, of course, youll need to use the integer values. For example, to specify a font that uses the Geneva face at 18 points in bold, use this code: tsSimple+tsSize(18)+tsBold This evaluates to the integer 1067010 (2+18432+1048576).

Text View (clParagraphView)

4-13

CHAPTER

Working with View Classes

Table 4-3 Constant Font Family

Font packing constants Value Description

(none dened) tsFancy tsSimple


Font Size

0 1 2

Identies the system font (Espy) Identies the New York font Identies the Geneva font

tsSize(pointSize)

pointSize << 10

Specify the point size of the font in pointSize

Font Face

tsPlain tsBold tsItalic tsUnderline tsOutline tsSuperScript tsSubScript

0 1048576 2097152 4194304 8388608 134217728 268435456

Normal font Bold font Italic font Underlined normal font Outline font Superscript font Subscript font

There may be additional fonts installed in the system, beyond those that are built in. The fonts that are currently installed in the system are available in the global variable fonts. The fonts variable contains a frame listing the installed fonts. In some situations, you may want to use whichever font the user has selected as their default font on the Styles palette. The users choice is available in the userFont slot of the userConfiguration global variable. You can reference it like this: userConfiguration.userFont

4-14

Text View (clParagraphView)

CHAPTER

Working with View Classes

Lightweight Text View


When you create a template using the clParagraphView class, and that template is instantiated into a view at run time, the system may create a specialized kind of paragraph view object, called a lightweight paragraph view. This kind of paragraph view is created automatically for you, instead of a standard paragraph view, if your template meets certain conditions. For example, it must be read-only, not include any tabs, and not include multiple font styles. The lightweight paragraph view has the primary advantage of occupying much less working memory than the standard paragraph view, since none of the editing code is needed. Here are the conditions that your clParagraphView template must meet in order for a lightweight paragraph view to be created from it:
n n

The viewFlags slot must contain the following ag: vReadOnly The viewFlags slot must NOT contain the following ags: vGesturesAllowed, vCalculateBounds The template must not contain the following other slots: tabs, styles

All paragraph views look the same after they are instantiated; that is, there is no way to tell whether a particular paragraph view is a standard or a lightweight view. Once a lightweight paragraph view has been instantiated, you cannot dynamically change the view ags to make it an editable view, or add multi-styled text by providing a styles slot, since this type of view object doesnt support these features. If you need this functionality for an existing lightweight paragraph view, youll have to copy the text out of it into an editable paragraph view.

Text View (clParagraphView)

4-15

CHAPTER

Working with View Classes

Shape View (clPolygonView)


The clPolygonView class is used to display graphic shapes (polygons) or ink, or to accept graphic or ink input. It includes these features:
n

Shape recognition and editing, such as stretching of shapes from their vertices, view resizing, scrubbing, selection, copying to clipboard, duplicating, and other gestures, as controlled by the setting of the viewFlags slot Snapping of new line endpoints to nearby vertices and midpoints of existing shapes Automatic resizing to accommodate enlarged shapes (when the view is enclosed in a clEditView). This feature is controlled by the vCalculateBounds flag in the viewFlags slot.

Views of the clPolygonView class are supported only as children of views of the clEditView class. In other words, you can put a clPolygonView only inside a clEditView. You don't need to create polygon views yourself if you are accepting user input inside a clEditView. You simply provide a clEditView and when the user draws in it, the view automatically creates polygon views to hold shapes. These slots are of interest for a view of the clPolygonView class: viewBounds points Set to the size and location where you want the view to appear. If the view contains a polygon shape, this slot contains a binary data structure of the type 'polygonShape, which holds the polygon data. See below for a detailed description of this binary data structure. If the view contains ink, this slot contains a binary data structure of the type 'ink, which holds the ink data.

ink

4-16

Shape View (clPolygonView)

CHAPTER

Working with View Classes

viewFlags

viewFormat

The default setting is vVisible. You will most likely want to set additional ags to control the recognition behavior of the view. Optional. The default setting is vfPen(2). The vfPen setting controls the thickness of polygon lines.

The points slot in a clPolygonView is a binary data structure with the class 'polygonShape. The binary data looks like this: shape This is a two-byte shape type identier that can have the following values:
Value Shape type

0 1 2 4 5 6 7 8 9 10 11 count points data

Circle Ellipse Tiny open curve (<15 pixels in diameter) Closed polygon Open polygon Closed curve Open curve Line Triangle Square Rectangle

This two-byte value is a count of the number of points following this value. A series of bytes representing the points that dene the polygon shape. Each point is represented by four bytes, where the rst two-byte value is the vertical point coordinate and the second two-byte value is the horizontal point coordinate of the point. Coordinates are relative to the upper left corner (0, 0) of the clPolygonView. So the first point in a square, for example, would have the coordinates (0, 0).

Shape View (clPolygonView)

4-17

CHAPTER

Working with View Classes

You can use the global functions PointsToArray and ArrayToPoints to translate points data between a polygon shape and a NewtonScript array. These functions are described following the example. Here is an example of a template dening a view of the clPolygonView class: aPolygon := {... viewClass: clPolygonView, viewBounds: {left:50, top:50, right:100, bottom:100}, viewFlags: vVisible+vCalculateBounds, viewFormat: vfPen(2), points: // binary object with the class 'polygonShape ...} The following two global functions allow you to convert the points data in a polygon shape between the binary data structure in the shape view and an array. PointsToArray PointsToArray(polygonShape) Returns an array of data extracted from a polygon shape binary object. polygonShape A binary object of the class 'polygonShape (from the points slot of a clPolygonView).

The rst element in the returned array is an integer identifying the shape type (see the description of clPolygonView above). The second element in the array is the number of points. Beginning with the third array element, the remainder of the array consists of coordinate pairs describing the points. The third element contains the X coordinate of the rst polygon point and the fourth element contains the Y coordinate, and so on. Coordinates are relative to the top left corner (0, 0) of the clPolygonView. Here is an example of an array returned from a rectangle shape: [11, 5, 0, 0, 0, 29, 40, 29, 40, 0, 0, 0]

4-18

Shape View (clPolygonView)

CHAPTER

Working with View Classes

The rst element, 11, describes the array as a rectangle; the second element, 5, indicates that there are ve points in the shape; and the remaining elements describe the ve points(0, 0), (0, 29), (29, 40), (40, 0), and (0, 0). ArrayToPoints ArrayToPoints(pointsArray) Converts an array of points to a binary object of the class 'polygonShape (as found in the points slot of a clPolygonView). The binary object is returned. pointsArray An array of points in the same format as returned by PointsToArray.

Picture View (clPictureView)


The clPictureView view class is used to display a picture. A picture can be a bitmap or picture object. These slots are of interest for a view of the clPictureView class: icon A bitmap or picture object to be displayed in the view. A bitmap is selected from a resource le by using the icon slot editor in NTK. A picture object is obtained from a resource le by using the GetResource or GetNamedResource compile-time functions in NTK. Set to the size and location where you want the view to appear. The default setting is vVisible. Optional. The default setting is nil. A binary object containing the bitmap data. It has the class 'bits. A bounds frame giving the dimensions of the bitmap ( {left:0, top:0, right:bitmapWidth, bottom:bitmapHeight}).

viewBounds viewFlags viewFormat

A bitmap object is a frame that has these slots: bits bounds

Picture View (clPictureView)

4-19

CHAPTER

Working with View Classes

mask

This slot is included only if a mask has been constructed or supplied. It contains a binary object representing the mask bitmap. It has the class 'mask.

A picture object is simply a binary object with the class 'picture. A Macintosh PICT resource can be imported into the Newton in two ways: as a bitmap or as a picture object. A Macintosh PICT resource is stored much more compactly on the Newton as a picture object; however it may be slower to draw than a bitmap. The same Macintosh PICT resource may occupy much more space when imported as a bitmap, but may draw signicantly faster. The method you should use depends on whether you want to optimize for space or speed. A Macintosh PICT resource is imported as a bitmap simply by using the slot editor for the icon slot (an editor of the Picture type). Alternatively, the resource can be imported as a picture object by using the GetResource or GetNamedResource compile-time functions from the NTK Project Data file. In this case, you must use an AfterScript to set the value of the icon slot to the picture object obtained by one of these resource functions.
Note

The constant clIconView can also be used to indicate a view of the clPictureView class. These two constants have identical values. u Here is an example of a template dening a view of the clPictureView class: aPicture := {... viewClass: clPictureView, viewBounds: {left:0, top:75, right:150, bottom:175}, viewFlags: vVisible+vClickable, icon: myPicture, ...}

4-20

Picture View (clPictureView)

CHAPTER

Working with View Classes

Keyboard View (clKeyboardView)


The clKeyboardView class is used to display keyboard-like arrays of buttons that can be pressed (tapped with the pen) to perform an action. Here is an example:

These slots are of interest for a view of the clKeyboardView class: Set to the size and location where you want the view to appear. keyDefinitions An array that denes the layout of the keys. For details, see the section Dening the Keys beginning on page 4-23. viewFlags The default setting is vVisible + vClickable. viewFormat Optional. The default setting is nil. keyArrayIndex Optional. Determines the array element to be used for a key legend or result, allowing dynamic indexing into an array for legends or results. See the section Dening the Keys beginning on page 4-23. keyHighlightKeys Optional. An array of keys that are to be highlighted on the displayed keyboard. (Specify an array of keyResult items; see the section KeyResult beginning on page 4-24.) keyResultsAreKeycodes Optional. If true, indicates that integers specied as results are to be interpreted as key codes, and the corresponding character is returned. If nil (the default), integers are not converted to characters. viewBounds

Keyboard View (clKeyboardView)

4-21

CHAPTER

Working with View Classes

keyReceiverView Optional. The view to which key commands (as a result of key presses) should be posted if no keyPressScript method exists. If the keyReceiverView slot is not found, the view identied by the symbol 'viewFrontKey is used. This symbol evaluates at run time to the current key receiver view. keySound Optional. A reference to a sound frame. The sound is played whenever a key is pressed. The default is no sound. keyPressScript Optional. This method is called whenever a key is pressed. The key result of the key pressed is passed as a parameter to this method. If this method is not supplied, the key result is converted (if possible) into a sequence of characters which are posted as key events to the key receiver view. An example of a view denition of the clKeyboardView class follows. The key constants in the row arrays are explained in the sections following the example. row0 := "1",1, "2",2, "3",3, row1 := "4",4, "5",5, "6",6, row2 := "7",7, "8",8, "9",9, [ keyVUnit, keyVUnit, keyHUnit+keyVUnit+keyFramed+2*keyInsetUnit+keyAutoHilite, keyHUnit+keyVUnit+keyFramed+2*keyInsetUnit+keyAutoHilite keyHUnit+keyVUnit+keyFramed+2*keyInsetUnit+keyAutoHilite ]; [ keyVUnit, keyVUnit, keyHUnit+keyVUnit+keyFramed+2*keyInsetUnit+keyAutoHilite, keyHUnit+keyVUnit+keyFramed+2*keyInsetUnit+keyAutoHilite, keyHUnit+keyVUnit+keyFramed+2*keyInsetUnit+keyAutoHilite ]; [ keyVUnit, keyVUnit, keyHUnit+keyVUnit+keyFramed+2*keyInsetUnit+keyAutoHilite, keyHUnit+keyVUnit+keyFramed+2*keyInsetUnit+keyAutoHilite, keyHUnit+keyVUnit+keyFramed+2*keyInsetUnit+keyAutoHilite ];

4-22

Keyboard View (clKeyboardView)

CHAPTER

Working with View Classes

row3 := [ keyVUnit, keyVUnit, "*",$*, keyHUnit+keyVUnit+keyFramed+2*keyInsetUnit+keyAutoHilite, "0",0, keyHUnit+keyVUnit+keyFramed+2*keyInsetUnit+keyAutoHilite, "#",$#, keyHUnit+keyVUnit+keyFramed+2*keyInsetUnit+keyAutoHilite ]; keypad := {... viewClass: clKeyboardView, viewBounds: {left:65, top:65, right:153, bottom:145}, viewFlags: vVisible+vClickable+vFloating, viewFormat: vfFrameBlack+vfFillWhite+vfPen(1), keyDefinitions: [ row0, row1, row2, row3 ], // defined above keyPressScript: func (key) begin Print("You pressed " & key); end, ...}

Dening the Keys


The keyDefinitions array determines the key layout of the keyboard. keyDefinitions is an array of arrays, one array for each row of the keyboard. Each one of the row arrays looks like this: row0 := [ rowHeight, rowMaxKeyHeight, key0Legend, key0result , key0Descriptor, key1Legend, key1result , key1Descriptor, key2Legend, key2result , key2Descriptor, ... ] The rst two elements describe the height that should be allotted for the row (rowHeight ) and the height of the tallest key in the row ( rowMaxKeyHeight), in key units (more about key units later). These two measurements are often the same, but they may differ.

Keyboard View (clKeyboardView)

4-23

CHAPTER

Working with View Classes

Next in the row array there are a series of three elements for each key in the row:
n n n

keyLegend keyResult keyDescriptor

These three elements are described in the following sections.

KeyLegend
The keyLegend species what appears on the keycap. It can be one of the following types of data:
n n n n n

nil, in which case the keyResult is used as the legend. A string, which is displayed centered in the keycap. A character constant, which is displayed centered in the keycap. A bitmap object. The bitmap is displayed centered in the keycap. An integer. The number is displayed centered in the keycap and is used directly as the result (unless the keyResultsAreKeycodes slot is set to true; see the following section, KeyResult). A method. The method is evaluated and its result is treated as if it had been specied as the legend. An array. An element of the array is selected and treated as one of the above data types. The index of the array element is determined by the value of the keyArrayIndex slot (which can be changed dynamically). Note that arrays of arrays are not allowed here, but an array can include any combination of other data types.

KeyResult
The keyResult is the value that is returned when the key is pressed. This value is passed as a parameter to the keyPressScript method. If this method doesn't exist, the result is converted (if possible) into a sequence of characters which are posted as key events to the key receiver view.

4-24

Keyboard View (clKeyboardView)

CHAPTER

Working with View Classes

The keyResult element can one of the following types of data:


n n

A string, character constant, or bitmap object, which is simply returned. An integer, which is returned. Alternately, if the keyResultsAreKeycodes slot is set to true, the integer is treated as a key code. In this case, the character corresponding to the specied key code is returned. See Figure 4-1 for the numeric key codes returned by each of the keys on a keyboard. A method. The method is evaluated and its result is treated as if it had been specied as the result. An array. An element of the array is selected and treated as one of the above data types. The index of the array element is determined by the value of the keyArrayIndex slot (which can be changed dynamically). Note that arrays of arrays are not allowed, but an array can include any combination of other data types.

KeyDescriptor
The keyDescriptor is 30-bit value that determines key size, framing, and other characteristics. The descriptor is specied by summing a combination of the following constants: keySpacer keyAutoHilite keyInsetUnit Nothing is drawn in this space, it is a spacer, not a key. Highlight this key when it is pressed. Inset this key's frame a certain number of pixels within its space. Multiply this constant by the number of pixels you want to inset, from 07 (for example, keyInsetUnit*3). Specify the thickness of the frame around the key. Multiply this constant by the number of pixels that you want to use for the frame thickness, from 0-3. Specify the roundedness of the frame corners. Multiply this constant by the number of pixels that you want to use for the corner radius, from 0-15, zero being square.
continued

keyFramed

keyRoundingUnit

Keyboard View (clKeyboardView)

4-25

CHAPTER

Working with View Classes

keyLeftOpen keyTopOpen keyRightOpen keyBottomOpen keyHUnit keyHHalf keyHQuarter keyHEighth keyVUnit keyVHalf keyVQuarter keyVEighth

No frame line is drawn along the left side of this key. No frame line is drawn along the top side of this key. No frame line is drawn along the right side of this key. No frame line is drawn along the bottom side of this key. A combination of these four constants species the horizontal dimension of the key in units. For details, see the next section. A combination of these four constants species the vertical dimension of the key in units. For details, see the next section.

Specifying Key Dimensions


The width and height of keys are specied in units, not pixels. A key unit is not a xed size, but is used to specify the size of a key relative to other keys. The width of a unit depends on the total width of all keys in the view and on the width of the view itself. Key widths and heights can be specied in whole units, half units, quarter units, and eighth units. When it is displayed, the whole keyboard is scaled to t entirely within whatever size view bounds you specify for it. To t the whole keyboard within the width of a view, the total unit widths are summed for each row, and the scaling is determined based on the widest row. This row is scaled to t within the view width, giving an equal pixel width to each whole key unit. A similar process is used to scale keys vertically to t within the height of a view.

4-26

Keyboard View (clKeyboardView)

CHAPTER

Working with View Classes

Figure 4-1

Keyboard key codes

Keyboard View (clKeyboardView)

4-27

CHAPTER

Working with View Classes

Fractional key units (half, quarter, eighth), when scaled, must be rounded to an integer number of pixels, and thus may not be exactly the indicated fraction of a whole key unit. For example, if the keys are scaled to t in the view bounds, a whole key unit ends up to be 13 pixels wide, and a key was specied to have a width of one and three eighth units (keyHUnit + keyHEighth*3), then its width would be rounded to 13 + 5, or 18 pixels, which is not exactly 1-3/8*13. Key dimensions are specied by summing a combination of horizontal and vertical key unit constants within the keyDescriptor. For example, to specify a key that is 2-3/4 units wide by 1-1/2 units high, specify these constants for keyDescriptor: keyHUnit*2 + keyHQuarter*3 + keyVUnit + keyVHalf

Analog Gauge View (clGaugeView)


The clGaugeView view class is used to display objects that look like analog bar gauges. Gauges are useful for graphically displaying information, such as the amount of battery power remaining in the system. They can also be used as interactive controls. For interactive gauges, the end of the gauge indicator bar contains a small diamond-shaped active area called the knob. The user can click on the knob and drag the indicator bar to a new position. Here is an example of a typical gauge view:

Knob

4-28

Analog Gauge View (clGaugeView)

CHAPTER

Working with View Classes

These slots are of interest for a view of the clGaugeView class: Set to the size and location where you want the view to appear. viewValue Set this slot to give the gauge an initial value, if you know it ahead of time. If you need to calculate the initial value at run time, set this slot within the viewSetupFormScript. This value must be an integer between minValue and maxValue, inclusive. During execution, the viewValue slot stores the current gauge setting by interpolating between minValue and maxValue. viewFlags The default setting is vVisible + vClickable. To make a gauge that is read-only, set the vReadOnly ag (and not vClickable). For read-only gauges, the diamond-shaped knob is not drawn on the gauge. viewFormat Optional. The default setting is nil. minValue Optional. This species the minimum gauge value; the number set as the viewValue when the gauge reads fully to the left side. The default is zero, which you can change if you wish. maxValue Optional. This species the maximum gauge value; the number set as the viewValue when the gauge reads fully to the right side. The default is 100, which you can change if you wish. gaugeDrawLimits Optional. The default is true, which displays the gray background. If you set this slot to nil, the gray background is not displayed. viewChangedScript Optional. This method is called whenever the value of the gauge view changes. If you check the value of the viewValue slot in this method, you can dynamically track the changes the user is making to the gauge indicator. This method is called repeatedly as the gauge viewBounds

Analog Gauge View (clGaugeView)

4-29

CHAPTER

Working with View Classes

knob is dragged. As usual, this method is passed two parameters: the name of the slot that changed and the name of the view. The return value of this method is ignored. viewFinalChangeScript Optional. This method is called once each time the gauge is moved, after the pen is lifted from the knob. This method is passed two parameters: rst, the initial viewValue of the gauge before it was changed; and second, the nal viewValue of the gauge after it was changed. If the gauge was moved but reset to its original value before the pen was lifted, this method is not called. The return value of this method is ignored. Here is an example of a view denition of the clGaugeView class: soundGauge := {... viewClass: clGaugeView, viewBounds: {left:80, top:20, right:180, bottom:28}, viewFlags: vVisible+vClickable, gaugeDrawLimits: true, minValue: 0, maxValue: 11 viewSetupFormScript: func() self.viewvalue := userConfiguration.soundVolume, viewChangedScript: func(slot, context) begin userConfiguration.soundVolume := viewValue; :SysBeep(); //play it so they can hear new level end, ...}

4-30

Analog Gauge View (clGaugeView)

CHAPTER

Working with View Classes

Monthly Calendar View (clMonthView)


The clMonthView view class is used to display a monthly calendar. Here is an example:

Selected day

Current day

Selected days are highlighted with an inverted rounded rectangle. The current day is shown in bold, if it appears in the month that is displayed. These slots are of interest for a view of the clMonthView class: viewBounds selectedDates Set to the size and location where you want the view to appear. Required. Initially, this slot must be set to an array containing a single element which is a time value. (For example, you can use the Time function to return the current time). The month displayed is the month in which this time value occurs. If the user makes a selection of days in the month, this slot holds an array of time values, one for each of the days selected. All time values are represented as the number of minutes passed since midnight, January 1, 1904. A read-only slot that holds an integer that is the year of the month shown. A read-only slot that holds an integer that is the number of the month shown (January=1, . . . , December=12). The default setting is vVisible+vClickable. Optional. The default setting is nil.

year month viewFlags viewFormat

Monthly Calendar View (clMonthView)

4-31

CHAPTER

Working with View Classes

Optional. The font used for the day numbers. The current day's date is shown in bold. The default font is ROM_fontSystem9. labelFont Optional. The font used to label the days above the dates. If you omit this slot or set it to nil, the day labels are not shown. The default font from NTK is ROM_fontSystem9Bold. noSelection Optional. You should set this slot to true if you do not want the initial date highlighted (selected) when the month view is rst displayed. The default is nil. singleDay Optional. You should set this slot to true to force single-day selection only (in which the user cannot select multiple days). The default is nil, meaning that multiple day selection is allowed. monthChangedScript Optional. This method is called when the date selection is changed in a clMonthView. The new selected dates are stored in an array in the selectedDates slot. viewSetupFormScript This method is set by default in NTK to the following line of code: self.selectedDates := [Time()]. This code causes the view to display the current month when it is opened. datesFont Typically, the selectedDates slot resides in the parent view of the month view and is found through inheritance when the month view is instantiated. This allows the parent and its other child views to have access to the date selection from the month view. Here is an example of a view denition of the clMonthView class: theMonth := {... viewclass: clMonthView, viewBounds: {left: 58, top: 82, right: 186, bottom: 178}, viewflags: vVisible+vClickable, labelFont: ROM_fontSystem9Bold,

4-32

Monthly Calendar View (clMonthView)

CHAPTER

Working with View Classes

dateFont: ROM_fontSystem9, selectedDates: nil, viewSetupFormScript: func() begin self.selectedDates := [Time()]; end, ...}

Scaled View (clRemoteView)


The clRemoteView view class is used to display a scaled image of another view. This can be used to show a page preview of a full-page view in a smaller window, for example. The view that you want to display inside of the remote view should be specied as the single child of the remote view. This child is always hidden, and is just used internally by the remote view to construct the scaled image. These slots are of interest for a view of the clRemoteView class: stepChildren Specify a single child view in this array. This child view will be scaled to t inside the clRemoteView. Typically, you set this slot at run time in the viewSetupFormScript method. Set to the size and location where you want the view to appear. The default setting is nil. Optional. The default setting is nil.

viewBounds viewFlags viewFormat

Here is an example of a view denition of the clRemoteView class: myRemoteView := {... viewclass: clRemoteView, viewBounds: {left: 75, top: 203, right: 178, bottom: 322},

Scaled View (clRemoteView)

4-33

CHAPTER

Working with View Classes

viewFlags: vVisible+vReadOnly, viewFormat: nil, viewSetupFormScript: func() begin // aView is the view to be scaled self.stepchildren := [aView]; end, ...};

Outline View (clOutline)


The clOutline view class is used to display an expandable text outline. Here is an example:

The clOutline view class includes these features:


n

Multi-level outline (up to 15 levels), with each outline level indented from the previous one. Headings that can be expanded (those that contain subheadings) are shown in bold automatically. The user can expand a heading to show its subheadings by tapping on the heading. Another tap on the heading collapses it, hiding its subheadings. The user can expand only one main heading at a time. If the user taps on a different heading, any other expanded heading is automatically collapsed, and the new heading is expanded.

4-34

Outline View (clOutline)

CHAPTER

Working with View Classes

These slots are of interest for a view of the clOutline class: Set to the size and location where you want the view to appear. browsers An array containing one frame item, List, which is itself an array of the items to be shown in the outline. Each outline item is a frame containing these slots: level The outline level of this item. 1 species a top-level heading, 2 species a second-level heading, and so on. This slot can be omitted for top-level items; it defaults to level 1. You can use up to 15 levels. name A string that is the text to be shown in the outline. Tabs are not allowed in the text. viewFont Specify the font to be used for the text in the outline. Its best not to specify a bold font since bold is added automatically for headings that have subheadings. If you specify bold, all the text will then be bold. The default font is ROM_fontSystem10. outlineClickScript Optional. This method is called whenever the user taps an item in the outline. It is passed two parameters: the rst is the index of the outline item in the List array (inside the browsers slot); the second parameter is not used. This function must return true. viewFlags The default setting is vVisible+vClickable+ vReadOnly. viewFormat Optional. The default setting is nil. clickSound Optional. Specify a sound frame. This sound is played when the user taps any item in the outline. viewBounds

Outline View (clOutline)

4-35

CHAPTER

Working with View Classes

Note

A view of the clOutline class can display a maximum of nine topics (at all levels) at one time, though you can have any number of headings and up to 15 levels in the outline. Practically, this means you cant have more than nine headings at the same level under the same heading, or at the top level. u Here is an example of a view denition of the clOutline class: myOutline := {... viewclass: clOutline, viewFlags: vVisible+vClickable+vReadOnly, viewBounds: {left: 25, top: 56, right: 220, bottom: 232}, viewFont: ROM_fontsystem12, clickSound: ROM_flip, browsers: [{list: [ {level:1, name:"My First Heading"}, {level:2, name:"First level 2 head"}, {level:2, name:"Another level 2 head"}, {level:3, name:"Wowa third level!"}, {level:1, name:"Second main heading"}, {level:2, name:"Section 2 subhead 1"}, {level:2, name:"Section 2 subhead1"}, {level:1, name:"Third main heading"}, {level:2, name:"Last subhead"}, ] }], outlineClickScript: func(index, dummy) begin Print("You picked browser item " & index); true; end, ...};

4-36

Outline View (clOutline)

CHAPTER

Working with View Classes

Summary of View Classes


This section contains an alphabetical list of all the view classes described in this chapter. clEditView clGaugeView clKeyboardView clMonthView clOutline clParagraphView clPictureView clPolygonView clRemoteView clView

Summary of View Classes

4-37

CHAPTER

Handling System Messages

As your application executes, it receives messages from the system which you can choose to handle by providing methods that are named after the messages. These system messages give you a chance to perform your own processing as particular events are occurring. For example, the view system performs default initialization operations when a view is instantiated. It also sends your view a viewSetupFormScript message. If you provide a method to handle this message, you can perform your own initialization operations in the method. However, handling system messages in your application is optional. The system usually performs its own actions to handle each of the events for which it sends your view messages. Your system message handling methods do not override these system actions. You cannot change, delete, or substitute for the default system event-handling actions. Your system message handling methods augment the system actions. For example, when the view system receives a Show command for a view, it displays the view. It also sends the view the viewShowScript message. If you have provided a viewShowScript method, you can perform any special processing that you need to do when the view is displayed.

5-1

CHAPTER

Handling System Messages

The system sends messages to your application at specic times during its handling of an event. Some messages are sent before the system does anything to respond to the event, and some are sent after the system has already performed its actions. The timing is explained in each of the message descriptions in this chapter. The system messages described in this chapter are grouped into the following sections:
n n n n n

Initialization and termination messages Drawing-related messages Scrolling and overview messages Input-related messages Other messages

Initialization and Termination Messages


When a view is instantiated, messages are sent to the view in a particular order. By providing methods to handle these messages, you can perform run-time initialization operations for the view. To help you understand the state of the view when each of these methods is executed, here is the sequence of execution during view instantiation: 1. The viewClass slot of the view template is read, a new view object is created, and its _parent slot is set, but no other slots are read yet from the template. 2. The viewSetupFormScript message is sent to the view. 3. The following view slots are read: viewFlags, viewFormat, viewBounds, and declareSelf. 4. The viewSetupChildrenScript message is sent to the view. 5. The viewChildren and stepChildren slots are read and the child views are instantiated using this same process. As part of the process, the following messages are sent to each child view, in this order: viewSetupFormScript, viewSetupChildrenScript,

5-2

Initialization and Termination Messages

CHAPTER

Handling System Messages

viewSetupDoneScript. If a child view has children, its children are instantiated after the viewSetupChildrenScript message is sent to it, and so on, until all children in the hierarchy are instantiated. 6. The viewJustify slot is read and the viewBounds are adjusted accordingly. 7. The viewSetupDoneScript message is sent to the view. 8. The view is displayed if its vVisible viewFlags bit is set. 9. The viewShowScript message is sent to the view and then the viewDrawScript message is sent to the view. (Note that the viewShowScript message is not sent to any child views, however.) 10. Each of the child views is drawn, in hierarchical order, and the viewDrawScript message is sent to each of these views, immediately after it is drawn. For additional information about view instantiation, see the section View Instantiation beginning on page 2-41. When a view is closed, the following steps occur: 1. If the view is closing because it was directly sent the Close or Toggle message, the system sends it the viewHideScript message. (If the view is closing because it is a child of a view being close directly, then the viewHideScript message is not sent to it.) 2. The graphical representation of the view is removed from the screen. 3. The view is sent the viewQuitScript message. The view itself may or may not be marked for garbage collection, depending on whether or not it was declared. For more information, see the section Closing a View beginning on page 2-45. These system messages mentioned here are described in this section: viewSetupFormScript, viewSetupChildrenScript, viewSetupDoneScript, and viewQuitScript. These additional messages mentioned here are described in the section Drawing-Related Messages: viewShowScript, viewDrawScript, and viewHideScript.

Initialization and Termination Messages

5-3

CHAPTER

Handling System Messages

viewSetupFormScript
During view creation, this message is sent before any slots in the view template are read. In this method, you can do any special initialization that your view needs, including setting the value of any slots other than the viewClass slot. For example, you can dynamically change the viewBounds slot, the viewFlags slot, the viewFont slot, and so on. Note that you cannot do any operations involving child views of your view since they haven't yet been instantiated at this point. (However, you can manipulate the stepChildren array at this point.) This message is also sent during execution of the system view method SyncView, before it begins its operations. This message is also sent during execution of the global function SetValue (it calls SyncView internally), if you set the value of one of these slots: viewBounds, viewFormat, viewJustify, or viewFont. Here is an example of using this method: viewSetupFormScript: func() begin self.viewBounds := SetBounds(0, 15, 200, 180); end
Note

The system searches for this method only in the current view and its protos. The parent chain is not searched for the method. u

viewSetupChildrenScript
This message is sent after a view is created but before its children are instantiated. In this method, you can do any special initialization that you need to do before the child views are instantiated. For example, you might want to dynamically set up the stepChildren array, which controls what child views are to be created.

5-4

Initialization and Termination Messages

CHAPTER

Handling System Messages

This message is also sent during execution of the following system view methods before the child views are redrawn: SyncChildren, RedoChildren, and SyncScroll (only if you pass a soup cursor for the rst parameter in SyncScroll). Here is an example of using this method: viewSetupChildrenScript: func() begin self.stepChildren := [pg4, pg5]; // child templates end
Note

The system searches for this method only in the current view and its protos. The parent chain is not searched for the method. u

viewSetupDoneScript
This message is sent after all of the child views of the view are instantiated, just before the view is displayed. Here is an example of using this method: viewSetupDoneScript: func() begin self:SetPopup(); end
Note

The system searches for this method only in the current view and its protos. The parent chain is not searched for the method. u

Initialization and Termination Messages

5-5

CHAPTER

Handling System Messages

viewQuitScript
This message is sent just before the view is closed. It gives you a chance to do any processing or clean-up that you need to just before the view is closed. Note that an undeclared view is destroyed when it is closed. A declared view still exists, if the view in which it is declared is still open. When a view is closing, this message is sent to the topmost view that is closing as well as to all of the children of that view, since they too are closing with it. When the topmost view receives this message, its child views still exist. However, this message propagates down to child views of this topmost view, and the order in which the child views receive the message and are closed is undened. The key point to remember is that for these child views, you cannot count on their children still existing when they receive this message. So a view shouldnt do any processing involving data in child views unless it is the topmost view receiving the viewQuitScript message. Here is an example of using this method: viewQuitScript: func() begin RemoveSlot(GetGlobals().routing, appSymbol); RemoveSlot(GetRoot(), 'businessFormat); RemoveSlot(GetRoot(), 'myAuxFormat); end
Note

The system searches for this method only in the current view and its protos. The parent chain is not searched for the method. u

5-6

Initialization and Termination Messages

CHAPTER

Handling System Messages

Drawing-Related Messages
The system messages described in this section concern drawing and other events that affect the visible representation of the view.

viewShowScript
This message is sent when the view is instructed to show itself. This can occur as a result of the Show, Open, or Toggle messages. When showing a view, the view system rst shows the view and then sends this message to allow you to perform any additional operations. Here is an example of using this method: viewShowScript: func() begin // idle method will close view after 5 seconds :SetupIdle(5000); end

viewHideScript
This message is sent when the view is instructed to hide itself. This can occur as a result of the Hide, Close, or Toggle view methods. When hiding a view, the view system rst sends this message, then hides the view and all of its child views. However, this message is not sent to any of the child views. This message is not always sent when a view is closed. Do not use this method to do clean-up when a view is closinguse the viewQuitScript method instead. The viewQuitScript message is sent immediately after the viewHideScript message when a view is being closed.

Drawing-Related Messages

5-7

CHAPTER

Handling System Messages

Here is an example of using this method: viewHideScript: func() begin // open anotherView when this one is hidden anotherView:Open(); end

viewDrawScript
This message is sent when the view is drawn. First the view system draws the view, then this message is sent, then the view frame and view highlight (if any) are drawn.This message is sent before any child views are drawn. If you wish to augment the drawing done by the view system or to perform other operations whenever the view is drawn, do it in this method. If you want to draw in a view other than when the viewDrawScript message is sent, use the DoDrawing view method, documented in the chapter Drawing. Here is an example of using this method: viewSetupFormScript: func() // set up line objects and save them in the lines slot begin local box; box := self:LocalBox(); self.lines[0]:= MakeLine(0, 0, box.right, box.bottom); self.lines[1]:= MakeLine(0, box.bottom, box.right, 0); end viewDrawScript: func() // draw an X in the view begin :DrawShape(self.lines, nil); end

5-8

Drawing-Related Messages

CHAPTER

Handling System Messages

Note

The system searches for this method only in the current view and its protos. The parent chain is not searched for the method. u

viewHiliteScript
This message is sent just before the system is about to highlight or unhighlight the view. This method is passed one parameter: a Boolean value that is true if the view is to be highlighted or nil if the view is to be unhighlighted. If this method returns true, it is assumed that you have handled the highlighting or unhighlighting operation, and the system wont do it. If this method returns nil, the system performs the operation. Note that you dont have use the DoDrawing method to do drawing in your viewHiliteScript method. Here is an example of using this method: viewHiliteScript: func(on) begin local box; box := self:LocalBox(); r := MakeRoundRect(box.left+3, 0, box.right-3, box.bottom, 4); :DrawShape(r, {transferMode: modeXor, fillPattern: vfBlack}); true; end
Note

The system searches for this method only in the current view and its protos. The parent chain is not searched for the method. u

Drawing-Related Messages

5-9

CHAPTER

Handling System Messages

Scrolling and Overview Messages


The system messages described in this section concern scrolling and overview events.

viewScrollDownScript
This message is sent when the view system receives a scrollDown event, which occurs when the user taps the downward-pointing scroll arrow. There is no default view-system operation that occurs as a result of this event only this message is sent. Note that scrolling down means that visually the items on the screen move upward, showing you new items that were previously hidden below the bottom of the view. Only a view with the vApplication ag set in its viewFlags slot can receive this message. Here is an example of using this method: viewScrollDownScript: func() begin if index < length(notes)-1 then begin roll:SyncScroll(notes, index, 1); index := index + 1; end end

// 1 = down

viewScrollUpScript
This message is sent when the view system receives a scrollUp event, which occurs when the user taps the upward-pointing scroll arrow. There is no default view-system operation that occurs as a result of this eventonly this

5-10

Scrolling and Overview Messages

CHAPTER

Handling System Messages

message is sent. Note that scrolling up means that visually the items on the screen move downward, showing you new items that were previously hidden above the top of the view. Only a view with the vApplication ag set in its viewFlags slot can receive this message. Here is an example of using this method: viewScrollUpScript: func() begin if index > 0 then begin roll:SyncScroll(notes, index, -1); index := index - 1; end end

// -1 = up

viewOverviewScript
This message is sent when the view system receives an Overview event, which occurs when the user taps the overview dot between the scroll arrows. There is no default view-system operation that occurs as a result of this eventonly this message is sent. Usually the overview button is used to toggle between two views of the data in an application: a close-up (normal) view, and an overview view. Only a view with the vApplication ag set in its viewFlags slot can receive this message. Here is an example of using this method: viewOverviewScript: func() begin if (cardPrefs.mode = modeCloseUp) then cardPrefs.mode := modeOverview

Scrolling and Overview Messages

5-11

CHAPTER

Handling System Messages

else cardPrefs.mode := modeCloseUp; closeUp:Toggle(); overView:Toggle(); status:RedoChildren(); end

Input-Related Messages
The system messages described in this section concern written input by the user. Any view can accept pen input, as long as at least the vClickable ag is set in its viewFlags slot; of course, other recognition ags must be set in order to accept input beyond just a tap. System messages are sent to a view to signal the following kinds of pen input: taps, strokes, gestures, and words. All pen input is rst signaled by the viewClickScript message. This message indicates that the pen was placed down inside the view. If this message is not handled by the view, and additional recognition ags are sent, other messages may be sent to the view, depending on what was written. These other messages include viewStrokeScript, viewGestureScript, and viewWordScript (in that order if all are sent). Each of the input-related messages has at least one parametera stroke unit. The stroke unit contains information about the pen input. There is no way to look at the stroke unit directly, but you can pass it to other system-supplied functions to get information from it such as the beginning and ending points of the stroke, an array of stroke points, the stroke bounds, and so on. Functions which operate on stroke units are described in the chapter Written Input and Recognition.

5-12

Input-Related Messages

CHAPTER

Handling System Messages

viewClickScript
This message is sent when the user places the pen down on the screen inside the view (assuming the view has the vClickable ag set). This message is sent before the view system does any processing of the pen input. This method is passed one parameter: a stroke unit object. This object contains information describing the interaction of the pen with the display. If the viewClickScript method returns true, the pen interaction is considered done, and the system performs no further processing of the pen input, and no other stroke-related messages are sent to the view (such as viewStrokeScript, viewGestureScript, and so on). If the viewClickScript method returns nil, the system continues to process the pen input. The message is passed up the parent view chain, until it is handled by a viewClickScript method, or ignored. If the viewClickScript message is not handled and there are other recognition ags set, then additional system messages may be sent to the view. For example, if the vStrokesAllowed ag is set, then the viewStrokeScript message may be sent; this may be followed by the viewGestureScript message, if the vGesturesAllowed ag is set; and this may be followed by the viewWordScript message, if word recognition is enabled. You can determine the coordinates of the pen-down location using the function GetPoint, and you can control the display of electronic ink using the functions InkOff and InkOn. That is, if you want to prevent the display of electronic ink in the view, you must call InkOff from within the viewClickScript method. Alternatively, you can call the view methods TrackHilite or TrackButton; both of these methods call InkOff internally. The StrokeDone function will tell you if the user has nished making the stroke. The Drag method will automatically track the pen on the screen and drag the view to where the pen is lifted.

Input-Related Messages

5-13

CHAPTER

Handling System Messages

Here is an example of using this method: viewClickScript: func(unit) begin :Drag(unit, nil); // drag the view when its tapped end

viewStrokeScript
This message is sent when the pen is rst lifted after being placed down within the view (assuming the view has the vStrokesAllowed ag set). You can do whatever processing you want as a result of this event. The view system does no default processing as a result of this event. This method is passed one parameter: a stroke unit object. This object contains the stroke and other information describing the interaction of the pen with the display. If the viewStrokeScript method returns true, the pen interaction is considered done, and the system performs no further processing of the pen input, and no other stroke-related messages are sent to the view (such as viewGestureScript, viewWordScript, and so on). If the viewStrokeScript method returns nil, the system continues to process the pen input. The message is passed up the parent view chain, until it is handled by a viewStrokeScript method, or discarded. If the stroke is not handled and there are other recognition ags set, then additional system messages may be sent to the view. For example, if the vGesturesAllowed ag is set, then the viewGestureScript message may be sent, and this may be followed by the viewWordScript message, if word recognition is enabled. The system regards multiple pen-down/pen-up events that are close in time as a single stroke (for writing letters and words). The viewStrokeScript message is sent to the view only the rst time the pen is lifted during a stroke. If the pen is lifted more than once during a single stroke, only one viewStrokeScript message is sent for that stroke.

5-14

Input-Related Messages

CHAPTER

Handling System Messages

Note that this message will be preceded by a call to viewClickScript, if the view has that method. You can determine the coordinates of the stroke using the function GetPoint, and you can control the display of electronic ink using the functions InkOff and InkOn. The StrokeDone function will tell you if the user has nished making the stroke (only the rst stroke if the pen interaction actually consists of several strokes close together in time). See the chapter Written Input and Recognition for details on these functions. Here is an example of using this method: viewStrokeScript: func(unit) begin local bounds, points; bounds := StrokeBounds(unit); print("Bounds of stroke are "); print(bounds); points := GetPointsArray(unit); print("Points are "); print(points); true; end

viewGestureScript
This message is sent when the user writes a recognizable gesture inside the view (assuming the view has the vGesturesAllowed ag set). Two parameters are passed to this method: rst, the stroke unit object, and second, an integer code that identies the gesture that was recognized. The following gestures are supported:
Gesture Constant Integer Value

tap double tap scrub

aeClick aeDoubleTap aeScrub

49 50 13
continued

Input-Related Messages

5-15

CHAPTER

Handling System Messages

Gesture

Constant

Integer Value

highlight caret horizontal line (makes a new page in the notepad)

aeHilite aeCaret aeLine

47 15 16

This message is sent after the view system recognizes the gesture, and only if the gesture is one not normally handled by the view. For example, views of the clParagraphView class handle all gestures except a tap, so for this kind of view, the viewGestureScript message will not usually be sent (except for a tap). (However, if you set the vReadOnly ag in the viewFlags slot, the viewGestureScript message will be sent for all gestures except highlight.)
Note

You can work around the limitation that this message is sometimes not sent. For example, you may want a view to receive this message no matter what kind of view it is, or what kinds of input it handles. You can do this by creating a child view of the clView class that is transparent and the same size as the input view you are working with. If you set the appropriate input ags for the clView, it will receive the input-related messages rst. For any particular message, the clView can take some action and return true to prevent the message from being passed to the parent, or it can return nil to pass the message on to the parent. u If the viewGestureScript method returns true, the pen interaction is considered done, and the system performs no further processing of the pen input, and no other stroke-related messages are sent to the view (for example, viewWordScript). If the viewGestureScript method returns nil, the system continues to process the pen input. The message is passed up the parent view chain, until it is handled by a viewGestureScript method, or discarded. If the

5-16

Input-Related Messages

CHAPTER

Handling System Messages

tap is not handled and there are word recognition ags set, then the viewWordScript message may be sent to the view. Note that this message will be preceded by a call to viewClickScript, if the view has that method. It may or may not also be preceded by a call to viewStrokeScript, if the view has that method. Here is an example of using this method: viewGestureScript: func(unit, gestureKind) begin if gestureKind = aeLine then // If it was a line begin // Make a new data item in our app end; end

viewWordScript
This message is sent when a word is recognized and passed to the view (assuming the view has some kind of word recognition ag set). This method is passed one parameter: a stroke unit object. This object contains the stroke and other information describing the interaction of the pen with the display. You can get the word that was recognized by calling the function GetWordArray. The first string returned in the word array is the one with the highest recognition probability . The viewWordScript message is sent after the system recognizes the word, and only if the view is not one that normally supports word recognition. For example, views of the clParagraphView and clEditView class support word recognition, so will not normally receive this message. (However, if you set the vReadOnly ag for these views, the viewWordScript message will be sent.)

Input-Related Messages

5-17

CHAPTER

Handling System Messages

Note

You can work around the limitation that this message is sometimes not sent. For example, you may want a view to receive this message no matter what kind of view it is, or what kinds of input it handles. You can do this by creating a child view of the clView class that is transparent and the same size as the input view you are working with. If you set the appropriate input ags for the clView, it will receive the input-related messages rst. For any particular message, the clView can take some action and return true to prevent the message from being passed to the parent, or it can return nil to pass the message on to the parent. u If the viewWordScript method returns true, the event is considered handled. If the viewWordScript method returns nil, the message is passed up the parent view chain, until it is handled by a viewWordScript method, or discarded. Here is an example of using this method: viewWordScript: func(unit) begin local matchedWords, recognizedWord; matchedWords := GetWordArray(unit); recognizedWord := matchedWords[0]; print("The recognized word was " & recognizedWord); true; end
Note

The system searches for this method only in the current view and its protos. The parent chain is not searched for the method. u

5-18

Input-Related Messages

CHAPTER

Handling System Messages

Other Messages
This section describes additional system messages, in alphabetical order.

powerOffScript
When the system is going into sleep mode, this message is sent twice to those views (or any frames) that have registered themselves as power-off handlers. System sleep could happen as a result of a user action like toggling the power switch, or it could happen automatically as a result of system inactivity. To register a view or other frame as a power-off handler, call the global function AddPowerOffHandler(self). You might want to do this in the viewSetupFormScript method of a view. To unregister the view or frame, call RemovePowerOffHandler(self). You might want to do this in the viewQuitScript method of a view. The powerOffScript method is passed one parameter: a symbol. The rst time this message is sent, the symbol 'oktopoweroff is sent as the parameter. If it is safe to power off, the method should return true. If it is not safe to power off, the method should return nil and the power-off sequence will be canceled. After all power-off handlers in the system have been notied, and assuming they all return true, the powerOffScript message is sent a second time, this time with the 'poweroff symbol as the parameter. This signals that system sleep is imminent. The powerOffScript method should complete any operations that need to be done prior to system sleep.

Other Messages

5-19

CHAPTER

Handling System Messages

Here is an example of using this method: powerOffScript: func(what) begin if what = 'okToPowerOff then true else if what = 'poweroff then base:Close(); else nil; end

printNextPageScript
This message is sent to a format during a routing operation. For more details, see the chapter Routing. After the system router nishes routingthat is, printing, faxing, or mailing a page of information, it sends this message so that your application can prepare the next page of data to be routed. This method must return true if there is more data to route, or nil otherwise. This method should also prepare the next page of data to be routed, if there is more data. Here is an example of using this method: printNextPageScript: func() begin :RedoChildren(); (index < length(fields.body)); end

5-20

Other Messages

CHAPTER

Handling System Messages

soupChanged
This message is sent when a different application (or the system) has changed a soup that you use or own, provided that you have registered your soup in the system global soupNotify. For more information, see the section Globals beginning on page 8-20. This method is passed one parameter: a string that is the name of the soup that changed. This message is sent for any of the following reasons:
n n n n n

a card containing your soup is inserted items in your soup are moved (between the internal store and a card) items are moved into your soup your soup is restored from a backup a soup item is changed or deleted

Here is an example of using this method: SoupChanged: func(soupName) begin if Visible(self) then mainDisplay:RedoChildren(); end

viewAddChildScript
This message is sent when a child is about to be added to a view of the clEditView class. This method is passed one parameter: the child template. This method gives you a chance to create and add the child view, or to do some other processing before the view is created and added automatically. If this method returns true, it is assumed that you have added the child view entry to your view's stepChildren array and that you have created the child view. If this method returns nil, these things are done for you. (Note that you can use the AddStepView function to perform these operations yourself.)

Other Messages

5-21

CHAPTER

Handling System Messages

In any case, a view must be instantiated from the template passed to this methodeither by you or by the system. If you return true, and fail to instantiate the view, the system will display an error alert, because it expects the view to exist. Here is an example of using this method: viewAddChildScript: func(newOne) begin AddToDefaultStore(mySoup, newOne); AddUndoAction(KillAddition, [newOne]); AddStepView(myView, newOne); end
Note

The system searches for this method only in the current view and its protos. The parent chain is not searched for the method. u

viewChangedScript
This message is sent when the value of a slot in the view is changed as a result of the SetValue function, or as a result of other view operations such as changing the bounds, changing the contents or the text style, and so on. This method is passed two parameters: rst, a symbol that is the name of the slot whose value changed; and second, the view that slot resides in. Here is an example of using this method: viewChangedScript: func(slot, view) begin if slot := 'text then textChanged := true; //set flag if text was changed end

5-22

Other Messages

CHAPTER

Handling System Messages

viewDropChildScript
This message is sent when a view of the clEditView class is about to remove a child view. This method is passed one parameter: the child view. This method gives you a chance to remove the child view entry from your view's stepChildren array, or to do some other processing before the view is removed. If this method returns true, it is assumed that you have removed the child view entry from your stepChildren array. If this method returns nil, this is not assumed and it is done for you. In either case, the child view itself is deleted for you by the system. (Note that you can use the RemoveStepView function to delete the view yourself.) Here is an example of using this method: viewDropChildScript: func(child) begin EntryRemoveFromSoup(child); base:RedoChildren(); nil; end
Note

The system searches for this method only in the current view and its protos. The parent chain is not searched for the method. u

viewIdleScript
When an idler is installed for a view, this message is sent repeatedly and at regular intervals when the view is open, to allow you to do periodic tasks such as polling a network for information or updating a clock on the display. You install an idler for a view by sending it the SetupIdle message, which species an initial delay after which the viewIdleScript message is sent. The viewIdleScript method should return an integer which species the

Other Messages

5-23

CHAPTER

Handling System Messages

delay, in milliseconds, until it should be called again. For example, to have the system call this method every second, you should return 1000. To stop idling, you can return the value nil, or you can send the view the SetupIdle message with a value of zero. There is no default view-system operation that occurs during idlingonly the viewIdleScript message is sent.
Note

When you install an idler for a view, the time when the viewIdleScript message will next be sent is not guaranteed to be the exact interval you specify. This is because the idler may be delayed if a method is executing when the interval expires. The viewIdleScript message cannot be sent until an executing method returns. Do not install idlers that use extremely short intervals (less than 100 milliseconds). u Here is an example of using this method: viewShowScript: func() // initialize blinking sequence begin icon := onBitmap; self.numBlinks := 0; self:SetupIdle (750); // start in 3/4 second end viewIdleScript: func() begin if icon = onBitmap then icon := offBitmap; else begin icon := onBitmap; numBlinks := numBlinks + 1; end; self:Dirty();

5-24

Other Messages

CHAPTER

Handling System Messages

if numBlinks < 4 then // blink 4 times return 750; // return time until next blink numBlinks := 0; // else return 0 to stop blinking end This example blinks an icon in a view of the clPictureView class when the view is shown. Be careful not to send this message too frequently for long periods of time (for example, many times each second for a few minutes). This will cause the Newton hardware to consume signicantly more power than usual and will reduce battery life.
Note

The system searches for this method only in the current view and its protos. The parent chain is not searched for the method. u

Summary of System Messages


This section contains a summary of all the system messages described in this chapter. Initialization and Termination Messages viewSetupFormScript() viewSetupChildrenScript() viewSetupDoneScript() viewQuitScript() Drawing-Related Messages viewShowScript() viewHideScript() viewDrawScript() viewHiliteScript(on)

Summary of System Messages

5-25

CHAPTER

Handling System Messages

Scrolling and Overview Messages viewScrollDownScript() viewScrollUpScript() viewOverviewScript() Input-Related Messages viewClickScript(unit) viewStrokeScript(unit) viewGestureScript(unit, gestureKind ) viewWordScript(unit) Other Messages powerOffScript(what) printNextPageScript() soupChanged(soupName) viewAddChildScript(childTemplate) viewChangedScript(slot, view) viewDropChildScript(childView) viewIdleScript()

5-26

Summary of System Messages

CHAPTER

Written Input and Recognition

This chapter discusses how to control and work with written input and the recognition system. Also included is information on how to do hit testing of areas on the screen and how to work with dictionaries, which support recognition.

Overview
The Newton recognition system uses a sophisticated multiple-recognizer architecture. There are recognizers for words, shapes, and gestures. The word recognizers work together with built-in dictionaries to choose words that accurately match what the user has written. For each view, you can congure which recognizers are enabled and how they are congured. For example, the word recognizer can be set to recognize only names, or names and phone numbers, or only words in a custom dictionary that you supply, among other choices.

Overview

6-1

CHAPTER

Written Input and Recognition

Most recognition events are handled automatically by the system view classes so you dont need to do anything in your application to handle recognition events unless you want to do something special. For example, when a user writes a word in a clParagraphView, that view automatically passes the strokes to the recognizer, accepts the recognized word back, and displays the word. In addition, the view automatically handles correction for you. (The user can double-tap on a word to get a list of the top ve recognition matches for it, or to use the keyboard to correct it.)

Controlling Recognition in Views


As mentioned previously, the recognizers and dictionaries enabled for a particular view are congurable. The set of view ags specied in the views viewFlags slot define the set of recognizers and dictionaries that are enabled for the view, thereby determining the kinds of data that the user can enter in the view. For example, you could congure a set of view ags that enables the view to recognize words and numbers but not shapes. More information on combining sets of view ags to produce various recognition behaviors is provided later in this section.

View Flags for Recognition


The following view ags can be specied in the views viewFlags slot to control which kinds of pen input the view recognizes and handles. Note that not all options are available for each view type. For example, a view of the clView class can accept clicks (taps) but cant recognize words.
Note

Newton ToolKit displays these ags in an area of the screen called Entry Flags because these ags control the entry of recognized data. However, in the code that NTK generates (and when you set these ags procedurally) they are placed in the views viewFlags slot. Hence, this chapter refers to these ags as view ags. u

6-2

Controlling Recognition in Views

CHAPTER

Written Input and Recognition

Non-word options

vNothingAllowed The view accepts no handwritten or keyboard input. vAnythingAllowed This ag turns on all recognizers, theoretically allowing the view to accept any kind of input; however, the recognition actually performed for the view at run time is controlled by the user preferences settings and the settings of the recognition buttons at the bottom of the screen (the user can tap these buttons to enable recognition of text and graphics). You must be certain that the recognition buttons are visible when you use this ag, because it allows the creation of a state in which nothing is recognized: if recognition is turned off and the recognition buttons are not displayed, the user cannot enable recognition in the view.
Note

The vAnythingAllowed ag is a mask that sets and clears other ags. To avoid unexpected results when specifying ags programmatically, you need to use the Bor function to logically OR this flag with any others you specify for the view that uses vAnythingAllowed. (See the description of the Bor function in Chapter 17, Utility Functions.) If you use the entryFlags editor in NTK to specify view ags for the view, you need not do anything special to use this agthe editor makes appropriate settings with respect to other ags for you. u Note that youll obtain faster and more accurate recognition using the correct set of individual ags for the types of data that your view accepts. If you want to control specic recognizers, you need to use a combination of the other viewFlags settings. The system sends the viewClickScript message to the view once for each pen tap (click) that occurs within the view.

vClickable

Controlling Recognition in Views

6-3

CHAPTER

Written Input and Recognition

IMPORTANT

You must set the vClickable flag for any view that is to accept pen input; no taps or strokes are passed to the view if this ag is not set. s Views that explicitly handle clicks (such as buttons) or track the pen themselves can set this ag and use the viewClickScript method to implement their handling of pen input. The viewClickScript method can track the position of the pen by calling the GetPoint function; for more information, see the description of the GetPoint function in the section Recognition Functions,later in this chapter. Electronic ink is turned on or off depending on the vClickable flags interaction with the viewClickScript method and the settings of view ags for views in the parent chain. If vClickable is the only view ag set for the view, inking is automatically turned off; that is, no electronic ink is drawn in the view at pen-down time. However, if vClickable is not set for the view, any of its parent views may handle clicks or draw ink. Ink is turned on in views having a viewClickScript method. To turn off inking, the viewClickScript can call InkOff. Note also that the TrackHilite and TrackButton methods also turn off ink. vStrokesAllowed The view accepts handwritten strokes, and is sent the viewStrokeScript message at the end of each stroke. The only time you need to set this ag is when the view has a viewStrokeScript method. This method would be used to do something application-specic with strokes, such as recognizing your own gestures. Dont set this ag if your view does not have a viewStrokeScript methodyoull only waste battery power! You must also set the vClickable ag when using this ag; otherwise, the view accepts no input.

6-4

Controlling Recognition in Views

CHAPTER

Written Input and Recognition

For more information on the viewStrokeScript method, see the Different Strokes code sample from PIE DTS. vGesturesAllowed The view accepts gesture strokes such as scrub, hilite, tap, double tap, caret, and line. It is sent the viewGestureScript message when one of these gestures is written. Most views that accept input also set this ag so that gestures such as scrub can be used. You must also set the vClickable ag when using the vGesturesAllowed flag; otherwise, the view accepts no input. vShapesAllowed Enables shape recognition within the view. You must also set the vClickable ag when using this ag; otherwise, the view accepts no input. vSingleUnit Disables recognition based on spatial cues (distance between gestures or strokes), forcing the recognition system to rely on temporal cues (time between the end of one stroke and the beginning of the next one) to determine when the user has completed a group of strokes. Using this ag may result in better recognition of complex stroke groups in which users tend to put large spaces, such as phone numbers.
Word options

vCharsAllowed

Enables word recognition using the default dictionary chain dened for the view. The default dictionary chain for a particular view is dened according to the view class or system prototype from which the view is derived, as well as the current locale. Setting this ag includes in the chain dictionaries for common words, proper names, the user dictionary, and any userinstalled default dictionaries. For more information, see the section How Locale Affects Recognition in Chapter 15, Localizing Newton Applications.

Controlling Recognition in Views

6-5

CHAPTER

Written Input and Recognition

vLettersAllowed Enables letter-by-letter character recognition without using dictionaries; thus enabling this ag allows the view to recognize combinations of letters that are not dictionary items. Take care to use this ag only when necessary, as it can slow down recognition and make it less reliable. For example, non-word combinations of characters such as xyz can be recognized when the vLettersAllowed flag is set. The vLettersAllowed ag can be used in conjunction with vCharsAllowed or vCustomDictionaries. It does not allow numeric input and therefore cannot be used with vMathAllowed, vPhoneField, vNumbersAllowed, vDateField, vTimeField, or vAddressField. vNameField Enables word recognition using the Names dictionary as the primary dictionary. vMathAllowed Enables the recognition of math substrings containing numeric characters or the math symbols +, -, =, $, %, / and decimal points. Works best if not used in conjunction with other word recognition options. vCustomDictionaries Enables word recognition using custom dictionaries. This is used for views that accept custom sets of data (e.g., company names or plant species, etc.). You must include in the template a dictionary slot which contains a reference to a custom dictionary (or an array of references to multiple dictionaries). Or you can specify the id of one or more built-in dictionaries to limit recognition to that set of words (e.g., state names). vPunctuationAllowed Enables recognition of punctuation marks in addition to any other recognizers that are enabled. This ag enables recognition of the following marks preceding a word: single quotation mark, double quotation mark, left parenthesis, and hyphen. This ag also allows the recognition of the following marks at the end of a word:

6-6

Controlling Recognition in Views

CHAPTER

Written Input and Recognition

vCapsRequired

single quotation mark, double quotation mark, right parenthesis, hyphen, period, comma, exclamation point, question mark, colon, and semicolon. Forces the rst character of each word to be capitalized when it is returned from the recognition system.

Lexical word options

These options can be used simultaneously with all other options except for vLettersAllowed. vNumbersAllowed Enables recognition of numbers. Numeric recognition includes monetary amounts (for example, $12.25), decimal points, and signs (+ and -). vPhoneField Enables recognition of phone numbers. vDateField Enables recognition of dates. vTimeField Enables recognition of times.

Combining View Flags


Multiple ags are typically specied for a single view. Keep in mind that Less is more when conguring view ags. That is, the fastest and most accurate recognition occurs when the fewest recognizers necessary to successfully analyze the input are enabled. Enabling unnecessary recognizers can potentially slow down recognition and introduce errors. The following examples describe how to combine view ags for to produce different kinds of recognition behaviors. To enable a view to recognize numbers and gestures such as scrubbing and highlighting, use these ags: vClickable+vGesturesAllowed+vNumbers
Note

Note that all of these combinations of view ags include the vClickable flag. You must set vClickable or the view will not accept pen input! u

Controlling Recognition in Views

6-7

CHAPTER

Written Input and Recognition

To enable a view to recognize normal words with punctuation and gestures, use these ags: vClickable+vGesturesAllowed+vCharsAllowed+vPunctuationAllowed To enable a view to support only math substrings and gestures, use these ags: vClickable+vGesturesAllowed+vMathAllowed

Text Flags
You can add an evaluate slot named textFlags to any view derived from the clParagraphView class to control certain aspects of text-handling and recognition behavior for that view. Spaces are suppressed as input to this eld; that is, the word returned by the recognizer has no spaces in it. vWidthIsParentWidth The right boundary of the text eld is extended to match that of its parent. You do not need to set this value yourself; the system sets it for you in views that use it. vNoSpaces

Using Dictionaries
When word recognition is enabled and letter- by-letter recognition is not enabled, the system attempts to match user input strokes in the view with items stored in one or more dictionaries. A dictionary can be supplied by the system or by the application, and can reside in RAM or in ROM. This section explains the use of the system-supplied dictionaries. The creation and use of custom dictionaries is later in this chapter, in the section RAM-based Dictionaries.

6-8

Using Dictionaries

CHAPTER

Written Input and Recognition

Enumerated and Lexical Dictionaries


There are two kinds of dictionaries used by the system: enumerated and lexical. An enumerated dictionary is simply a list of dictionary items (strings) that can be matched. A lexical dictionary species a grammar or syntax that is used to classify user input. The kind of dictionary used for a particular task is dependent upon task-specic requirements. The system-supplied dictionaries include both enumerated and lexical dictionaries. Dictionaries can be in ROM or in RAM. Most of the system-supplied dictionaries are in ROM; however, the user dictionary resides in RAM. Note that RAM-based and ROM-based custom dictionaries can also reside on a PCMCIA card.

System-Supplied Dictionaries
The system supplies various enumerated and lexical dictionaries used by the recognition system. The set of dictionaries involved in recognition for a particular view is specied by a combination of the default settings, the locale specied in user preferences and the set of view ags enabled for the view. Table 6-1 describes the system-supplied dictionaries accessible from NewtonScript. These dictionaries are available in every locale.
Table 6-1 System-supplied enumerated dictionaries Contents

Dictionary ID (constant)

kUserDictionary kCommonDictionary kCountriesDictionary kDaysMonthsDictionary kFirstNamesDictionary kLastNamesDictionary kSharedPropersDictionary

words added by the user commonly-used words names of countries names of days and months rst names surnames proper names

Using Dictionaries

6-9

CHAPTER

Written Input and Recognition

Note

Although these constants currently evaluate to integers, do not rely on these values. Use only the appropriate constant names to reference these dictionaries. u

Locale-specic Dictionaries
In addition to the dictionaries described in Table 6-1, several enumerated dictionaries containing location-specic information are congured according to the locale specied in user preferences.These dictionaries are listed in Table 6-2.

Table 6-2

Locale-specic enumerated dictionaries Contents

Dictionary ID (constant)

kLocalPropersDictionary kLocalCitiesDictionary kLocalCompaniesDictionary kLocalStatesDictionary kLocalStatesAbbrevsDictionary

proper names names of local cities names of local companies names of states, provinces, etc. abbreviations of states, provinces, etc.

Note

Although these constants currently evaluate to integers, do not rely on these values. Use only the appropriate constant names to reference these dictionaries. u The system also supplies lexical dictionaries that dene certain location-specic formats; these dictionaries are listed in Table 6-3.
Note

Although these constants currently evaluate to integers, do not rely on these values. Use only the appropriate constant names to reference these dictionaries. u

6-10

Using Dictionaries

CHAPTER

Written Input and Recognition

Table 6-3

Locale-specic lexical dictionaries Contents

Dictionary ID (constant)

kDateLexDictionary kTimeLexDictionary kMoneyLexDictionary kNumberLexDictionary

date formats time formats currency formats numeric formats

RAM-based Dictionaries
Besides using the system-supplied dictionaries, your application can use custom dictionaries to recognize specialized terms, such as medical or legal vocabulary. Currently, you can create RAM-based custom dictionaries. Future versions of NTK will allow developers to create dictionaries residing on PCMCIA cards (ROM or RAM.

About the User Dictionary


Applications must never add items to the user dictionary without the users consent, for several reasons. The rst is that the user dictionary is intended to be solely in the users controladding items to it is akin to changing the users handwriting preferences or Names le entries. Its also important to leave room for users to store their own items.
IMPORTANT

An excessively large user dictionary can slow the system when performing searches that are not related to your application. It is therefore recommended that applications do not add items to the user dictionary at all. s On the Newton MessagePad, the user dictionary browser supports a total of about 3,000 items in the RAM-based user dictionary. Note that this number may change in future Newton devices.

Using Dictionaries

6-11

CHAPTER

Written Input and Recognition

Creating a RAM-based Dictionary


Its relatively easy to create a RAM-based enumerated dictionary at run time. The ability to create a lexical dictionary or ROM-based dictionaries (lexical or enumerated) will be included in a future release of NTK. You can take the following steps to create a RAM-based enumerated dictionary at run time: 1. Use the global function NewDictionary to create a new empty dictionary. 2. Use the global function AddWordToDictionary to add dictionary items to the new dictionary. 3. Use the global function GetDictionaryData to create a binary representation of the completed dictionary, which can then be stored in a soup. Another way to do this is to create a new dictionary and restore its data from a soup. The next several sections describe the numbered steps in greater detail. Following this discussion, the section Restoring Dictionary Data From a Soup describes how to restore an existing dictionary from soup data. About Dictionary Items To create a custom enumerated dictionary, you must populate a blank RAM-based dictionary with your dictionary items. Dictionary items can come from a number of places: they might be elements of your own array of strings stored in the applications Project Data le; they could be represented as binary resource data in your applications NTK project; they might be supplied by the user in an input line view; they might even arrive as serial data. Because dictionary items can originate from a number of sources, the example here presumes that you know how to store your word strings and pass them, one at a time, to the AddWordToDictionary function. The AddWordToDictionary function does not place any restrictions on the strings to be entered in the dictionary. For non-recognition purposes, any string is a valid dictionary entry; for example, you might use a dictionary to

6-12

Using Dictionaries

CHAPTER

Written Input and Recognition

restrict entries in a data eld to a specied set of valid entries. For use in stroke recognition, however, each string in an enumerated dictionary must have the following characteristics:
n n

The string must consist entirely of lowercase alphabetic characters. The string must not include spaces, digits, or non-alphabetic characters.

Creating the Blank Dictionary You can create a blank RAM-based dictionary anywhere in your application that makes sense; a common approach is to take care of this in the viewSetupFormScript method of the applications base view. You must also create a slot in which to store the RAM-based dictionary. The following code fragment creates a dictionary in the mySpecialDictionary slot. viewSetupFormScript:func() begin local element; mySpecialDictionary := NewDictionary('custom); end, This code example uses the NewDictionary function to create a blank dictionary in the mySpecialDictionary slot. The NewDictionary function accepts the symbol 'custom as its argument, which species that the new dictionary is for this applications use only.
Note

Although the token returned by the NewDictionary function currently evaluates to an integer in the Inspector, the type of value returned by this function may change on future Newton devices. Do not rely on the NewDictionary function returning an integer. u

Using Dictionaries

6-13

CHAPTER

Written Input and Recognition

Populating the Blank Dictionary Once you have created a blank dictionary, you need to populate it with your dictionary items. You can use the AddWordToDictionary function to add a specied string to a specied RAM-based dictionary. The rst argument to this function is the identier of the dictionary to which the string is to be added; this identier is returned by the NewDictionary function. The previous code example stored this identier in the mySpecialDictionary slot. The second argument to this function is the string to be added to the dictionary. If this argument is not a string, the AddWordToDictionary function throws an exception. If the word is added successfully, this function returns TRUE. If the specied word cannot be added because it is already present in the specied dictionary, this function returns NIL. To populate the dictionary, you need to call the AddWordToDictionary function once for each item to be added. There are many ways to iteratively call a function; the best approach for your needs is an application-specic detail that cannot be anticipated here. The following code example shows one way to populate a blank dictionary. myAdder:func() begin local element; // items slot contains an array of dictionary strings foreach element in items do AddWordToDictionary(mySpecialDictionary, element); end This approach works well for small dictionaries; for most large dictionaries, however, it is far more efcient to populate the dictionary from saved soup data. You should store custom dictionary data in a soup so that it is safely stored and persistent across warm boots.

6-14

Using Dictionaries

CHAPTER

Written Input and Recognition

Saving Dictionary Data to a Soup Once you have added all of your dictionary entries, your RAM-based custom dictionary is ready for use. However, it would be rather inefcient to have to build it from scratch each time you need it, especially if the dictionary is large. Instead, you can store a binary representation of the dictionary data in a soup and use this soup data to restore the custom dictionary. The NewDictionary function returns an identier used to reference the dictionary; in the previous example, this identier was stored in the slot mySpecialDictionary, which is defined in the base view of the application. You can pass a path expression to this slot as the argument to the GetDictionaryData function, which returns a frame containing a binary representation of the dictionary data (the words or items). You can then store this frame in a soup. The following code fragment assumes that the soup kSoupName is a valid soup created according to the PIE DTS soupcreation guidelines. // make sure the soup is open & available mySoup := GetUnionSoup (kSoupName); // create binary representation of dictionary data local dict := GetRoot().appSym.mySpecialDictionary; local theObj:= GetDictionaryData(dict); // store the dictionary data dictData := {data:theObj}; mySoup:Add(dictData); Restoring Dictionary Data From a Soup To use the dictionary, your application needs to retrieve the dictionary data object from the soup and use the global function SetDictionaryData to install the data in an empty dictionary. This is typically done in the application packages installScript method or in the viewSetupFormScript method of the view that uses the custom dictionary, as in the following code example.

Using Dictionaries

6-15

CHAPTER

Written Input and Recognition

// make new blank dictionary mySpecialDictionary := NewDictionary('custom); // get the dictionary data from the soup // structure of query depends on how you store data dataCursor:=Query(dictDataSoup,querySpec); // how you get entry depends on how you store data myBinaryData := dataCursor:entry(); // put data in dictionary SetDictionaryData(mySpecialDictionary, myBinaryData);

Using the RAM-based Dictionary


This section describes how to make a RAM-based dictionary available to your view. The dictionary is made available to the view by means of a dictionaries slot that the view can access. You need to take the following steps to make your RAM-based dictionary available: 1. Set the vCustomDictionaries ag for the view that is to use the dictionary. This ag indicates that the view has a slot named dictionaries which contains the identifiers for all dictionaries to be used in recognition for this view. 2. Create a dictionaries slot that is accessible to the view& store your dictionarys identier in it. Making Dictionaries Available In the view that is to use the custom dictionary, you need to create a slot called dictionaries which stores an array of dictionary identiers. You need to install the newly created dictionary in this slot using code similar to the following example. // vCustomDictionaries flag already set in NTK // search custom dictionary only dictionaries := [mySpecialDictionary];

6-16

Using Dictionaries

CHAPTER

Written Input and Recognition

If no ags other than vCustomDictionaries are set in the entryFlags editor in NTK the default system dictionary chain is empty and the only dictionary used for recognition in this view is the custom dictionary. If you want to search the custom dictionary in addition to the systemsupplied dictionaries, just check the appropriate view ags in the Entry Flags editor in NTK and add only your custom dictionary to the dictionaries slot. (Dont forget to check the vCustomDictionaries ag as well.) If you want to enable dictionaries procedurally, rather than in the NTK entryFlags editor, you can add the appropriate ags to the views viewFlags slot. Each view ag enables a particular combination of system dictionaries; if you want to explicitly control which system dictionaries are used, check only the vCustomDictionaries flag in NTK and use the constants described previously in the System-Supplied Dictionaries section to add specic dictionaries to the dictionaries slot. For example, dictionaries :=[mySpecialDictionary, kUserDictionary, kCommonDictionary] The order in which dictionaries appear in the dictionaries array is not critical; the recognition system searches all of the dictionaries at once.

Removing a RAM-based Dictionary


It is recommended that you remove your custom dictionary when it is no longer needed, such as when your application is removed. The DisposeDictionary function removes a specified RAM-based dictionary and always returns NIL. The DisposeDictionary function accepts one argument, the dictionary identier returned by NewDictionary. In an earlier example, this identier was stored in the mySpecialDictionary slot; hence, a line of code similar to the following example would be used to remove the custom dictionary. DisposeDictionary(mySpecialDictionary);

Using Dictionaries

6-17

CHAPTER

Written Input and Recognition

Function Reference
This section describes global functions related to recognition, hit-testing, and dictionaries.

Recognition Functions
These functions operate on ink, points, strokes, and words. InkOff InkOff(unit) unit The stroke unit passed to the viewClickScript and viewStrokeScript methods when the user touches the pen to the screen.

Turns off the display of electronic ink for the stroke contained in the specied stroke unit. This function always returns TRUE. SetInkerPenSize SetInkerPenSize(size) size The width of the pen, in pixels.

Sets the thickness of the electronic ink drawn on the screen. The pen size can range from 1 to 4 pixels wide; the system default is 2. This function returns NIL if the pen size was set successfully, otherwise an error code is returned.

6-18

Function Reference

CHAPTER

Written Input and Recognition

Note

This function only changes the width of ink as it is drawn by the system. To ensure that ink is properly displayed and updated under all circumstances, your application must set the value of userConfiguration.userPenSize appropriately and then pass this value as the argument to the global function SetInkerPenSize. u The following code example sets the inker pen size to the value 4. sysSoup:=Getstores()[0]:GetSoup(ROM_SystemSoupName); configCursor := Query(sysSoup, {type:'index, indexPath:'tag, startKey:"userConfiguration"}); userConfigs := configCursor:Entry(); userConfigs.userPenSize := 4 SetInkerPenSize(userConfigs.userPenSize); GetPoint GetPoint(selector, unit ) selector species which point coordinate is returned. You must specify one of the following predened values for selector: firstX firstY finalX finalY unit The x coordinate of the rst point in the stroke The y coordinate of the rst point in the stroke The x coordinate of the last read point in the stroke The y coordinate of the last read point in the stroke

The stroke unit passed to the viewClickScript and viewStrokeScript methods when the user touches the pen to the screen.

Function Reference

6-19

CHAPTER

Written Input and Recognition

Returns one of two different kinds of point coordinates that are part of the stroke contained in the specied stroke unit. All points returned are in global (screen) coordinates. Note that if you specify finalX or finalY, the coordinate returned could be that of a point in the middle of a stroke in progress, rather than the nal point in the stroke. If the user is still drawing the stroke when this function is called, the coordinate of the last point read by the system may not be the last point in the stroke. You can test if the stroke is actually done by using the function StrokeDone. StrokeDone StrokeDone(unit) unit The stroke unit passed to the viewClickScript and viewStrokeScript methods when the user touches the pen to the screen.

Returns TRUE if the stroke contained in the specied stroke unit has been completed by the user (they have lifted the pen from the display). Returns NIL if the stroke is not done. StrokeBounds StrokeBounds (unit) unit The stroke unit passed to the viewClickScript and viewStrokeScript methods when the user touches the pen to the screen.

Returns a bounds frame describing the boundaries of the stroke unit in its view. A bounds frame has this structure: {left: n , top: n, right: n , bottom: n}

6-20

Function Reference

CHAPTER

Written Input and Recognition

GetPointsArray GetPointsArray(unit) unit The stroke unit passed to the viewClickScript and viewStrokeScript methods when the user touches the pen to the screen.

Returns an array of points in the stroke unit.The array consists of coordinate pairs describing the points. The rst element contains the Y coordinate of the rst point and the second element contains the X coordinate, and so on. (Note that this is reversed from the usual way that coordinate pairs are written.) Coordinates are global; that is, they are relative to the upper-left corner (0, 0) of the screen. GetWordArray GetWordArray(unit) unit The stroke unit passed to the viewClickScript and viewStrokeScript methods when the user touches the pen to the screen.

Returns an array of strings that are the recognition choices for the stroke unit passed as an argument. The rst element in the array is the word with the highest probability of matching the stroke that the user wrote. The following words are alternate choices in descending order of matching condence. Note that the words returned aren't necessarily alphabetic words. They can be numbers, phone numbers, times, or any other special kind of recognized characters.

Function Reference

6-21

CHAPTER

Written Input and Recognition

GetScoreArray GetScoreArray(unit) unit The stroke unit passed to the viewClickScript and viewStrokeScript methods when the user touches the pen to the screen.

Returns an array of numbers that are the recognition condence scores for each of the words returned by GetWordArray. There is one score for each word. A score can range from 1 to 1000, with a lower number representing a higher recognition condence.

Hit Testing Functions


These functions allow you to determine whether a point or stroke lies within a specied shape. HitShape HitShape(shape, x, y) x y shape The x-coordinate of the point to be tested, in local (view) coordinates The y-coordinate of the point to be tested, in local (view) coordinates a shape returned by one of the drawing routines that creates shapes (such as MakeRect, MakeOval, MakeRegion, MakePolygon, and so on.) You can specify an array of shapes for shape, and in this case, each shape in the array is hit tested with the point. If a hit is found, the function returns immediately and subsequent shapes in the array are not tested.

Returns TRUE if the point described by the x and y coordinate parameters lies within the shape. Returns NIL if the point is outside the shape. The result on an unclosed polygon is undened.

6-22

Function Reference

CHAPTER

Written Input and Recognition

PtInPicture PtInPicture(x, y, bitmap) x y bitmap The x-coordinate of the point to be tested, in local (view) coordinates The y-coordinate of the point to be tested, in local (view) coordinates The bitmap object associated with the mask to be tested

Returns TRUE if the point described by the x and y coordinates lies within the mask associated with the specied bitmap object. If no mask is dened for the specied bitmap, this function tests whether the point lies within the bitmap itself. This function returns NIL if the point is outside the test area.

Dictionary Functions
These functions allow you to look up words in the built-in dictionaries and to work with your own custom dictionaries. GetRandomWord GetRandomWord(minLength, maxLength) minLength maxLength the minimum number of characters in words returned by this function the maximum number of characters in words returned by this function. This function does not return words longer than 20 characters, regardless of the value specied by this argument.

Returns a string that is a word chosen at random from the common word dictionary. The string returned by this function is at least minLength characters long but not more than maxLength characters long. This function does not return any word longer than 20 characters. The GetRandomWord function uses random numbers generated by the system to select words from the dictionary. To begin a new sequence of

Function Reference

6-23

CHAPTER

Written Input and Recognition

random words you must rst initialize the random number generator using the SetRandomSeed function. You need only call SetRandomSeed once to begin a new sequence of random words. For more information, see the discussion of the SetRandomSeed function in Chapter 17, Utility Functions. LookupWordInDictionary LookupWordInDictionary(dictID,word ) dictID word identier specifying the dictionary to be searched the string to be found in the specied dictionary

This function looks up the specied string in the dictionary indicated by dictID, and returns TRUE if the word is there, NIL if it was not. DeleteWordFromDictionary DeleteWordFromDictionary(dictID,word ) dictID word identier specifying the dictionary to be searched the string to be removed from the specied dictionary

This function removes the specied word from the RAM-based dictionary indicated by dictID, returning TRUE if the word is removed and NIL if it is not. A NIL result usually indicates that the specied word was not found in the dictionary indicated by dictID. It is an error to call this function on a ROM-based dictionary. AddToUserDictionary AddToUserDictionary(wordString ) wordString The string to be added to the user dictionary

Adds the word to the user dictionary. This function returns TRUE if the word was added, or NIL if the word already exists in the dictionary.

6-24

Function Reference

CHAPTER

Written Input and Recognition

SaveUserDictionary SaveUserDictionary() Saves the user dictionary to the permanent system soup. This saves any changes that have been made to the dictionary. NewDictionary NewDictionary(dictionaryKind) Creates a new RAM-based dictionary and returns a dictionary identier for it. The dictionary identier is used in the other custom dictionary functions. dictionaryKind species how the dictionary is to be used. Currently, only the symbol 'custom has any meaning as an argument to this function. If you pass 'custom, the dictionary is used for recognition only in views where it is specied in a dictionaries slot in conjunction with the vCustomDictionaries viewFlag (refer to the previous section, Controlling Recognition in Views.)

Note

Although the token returned by the NewDictionary function currently evaluates to an integer in the Inspector, the type of value returned by this function may change on future Newton devices. Do not rely on the NewDictionary function returning an integer. u DisposeDictionary DisposeDictionary(dictionary) dictionary The dictionary to be deleted

This function deletes the specied RAM-based dictionary and always returns NIL.

Function Reference

6-25

CHAPTER

Written Input and Recognition

AddWordToDictionary AddWordToDictionary(dictionary, wordString ) dictionary wordString The dictionary to which this function adds the specied string The string to be added to the specied dictionary

Adds the word to the specied RAM-based dictionary, returning TRUE if the word was added successful. If the word could not be added, this function returns NIL. GetDictionaryData GetDictionaryData(dictionary) dictionary The dictionary from which this function extracts data.

Returns a binary representation (an object of class 'dictdata) of the specied dictionarys word list. You can use this function to store dictionary data in a soup. SetDictionaryData SetDictionaryData(dictionary, binaryObject) dictionary binaryObject The dictionary into which this function loads data. The binary object from which this function extracts data.

Retrieves dictionary data (the words) from the specied binary object and loads them into the specied dictionary. This function always returns NIL. You can use this function to populate a blank dictionary with dictionary items stored in a soup.

6-26

Function Reference

CHAPTER

Written Input and Recognition

Summary of Recognition Functions


This section categorizes the input and recognition functions by task.

Recognition Functions
GetPoint(selector, unit) GetPointsArray(unit) GetScoreArray(unit) GetWordArray(unit) InkOff(unit) SetInkerPenSize(size) StrokeBounds (unit) StrokeDone(unit)

Hit-Testing Functions
HitShape (shape, x, y) PtInPicture(x, y, bitmap)

Dictionary Functions
AddToUserDictionary(wordString ) AddWordToDictionary(dictionary, wordString ) DeleteWordFromDictionary(dictID, word ) DisposeDictionary(dictionary) GetDictionaryData(dictionary) GetRandomWord(minLength, maxLength ) LookupWordInDictionary(dictID, word ) NewDictionary(dictionaryKind) SaveUserDictionary() SetDictionaryData(dictionary, binaryObject)

Summary of Recognition Functions

6-27

CHAPTER

Data Storage and Retrieval

Newton applications store data in a common format called the frame. Dissimilar data types can be stored in any frame and a common set of predened data types supported by all frames allow Newton applications to share data virtually transparently. Frames can grow and shrink dynamically, and frame data is automatically compressed and decompressed by the object system when the frame is accessed or stored. This chapter describes the Newton data storage model and the systemsupplied functions and methods used to store and retrieve data.

Overview
Related frames are grouped in persistent objects called soups. A soup resides in a repository called a store on a physical storage device. This overview describes the relationships between these objects.

Overview

7-1

CHAPTER

Data Storage and Retrieval

Frames and Slots


The basis of data storage on the Newton is an object called the frame. Like a database record, a frame stores data items. Frames are dynamic; in other words, they can grow and shrink as necessary. Thus the frame offers an extremely exible and efcient means of storing data. Individual data items in the frame are stored in slots, which may be thought of as the elds of the database record. Slots can store data directly, using predened data types to represent strings, numeric formats, arrays, and binary objects. These system-supplied data types, in conjunction with the frames-based data storage model, allow Newton applications to share data directly. A single slot can store items of dissimilar data types. Slots can also store frames and references to frames, slots, and binary objects. This feature of the object system is used to provide dynamic slot lookup and message-passing among frames, as well as slot-based inheritance of frame data. For example, the view object system relies heavily on slot-based inheritance to share attributes and data among view objects. Frames dont impose any structure on their data, other than the requirement that it must reside in a slot. In practical use, though, the slots in a frame are usually related to each other in some way. They generally store related data and methods that operate on those data, embodying in many ways the classic object-oriented programming denition of an object. Frames do not implement data hiding, however, nor do they necessarily encapsulate their data. For more information about the concepts touched upon here, see The NewtonScript Programming Language . It contains detailed discussions of frames, slots, system-supplied data types, dynamic slot lookup, message passing and inheritance in NewtonScript.

Soups
Frames can be stored in a persistent data structure called a soup. A soup is simply a collection of frames. The object system does not impose any limitations on the number of frames or the kinds of data that may reside in a soup. In practical use, though, the items in a soup generally have some relationship to one another. 7-2

Overview

CHAPTER

Data Storage and Retrieval

Stores
The soup resides on a store, which is a logical data repository on a physical storage device. A store may be likened to a disk or volume on a personal computer; just as a disk can have multiple partitions, a physical storage device can house multiple stores. The Newton MessagePad has an internal store and supports a single external store on a PCMCIA device; however this may change in future Newton devices. Soups can exist on internal or external stores; a special kind of soup, the union soup, is composed of multiple soups residing on multiple stores.

Union Soups
A union soup is a logical grouping of single soups having the same name. Union soups allow applications to treat multiple soups on various available stores as a single entity. Union soups are accessed by calling the systemsupplied global function GetUnionSoup. Recall that the user can specify in the Card dialog whether to store new data items on the PCMCIA store or the internal store. Use of union soups makes it easy to respect the users wishes when writing data to the store; the AddToDefaultStore method is used with union soups to write soup data to the correct store as specied by the user. The next section describes how all soups store frame data.

Entries
A frame stored in a soup is referred to as an entry in that soup. Returning to the database analogy, you can think of entries as the individual records in the database, and you can think of the soup as the database itself. Like a database, soups are opaqueyou retrieve soup entries by querying the soup, rather than by examining its records directly. Soups are automatically indexed, and applications can create additional indexes to be used when querying for data items.

Overview

7-3

CHAPTER

Data Storage and Retrieval

Queries and Cursors


A soup query returns a cursor, which is an object used to navigate soup data. The cursor object provides methods to iterate over the entries meeting the search criteria specied in the query. Cursors are updated dynamically; if soup entries meeting the search criteria are added or deleted after the original query is made, these changes are automatically reected in the set of entries returned by the cursor.

Modifying Entry Frames


Soup entries returned by the cursor are not decompressed until they are referenced, at which time the system constructs in RAM the entire entry frame and the transitive closure of its pointers (that is, everything the entry frame points to, everything its data structures point to, and so on). This scheme improves both the speed and efciency of the Newton data storage model by reducing the time necessary to perform a query and by reducing the amount of storage required by a cursor object. When the entry is decompressed, it is cached in RAM until it is written back to the soup. Thus, applications can modify the entry frame directly once it is obtained from the cursor.

Storing Persistent Data


Decompressed entry frames remain in the cache (RAM) until the application writes them back to the soup by calling the global function EntryChange. Your application needs to call EntryChange for each entry that is to be saved to the soup.

Soups and Boots


The microprocessor in a Newton device never shuts down completely, but instead sleeps when it is not in active use; thus, RAM does not normally need to be reinitialized when the Newton device is powered up. This allows

7-4

Overview

CHAPTER

Data Storage and Retrieval

the device to return to a working state quicklyvirtually the same one last seen by the user because soups remain in RAM until they are removed explicitly, even if the machine is powered down. This working state is preserved unless a misbehaving application should corrupt RAM, or a hard reset occurs. Newton devices can perform two kinds of resets: the soft reset and the hard reset. Soft Resets and Soup Data A soft reset can be initiated in software by the operating system or in hardware by the user. When the operating system cannot obtain enough memory to complete a requested operation, it may display a dialog box advising the user to reset the Newton device. The user can tap the Reset button displayed in the dialog box to initiate the soft reset, or can tap the Cancel button and continue working. The user may also initiate a soft reset by pressing a hardware button provided for this purpose. This button is designed to prevent its accidental use; on the MessagePad, it is recessed inside the battery compartment and must be pressed with the Newton stylus or similarly-shaped instrument. A soft reset may also be caused by misbehaving application software. When the soft reset occurs, soup data residing on the store remains intact, but the cache is reinitialized. Any frames in the cache are lost, such as new or modied entries that have not been written back to the soup. One way to minimize the occurrence of unexpected resets is to utilize exception-handling code where appropriate. Unfortunately, the only way to mimes the consequences of a soft reset is to be prepared for one to happen at any time. Your application needs to write changed entries back to the soup as soon as is feasible. Its also advisable to test your applications ability to recover from a soft reset. The exact sequence of steps required to soft reset the Newton MessagePad is documented in its user guide.

Overview

7-5

CHAPTER

Data Storage and Retrieval

Hard Resets and Soup Data A hard reset occurs at least once in the life of any Newton device; that is when it is initially powered on. When the hard reset occurs, all internal RAM is returned to a known state: all soups are erased, all caches are purged, all application packages are erased from the internal store, application ram is reinitialized, the NewtonScript heap is reinitialized, and the operating system restarts itself. Its the end (or beginning) of the world as your application knows it.
Note

Data on external stores is not affected by a hard reset.

A hard reset is initiated only in hardware by the user. Extreme precautions have been taken to ensure that this action is deliberate. On the MessagePad, the user must simultaneously manipulate the power and reset switches to initiate the hardware reset. After this is accomplished, the hardware reset displays two dialog boxes warning the user that all data is about to be erased; the user must conrm this action in both dialog boxes before the hard reset takes place. It is extremely unlikely that misbehaving application software would cause a hard reset. However, a state similar to hardware reset may be achieved if the battery that backs up internal RAM is removed or fails completely. Again, its advisable to test your applications ability to install itself and run on a system that has been initialized with a hard reset. The exact sequence of steps required to hard reset the Newton MessagePad is documented in its user guide.

Sharing Soup Data


As you know, one of the primary purposes of the frames-based storage model is to facilitate the sharing of data. Thus, the object system provides a means of notifying other objects when soup data changes. (For more information, see the section Sharing Soups With Other Applications, later in this chapter.

7-6

Overview

CHAPTER

Data Storage and Retrieval

Its also recommended that you document the format of your applications soup entries for use by other applications. Refer to Chapter 8, Accessing System Data, for an example of how to document your own soup formats; it contains descriptions of the soups used by the applications built into the MessagePad ROM.

Optimizing Data Storage Performance


Despite the many advantages offered by soup-based data storage, there are times when storing data in other formats may improve your applications performance or reduce its RAM requirements. This section explains performance issues related to the use of soups and offers suggestions for optimizing your applications approach to data storage.

Soup Overhead
Because each entry in a soup is a frame, the price you pay for using soup-based storage can be measured in the amount of time required to nd slots at run time, the space required to expand soup entries and the space required to store the resulting entry frames on the NewtonScript heap. For many uses, the benets offered by the use of soups outweigh these costs; however, other approaches may be more suitable for certain data sets. Using a soup to store a simple list of key and value pairs can be a poor choice if implemented incorrectly. For example creating a group of slots, each of which contained the name of a state and its postal code, such as myFrame := {state:California, postCode:95051} would be a poor implementation because it would require more heap space than if the data were stored in a simple array.

Optimizing Data Storage Performance

7-7

CHAPTER

Data Storage and Retrieval

Alternatives to Using Soups


A large list of read-only data, like the aforementioned list of states and postal codes, is best stored as single array, frame, or binary object in a slot in the applications base view. Information stored in this way is compressed along with your application package and is not brought into the NewtonScript heap when it is accessed. The primary disadvantages of this scheme are that the data set is read only and that you cannot take advantage of the conveniences provided by soup queries. If your application makes use of a large initial data set to which the user can make additions, you might consider a hybrid approach: keep the initial data set in your base view and use a soup only for the users additions.

Optimizing Alternative Storage Schemes


If you decide not to store your data in a soup, consider the following points.
n

Dont be too quick to discount frames as your data structure of choice slot lookup is actually quite fast. Storing data as a binary object can help you avoid some of the overhead associated with array and frame data structures. In general, binary objects may let you store your data more compactly, but youll pay more to access it: youll need to use the various ExtractDataType functions to retrieve items. Note that the ExtractCString and ExtractPString functions create a string object in the NewtonScript heap for each string extracted from a binary object. Consider storing symbols for repeated strings rather than storing the strings themselves. When you dene a symbol for an object (such as a string or frame), only one copy of the actual object is stored in the application package, and all of the symbols reference it. Remember that symbols (slot names) can include non-alphanumeric characters if the name is enclosed by vertical bars; for example, the space in the symbol '|Chicken Little| would normally be illegal syntax because it contains a space, but the vertical bars suppress the usual evaluation of all characters they enclose. Keep arrays sorted, thereby allowing you to use binary searches to perform lookups.

7-8

Optimizing Data Storage Performance

CHAPTER

Data Storage and Retrieval

The remainder of this chapter expands upon the concepts introduced in this overview. Separate sections discuss the implementation-specic details of using stores, soups, queries, cursors and entries. Each sections includes a reference to those functions and methods related to its main topic.

Stores
A store is a logical repository for data in the Newton system. You can think of it like a disk volume on a personal computer. The Newton has a single built-in store, and there may be other stores present on PCMCIA cards and other devices. Each store is identied by a name, which is not necessarily unique, though a store has a nearly-unique random number signature. A store may contain one or more soups. (Soups are described in the next section, Soups.) This section describes functions and methods for
n n n

accessing information about the store and its contents reading and writing store data creating soups on stores

Store Functions
The following functions and methods allow you to get information about all of the currently available stores, get and set the information frame that describes the store and its contents, obtain lists of soups and packages present on the store, create soups, and write soups and packages to the store.

About the Store Metasymbol


Many of the methods described in this section take the form of messages that are sent to an object. The notation store is a replaceable metasymbol representing the store object to which the message is sent in order to invoke

Stores

7-9

CHAPTER

Data Storage and Retrieval

its method. For example, the notation store:CheckWriteProtect() means send the CheckWriteProtect message to the store object represented by the store metasymbol. In your application, the code to invoke this method would look similar to the following code example. myStore:CheckWriteProtect(); CheckWriteProtect store:CheckWriteProtect() Returns NIL if the store can be written; throws an exception if the store is locked or in ROM. This function is used to test whether the store can be written before executing a complicated operation; it provides a graceful exit if the store cant be written. If the store is in ROM, this function throws |evt.ex.fr.store|(kFramesErrStoreIsROM). If the store is not in ROM, but is write-protected, it throws |evt.ex.fr.store|(kSError_WriteProtected). For example, myStore:CheckWriteProtect(); //exit if we cant write myStore:SetAllInfo({info:{<<huge info frame>>}}); CreateSoup store:CreateSoup (soupName, indexArray ) Creates a soup called soupName on the specied store and returns a reference to the soup object created. Any existing union soups with the same name are updated to include the newly created soup, as are any existing cursors. soupName A case-insensitive string up to 39 characters long that species the name with which the soup is to be created.

7-10

Stores

CHAPTER

Data Storage and Retrieval

indexArray

An array of frames specifying the characteristics of indexes that you want the soup to possess. Each indexArray frame has the following slots: structure Species the kind of index. Currently, only the symbol 'slot can be specied, indicating that the index key is the value of a slot in each soup entry. path The path to the slot which is the index key. This is a path expression, which means it is either a symbol (for a simple path) or an array of class PathExpr in which individual elements are symbols for example, [PathExpr:'x.y.z] would be one example of such an array. For a complete explanation of path expressions, see The NewtonScript Programming Language. type The data type of the index key slot. This can be an integer (specify 'int), a string (specify 'string), a character (specify 'char), a real number (specify 'real), or a symbol (specify 'symbol).

Soups commonly contain frames that store similar types of data. For example, the built-in Names soup contains frames that all look alikethey each contain slots that match the data on a card in the Names application. Some frames contain optional slots that others don't have, but they each have the same core set of slots. This allows you to create an index that makes searching for frames easier and faster. You don't need to specify an index for a soup, but an index speeds up queries on the soup and it causes the results of a query to be sorted on the index key slot. You should create an index for each slot on which the soup will be searched frequently. You can also use the AddIndex soup method to add an index to a soup that has already been created.

Stores

7-11

CHAPTER

Data Storage and Retrieval

Here is an example: theStore:=getStores()[0]; mySoup:=theStore:CreateSoup("myNewSoup", [{structure:'slot,path:'name,type:'string}])


Note

To remove a soup from a store, use the soup: RemoveFromStore method. u Erase store:Erase() Erases all contents of the specied store. Returns NIL if successful; else, throws an exception. GetAllInfo store:GetAllInfo() Returns the frame residing in the stores info slot. This special-purpose method is intended for use by backup/restore applications only; most applications need not use it. Unless an application stores data in it, this slot may not exist on every store. Applications can use the GetInfo method to get their own slot from the information frame. For more information, see the description of the GetInfo method, later in this section. GetInfo store:GetInfo(slotSymbol ) Returns the contents of the specied slot in the stores information frame. Unless an application stores data in it, the information frame may not exist on every store. This function returns NIL if the info slot (which stores the information frame) does not exist. Applications can create a slot in the

7-12

Stores

CHAPTER

Data Storage and Retrieval

information frame to store card data, such as the last time the application encountered a particular card. For more information, see the description of the store:SetInfo method. slotSymbol The slot to be returned. This value must be a symbol. Applications should create only a single slot in the store information frame and store minimal amounts of data in it.

The following example gets the contents of the myText slot from the information frame on the myStore store. myStore:GetInfo('myText); GetKind store:GetKind() Returns a string describing kind of RAM on which the specied store resides; this method always returns the string "Internal" for the internal store. Other strings returned include "Flash storage card" for a store on a ash card, "Storage card" for a store on an SRAM card, Application card for a store on a ROM card, and so on.
Note

Do not rely on the strings returned for stores other than the internal store; they may change on future Newton devices. u GetName store:GetName() Returns as a string the name of the store referenced by store. For example, getStores()[0]:GetName(); returns the string "Internal".

Stores

7-13

CHAPTER

Data Storage and Retrieval

GetPackages GetPackages() Returns an array of packages currently installed in the Newton system. Each array element is a frame containing the following slots: id size title An integer that is the package id. An integer that is the size of the package in bytes A string that is the name of the package.

A package is a bundle of resources that has been installed in the system. For example, a package can contain an application, fonts, sounds, images, and any other data needed by an application.
IMPORTANT

Because the package installation process is not re-entrant, you cannot call the GetPackages function from your applications InstallScript method or RemoveScript method. (These methods are invoked by the system in the midst of installing or removing a package.) s GetSignature store:GetSignature() Returns an integer that is the signature for the store. This is a random integer assigned when the store was created, unless a specic signature was set using the method store:SetSignature. GetSoup store:GetSoup(soupNameString) Returns a reference to the soup object specied by soupNameString in the store specied by store. If the soup doesn't exist, NIL is returned. Here is an example: theStore:=getStores()[0]; currentSoup:=theStore:GetSoup(ROM_CalendarSoupName);

7-14

Stores

CHAPTER

Data Storage and Retrieval

Note the use of the ROM_CalendarSoupName constant for the name of the built-in Calendar soup. For more information, see the section Accessing Soup Data, later in this chapter.
Note

Applications should use union-soups for most purposes. You cannot use the GetSoup function to retrieve a union soup; instead, use the GetUnionSoup function. u GetSoupNames store:GetSoupNames() Returns an array of strings containing the names of the soups in the store specied by store. For example, theStore:=getStores()[0]; theStore:getSoupNames(); returns the names of the soups on the internal store. GetStores GetStores() Returns an array containing references to all existing stores. Do not modify this array. The elements of this array are store objects to which you can send the messages described in the rest of this section. The element occupying the rst position in the array returned by this function (GetStores()[0]) is always the internal store; however, the representation of other stores in this array cannot be relied upon, as it may vary in future Newton devices. The following example shows how you can use the GetStores function to pass the internal store to the GetSoupNames function, which then returns a list of all the soup names in the internal store. GetStores()[0]:GetSoupNames();

Stores

7-15

CHAPTER

Data Storage and Retrieval

IMPORTANT

Dont call the GetStores method from your applications RemoveScript method. At that point, the store is already unavailable to your application, but the global variable it uses is not yet updated; hence, GetStores() may return inaccurate information when called from a RemoveScript method. s HasSoup store:HasSoup(soupName) Returns True if the store specied by store contains the soup having the name specied by soupName; otherwise, returns NIL. soupName The soup for which this method is to return the name string. This argument can be a string, such as "Names" or a constant, such as ROM_CardFileSoupName.

For example: theStore:=getStores()[0]; theStore:HasSoup(ROM_CardFileSoupName); IsReadOnly store:IsReadOnly() Returns True if the store is read-only (it could be a card that is writeprotected), or NIL if the store can be written. RemovePackage RemovePackage(packageFrame) Removes the specied package. packageFrame The package to be removed. It is one of the frames in the array returned by the GetPackages function.

IMPORTANT

You cannot call this function from your applications InstallScript method or RemoveScript method. 7-16

Stores

CHAPTER

Data Storage and Retrieval

RestorePackage store:RestorePackage(packageObject) Installs the specied package on the specied store. packageObject
IMPORTANT

The binary package object to be restored.

You cannot call this function from your applications InstallScript method or RemoveScript method. SetAllInfo store:SetAllInfo(frame)

Writes the specied frame in the stores info slot. This special-purpose method is intended for use by backup/restore applications only; most applications need not use it. Instead, applications should use the store:SetInfo method to store data in a single slot in the information frame. For more information, see the description of the SetInfo method, later in this section. frame SetInfo store:SetInfo(slotSymbol ,value ) Sets the value of the specied slot in the stores information frame. If the specied slot does not exist, this function creates it and sets it to the specied value. Applications can create a slot in the information frame to store card data, such as the last time the application encountered this card. Because the store information frame is shared by all applications, it is strongly recommended that your application follow the same guidelines for creating its slot in the store information frame as for creating a slot in another applications soup. For more information, see the sections Making Changes to Other Applications Soups and Making Information Available to All Entries in a Soup, elsewhere in this chapter. The frame to be written in the stores info slot.

Stores

7-17

CHAPTER

Data Storage and Retrieval

Returns NIL if the value was set successfully; else, throws an exception. slotSymbol The slot to be set (or created if necessary.) This value must be a symbol. Applications should create only a single slot in the store information frame and store minimal amounts of data in it. To help avoid slot name collisions with other applications storing data in the store information frame, the name of this slot needs to be a concatenation of your application symbol and developer signature. The value to be stored in the specied slot.

value

The following example creates or sets the slot |mySlot:myApp:PIEDTS| in the myStore store. myStore:SetInfo('|mySlot:myApp:PIEDTS|, {money: NIL,chicks:"free"}); SetName store:SetName(storeNameString) Sets the name of the specied store to the value of storeNameString. and returns the new name of the store. This special-purpose method is intended for use only by backup/restore applications.
IMPORTANT

Its generally unwise to change the name of a store; you have no way of telling whether other applications are using its current name to refer to it. s The following code example sets the name of the internal store to "dontTryThisAtHome". getStores()[0]:SetName("dontTryThisAtHome");

7-18

Stores

CHAPTER

Data Storage and Retrieval

SetSignature store:SetSignature(signature) Sets the store signature to the specied integer value and returns the signature. signature
IMPORTANT

The integer value to assign as the stores signature

Do not call this function unless you intend to completely replace all data on the store. This special-purpose method is for use only by backup/restore applications. s SetupCardSoups SetupCardSoups() Ensures that all single soups registered in the global array SoupNotify exist on the external store, creating them if necessary. This function is called by the system whenever a PCMCIA card is inserted. For more information on the function RegisterCardSoup, which performs a similar task, but does so using union soups, see the section Creating Your Applications Soups, later in this chapter. TotalSize store:TotalSize() Returns the total size in bytes of the physical medium on which the specied store resides. For example, the following line of code returns the total size of internal RAM. getStores()[0]:TotalSize();

Stores

7-19

CHAPTER

Data Storage and Retrieval

UsedSize store:UsedSize() Returns the number of bytes used in the store, including all overhead. Note that the gure reported for the used size may be larger than the amount actually used if store garbage collection hasnt happened for a while (leaving some unused memory temporarily marked as used). The following code example returns the number of bytes used in the main store. getStores()[0]:UsedSize();

Soups
Soups are opaque objects that serve as dynamic repositories for data. Multiple data types can reside in a single soup. Unless removed intentionally, soups remain resident on the store even if the application that owns them is removed. This section offers advice on structuring and using soups efciently, and describes the functions and methods used to manipulate soups. This section describes functions and methods for
n n n n

creating soups and union soups reading soup data from the store writing soup data to the store accessing information about the soup itself and the store on which it resides

The functions and methods described here allow you to get information about the currently available soups and union soups; get and set the information frame that describes the soup and the store on which it resides; obtain lists of soups present on the store; create soups and union soups; and write soups and packages to the store.

7-20

Soups

CHAPTER

Data Storage and Retrieval

Note

Individual entries in soups and union soups are manipulated with queries, cursors and entry functions; the remaining sections in this chapter explore these topics in detail. u

Naming Soups
When creating soups, you need to follow certain naming conventions in order to avoid name collisions with other applications soups as well as to make your own soups more easily identiable. If your application creates only one soup, you can use your package name for the soup name. Your package name is created by using a colon (:) to concatenate your packages Extras drawer name with your unique developer signature. For example, if your developer signature is myCompany and you are creating a package that appears in the Extras drawer with the name foo, concatenating these two values produces the foo:myCompany package name. If your application creates multiple soups, use your package name as a sufx to a descriptive soup name. For example, soup1:foo:myCompany and soup2:foo:myCompany would be acceptable soup names unlikely to collide with those used by other applications.

Creating Soups and Union Soups


A soup object is created on a store by the method store:CreateSoup or the global function CreateCardSoups, as explained in the Store Functions section, earlier in this chapter. Soup objects can be retrieved one at a time by the store:GetSoup method. However, an applications data is often not stored in a single soup. For example, when a PCMCIA card is installed, data may be spread out amongst the internal and card soups. The object system provides a way to address multiple soups as a single virtual soup called a union soup. A union soup represents multiple soups having the same name that reside on different stores. Figure 7-1 depicts the concept of a union soup graphically. 7-21

Soups

CHAPTER

Data Storage and Retrieval

Figure 7-1 Internal (NewtonRAM) store

Stores, soups and union soups soup entries

Soups on internal store

Entries in union soup

Soups on external store

External (PCMCIA) store

Union Soup soup entries

In general, youll want to use union soups for most purposes, and certainly for most data that the user creates with your application. Applications must allow the user to choose whether new data is to be stored on the internal or external store; using union soups makes this easy to do.

Accessing Soup Data


The recommended way to access any soup is to call the global function GetUnionSoup(soupName), which returns a union soup created from all available soups having the specied name. The GetUnionSoup function is described in detail later in this section.

7-22

Soups

CHAPTER

Data Storage and Retrieval

Getting System Soups


The Newton object system supplies a set of constants you can use to access the soups used by the built-in applications. Always use these constants, rather than the names of the soups, to access the built-in soups; they will help ensure your applications compatibility with internationalized Newton devices and future Newton devices. Table 7-1 lists these constants and their respective soups.

Table 7-1 Constant

Constants representing built-in soups English name

ROM_CalendarSoupName ROM_CardFileSoupName ROM_InBoxSoupName ROM_OutBoxSoupName ROM_MetaDataSoupName ROM_PaperRollSoupName ROM_SystemSoupName ROM_ToDoSoupName

Calendar Names Inbox Outbox Directory Notes System To do

Adding Entries to Soups


Due to the use of automatic data compression (and other factors), its not possible to tell how large the resulting entry will be before you add a frame to a soup. Thus, you cant tell in advance if an entry will t. Therefore, you must add the entry and then catch the exStoreError exception to handle store full errors. (Error code kSError_StoreFull.) In general, entries need to be self-contained, independent pieces of data that do not contain pointers to other data structures. Frames returned by functions such as the GetStores() function should generally not be stored as soup data; they may contain _parent references that are followed when

Soups

7-23

CHAPTER

Data Storage and Retrieval

creating the soup entry, making it quite large. The discussion of the soup:Add function, later in this section, explains how pointer data is stored in entry frames. Later in this chapter, the section Entries and RAM discusses in detail the creation of soup entries. To add entries to an individual soup, use the soup:Add method, described later in this section. To add entries to a union soup, use the global function AddToDefaultStore. This function stores data in the appropriate constituent soups of a union soup while respecting the users preferences for storing new data on the internal or external store. Both of these functions destructively modify the frame presented as their argument, adding a _uniqueID slot to it that identifies this frame as a soup entry. The _uniqueID slot stores an integer value unique to its soup entry; this value is used by the system to keep track of the soup entry, and can be used by other entries to nd this entry. These identiers are only unique within a single soup (they are not unique within union soups). A given uniqueID value is recycled after the creation of 230 entries.

Making Information Available to All Entries in a Soup


Each soup has an information frame associated with it. You can use this frame to make information available to every entry in the soup. For example, if your application records business trip expenses and you create a separate soup for each business trip, you can store the name of the business trip in the soup information frame. Each entry in the soup associated with that trip can use the name information without having to store its own copy of it. For more information on using the information frame, see the description of the soup methods soup:GetInfo and soup:SetInfo in the section Soup Functions, later in this chapter.

Creating Your Applications Soups


You need to use the global function RegisterCardSoup to create your applications union soups as necessary when the application opens; this function is invoked from your applications viewSetupFormScript method.

7-24

Soups

CHAPTER

Data Storage and Retrieval

The RegisterCardSoup function creates the specied union soup on the internal store and any currently-available external stores and returns the union soup. The constituent soups of the union are only created as necessary; that is, if an appropriate soup already exists on one of the stores, it is used as one of the constituents of the union soup. This function also registers the union soup with the system to ensure that its constituent soups are created on any stores that subsequently become available. A corollary method, UnRegisterCardSoup, unregisters the soup with the system; the system no longer automatically creates this union soups constituent soups on cards that are presented after the UnRegisterCardSoup method is invoked. Typically this method is invoked from the viewQuitScript method of your applications base view. Constants Used by RegisterCardSoup and UnRegisterCardSoup The RegisterCardSoup and UnRegisterCardSoup methods make use of the standard PIE DTS constants for the applications appSymbol, package name, appObject, soup name and soup indexes. You are probably familiar with the most of these constants already. For example, the following code denes the constants used by an application that appears in the Extras drawer under the Llama name. The Llama package is created by someone having the developer signature PIEDTS. //constants defined in "Project Data" constant kAppSymbol := '|llama:PIEDTS|; constant kPackageName := "llama:PIEDTS"; constant kAppObject := '["thing","things"]; constant kSoupName := kPackageName; constant kSoupIndexes := '[{structure: slot,path: name.first, type: string}]; You may not be familiar with the appObject array, though. This array contains two strings specifying the singular and plural forms of individual data items manipulated by the application. These strings are used by the system-supplied ling service to display progress to the user. For example, 7-25

Soups

CHAPTER

Data Storage and Retrieval

an individual data item manipulated by the Llama package is called a thing and the plural reference to said items would be things, as used in the sentence Filing 2 things in Business Notes. (The appObject array is fully explained in the Filing section of Chapter 12, Additional System Services.) The kSoupIndexes constant denes an array of indexes associated with the soup. For the purposes of this discussion, its sufcient for you to know that indexes are used to nd and sort soup data. Indexes are explained more fully in the descriptions of the methods store:AddIndex and soup:AddIndex, as well as in subsequent sections dealing with queries and cursors. Using the RegisterCardSoup Method Note that your application need only ensure the existence of its soups on all available stores while it is actually open. If a new card is introduced while your application is closed, the RegisterCardSoup method creates the necessary soups automatically the next time your application opens. Thus, you can use the RegisterCardSoup method by placing code like the following example in the viewSetupFormScript method of your applications base view. // place in base views viewSetUpFormScript :RegisterCardSoup(kSoupName,kSoupIndexes, kAppSymbol,kAppObject); The UnRegisterCardSoup Method When your application closes, it needs to invoke the UnRegisterCardSoup method, which unregisters the specied soup with the system. The system no longer automatically creates the union soups constituent soups on cards that are presented after the UnRegisterCardSoup method is invoked. You can invoke the UnRegisterCardSoup method from the viewQuitScript method of your applications base view, as shown in the following code example. //place in base views viewQuitScript :UnRegisterCardSoup(kSoupName);

7-26

Soups

CHAPTER

Data Storage and Retrieval

Sharing Soups With Other Applications


Newton applications are encouraged to reuse existing system-supplied soups for their own needs and to share their own soups with other applications. Refer to Chapter 8, Accessing System Data, to see descriptions of the soups used by the applications built into the MessagePad ROM. You can also use these descriptions as a model for documenting the structure of your applications shared soups. When your application changes an entry in a shared soup, it needs to send a message to the system telling it to notify other applications using that soup that something has changed; those applications can then take action appropriate for dealing with the change. The system uses the global array SoupNotify to send messages to the appropriate applications when changes to soup data occur.

Registering Your Application for Notication


To register your application for notication when a particular soup changes, you need to add the appropriate elements to the global SoupNotify array. The elements of the SoupNotify array are used in pairs. The rst element in the pair is a string specifying the name of the soup. The second element is the application symbol of the application to be notied when that soup changes. Applications typically register with the SoupNotify array from within the viewSetupDoneScript method of their base view. Your application needs to place a pair of elements in the SoupNotify array for each soup from which it is to receive notication. The following code example shows how to register your application for notication of changes in the system soup. This code sample assumes that a constant, kAppSymbol, has been dened for the applications application symbol. //register w/ SoupNotify in viewSetupDoneScript AddArraySlot(SoupNotify,ROM_SystemSoupName); AddArraySlot(SoupNotify,kAppSymbol);

Soups

7-27

CHAPTER

Data Storage and Retrieval

Unregistering Your Application for Notication


When your application closes, it needs to remove its entries from the SoupNotify array using code like that shown in the example immediately following. Normally, you can place this code in the viewQuitScript method of your applications base view. //unregister with SoupNotify in viewQuitScript local soupNotifyPos := ArrayPos(soupNotify, kAppSymbol,0,nil); ArrayRemoveCount(soupNotify,soupNotifyPos-1,2); Note that the code for unregistering uses the application symbol, rather than the soup name, to nd the array elements to remove. Its essential to take this approach, because other applications may have requested notication for the same soupyou wouldnt want to remove their entries from the SoupNotify array, just your own. This code can easily be generalized to unregister your application from multiple soups, as shown in the following code example. //unreg all SoupNotify entries in viewQuitScript local soupNotifyPos; while soupNotifyPos := ArrayPos(soupNotify,kAppSymbol,0,nil) do ArrayRemoveCount(soupNotify,soupNotifyPos-1,2);

Receiving Notications
Once your application is registered in the SoupNotify array, it receives soupChanged messages when soups change. You need to define in your applications base view a SoupChanged method that accepts a single argument, a string specifying the name of the soup that changed. The implementation of your applications SoupChanged method must take any action that is appropriate to respond to the change. Most applications have no need to respond to soup changes unless they are open, which is why

7-28

Soups

CHAPTER

Data Storage and Retrieval

it is recommended that you register your application when it opens and unregister when it closes.
IMPORTANT

The system-supplied Preferences application does not notify applications of changes to its soups. s

Sending Notications
When your application alters a shared soup, it needs to call the global function BroadcastSoupChange. This function sends a soupChanged message to all of the applications registered with that soup in the SoupNotify array. The BroadcastSoupChange function takes a single argument, a string specifying the name of the soup that changed.

Making Changes to Other Applications Soups


In addition to using the BroadcastSoupChange function, there is an additional convention your application needs to follow when it makes changes to soups owned by other applications. If your application needs to make changes to an entry in another applications soup, it should create a single slot in the entry, and conne its changes to data in that slot. The same cautions apply to naming slots in other applications soups as apply to naming soups themselves. When you create a slot in another applications soup entry, try to use your application name and developer signature in the slot name to help prevent slot name collisions. This approach provides the following benets:
n

It prevents your application from inadvertently damaging another applications data. It helps your application avoid name collisions with other applications slots. It keeps soups from being cluttered with an excessive number of entries. It provides for easy removal of your applications data.

n n

Soups

7-29

CHAPTER

Data Storage and Retrieval

Cleaning Up Leftover Soup


When your application closes, it needs to clean up after itself as much as possible, removing any references it has made to soups, entries or cursors. This usually means setting to nil any slots that store references to these objects.
IMPORTANT

If you dont remove references to unused soups, entries or cursors, the references, entries and cursors will not be garbage collected, reducing the amount of RAM available to the system and other applications. s The problem of removing soups entirely, however, is a little thornier. Soups are not garbage-collected; even when empty, they can only be removed explicitly. Because soups are intentionally invisible to the user, there is no user interface for removing them. Thus, its up to the application to delete its soups. Performing the task itself is not so much the problem as is determining when to do it. You certainly dont want to delete soups in the applications viewQuitScript method the user data needs to be preserved until the next time the application is run, unless the application is being removed permanently. Unfortunately, there is no way at the moment to distinguish between removing your software permanently using the Remove Software dialog in the Memory preference and removing it temporarily by ejecting the PCMCIA card. You may also be wondering about the soups created on every card inserted while your application is open. Fortunately, these soups are empty unless the card is designated as the default store when the user creates data with your application. Hopefully, Newton users will learn to organize their data on cards, just as personal computer users have learned to organize their data on oppy disks. Thus, at the moment there is no easy answer to the problem of soup leftovers. However, PIE DTS is considering possible solutions to the problem, including the following:
n

A reliable method to distinguish between ejecting the PCMCIA card and using the Remove Software dialog may be documented. When your

7-30

Soups

CHAPTER

Data Storage and Retrieval

application detects the Remove Software case it can display a dialog box asking whether the user really wants to remove all traces of the application from the system. This is not as straightforward as it may seem: what if the user is simply deleting an extra copy of your application from a card? At the very least, it seems clear that this sort of action should not be taken without prompting the user.
n

Users may explicitly do the cleanup. Some applications will provide this option to the user via a button in their Preferences panel or as a separate utility application. Guidelines for naming soups and preferences data may be established. If applications follow these guidelines consistently, it should be possible to write a de-installer application for doing this kind of cleanup.

For now, youll need to wait for PIE DTS to provide further details regarding a solution to this problem.

But I Really Want to Remove My Soups


If the case for removing your applications soup is extremely clear cutfor example your application creates and uses a specialized soup that no other application can use, and you want to remove this soup every time the application is removed for any reasonyou might take the approach shown in the following code example. This code example shows one way an applications removeScript method can remove the applications soups. foreach store in GetStores() do begin local soup := store:GetSoup("mySoupName"); if soup then soup:RemoveFromStore(); // might also want to handle // case when store:IsReadOnly() = true end;

Soups

7-31

CHAPTER

Data Storage and Retrieval

Unexpected Index Errors When Removing a Soup You may receive an error number -48022 "Internal errorsomething unexpected happened" when trying to remove a soup. This error is returned when any of the following things happen:
n n n

No space for more nodes while indexing A slot is internally out of range (problem nding it using offset) Unable to create index resources when creating a soup, adding or deleting indexes.

If you receive this error, there is a strong possibility that the soups index denitions are or were corrupted. You might also check to see whether you are attempting to delete an index that is no longer present.

Determining a Soups Size


Due to the use of automatic data compression (and other factors), its difcult to predict the soups nal size. One way you can make an educated guess is to generate a test soup that stores a set of representative entries and measure its size. The following code example shows how to create a simple test soup from the Inspector. call func() begin local s, i, j; for i := 1 to Random(10, 20) do begin s := GetStores()[0]:CreateSoup("Soup"&i&":PIEDTS",{}); for j := 1 to Random(100, 1000) do s:AddEntry({ string: GetRandomWord(5,10) && GetRandomWord(6,12), real: Random(1000) + 1/Random(1000), integer: Random(10000)}); end; end with ();

7-32

Soups

CHAPTER

Data Storage and Retrieval

If you need to create richer soups that store additional data types, see the PIE DTS code sample Sync Another One for additional examples. The Sync Another One sample shows how to create a random eld of nearly every data type used in the Newton environment. To create complex sets of soup data, you might nd useful the PIE DTS Slurp code sample, which uses the Newton serial port to import soups dened as text les on the Macintosh. Note that Slurp requires the use of a terminal emulation program on the Macintosh.

Storing User Preference Data


Most of the time youll want to store data in union soups, but one task for which union soups are not suitable is the storage of user preferences for your application. There are several good reasons to always store the applications user preferences data on the internal store:
n

If your application is on a card and is moved from one Newton device to another, it should acts the way the users of the respective Newton devices think it should. The obvious way to keep preference data with a particular device is to store it in internal RAM. It rarely makes sense to spread out preferences data across several PCMCIA cards. Its difcult to guarantee that your application would always have access to even one particular card. If your application is in internal memory and it simply adds preference data to the default store, the preference data could wind up on the card and become unavailable to the application when the card is ejected.

Hence, the built-in soup named System on the internal store would seem to be the right place to always store your applications preferences data. Because all applications have to share the System soup, you need to be considerate and avoid storing large amounts of data there. As with any system-supplied soup, you need to access the System soup using the appropriate constant (in this case, ROM_SystemSoupName). The constants dened for the names of the built-in soups are listed in the section Getting System Soups, later in this chapter. 7-33

Soups

CHAPTER

Data Storage and Retrieval

See Chapter 8, Accessing System Data, for an example of how to access preferences data in the System soup.

Soup Functions
The following functions and methods allow you to get and set information describing the soup and its contents, change individual soup entries, make copies of soups and write soups to the store.

About the Soup Metasymbol.


Many of the methods described in this section take the form of messages that are sent to an object. The notation soup is a replaceable metasymbol representing the soup object to which the message is sent in order to invoke its method. For example, the notation soup:GetIndexes() means send the GetIndexes message to the soup object represented by the soup metasymbol. In your application, the code to invoke this method would look similar to the following code example. mySoup:GetIndexes(); Add soup:Add(frame) frame The frame to be made into an entry in the specied soup.

Adds the specied frame to the soup or union soup object soup. If you send this message to a union soup (see GetUnionSoup below), the frame is added to one of the soups in the union, though you have no control over which one. If soup is a union soup and you want to ensure that the frame is added to the default store, use the AddToDefaultStore method; for more information, see the description of this method in later in this section. The frame presented to Add is transformed into a soup entry, which is returned. The entry consists of the original frame plus the transitive closure of that frame's pointers (that is, everything that frame points to, everything those data structures point to, and so on). Thus, putting a _parent slot in a

7-34

Soups

CHAPTER

Data Storage and Retrieval

frame presented as the argument to Add is a bad idea! It causes the whole _parent view (and its parent, and so on) to be stored in the resulting entry, making it extremely large. Instead, you might store a key symbol in the data and look up the parent view in a frame of templates at runtime. On the other hand, _proto slots are not followed, so they may be safely included in frames presented to this method.
IMPORTANT

The Add method destructively modies the frame that is presented to it, creating special slots in the entry to identify it as belonging to a soup. An example of one such slot is the uniqueID slot. Thus, if its important that the original frame remain unmodied, you may want to clone it rst and pass the clone as the argument to this method. s Because cursors are dynamic, subsequent traverses of the soup return the new entry frame if it meets the criteria of the query that generated the cursor. The following code example shows the use of the Add method to add the frame aFrame to the soup cribSoup. aFrame:={bDay:"Moms birthday"}; theStore:=getStores()[0]; cribSoup:=theStore:GetSoup("CribNotes"); cribSoup:Add(aFrame); AddIndex soup:AddIndex(indexSpec) Adds an index to the soup or union soup object soup. An index speeds up searches that are done on the index key slot (specied in path in indexSpec, see below). Additionally, the set of entries referenced by the cursor returned from a query are sorted in index order.

Soups

7-35

CHAPTER

Data Storage and Retrieval

indexSpec

A frame specifying the characteristics of the index. The indexSpec frame has the following slots: structure Species the kind of index. Currently, only the symbol 'slot can be specied, indicating that the index key is the value of a slot in each soup entry.
IMPORTANT

Currently, index string values are undened beyond 39 characters. For example, if you have a string index on the 'name slot, the slot name:39Chars1 may not sort before the slot name:39Chars2.This limit may increase in the future; however, it will not decrease. s path The path to the slot which is the index key. This is a path expression, which means it is either a symbol (for a simple path) or an array of class PathExpr in which individual elements are symbols for example, [PathExpr:'x.y.z] would be one example of such an array. For a complete explanation of path expressions, see The NewtonScript Programming Language. The type of data stored in the index key slot. This can be an integer (specify 'int), a string (specify 'string), a character (specify 'char), a real number (specify 'real), or a symbol (specify 'symbol).

type

If the argument to the soup parameter is a union soup (see the description of the GetUnionSoup function for more info) the index is added to all soups in the union soup. Here is an example: theStore:=getStores()[0] cardSoup:=theStore:GetSoup("CardFile") cardSoup:AddIndex({structure:'slot, path:'Postal_code,type:'string})

7-36

Soups

CHAPTER

Data Storage and Retrieval

AddToDefaultStore unionSoup:AddToDefaultStore(frame) Adds the specied frame to the specied union soup, returning TRUE if the frame is added successfully and throwing an exception if the frame cannot be added. The frame is added to the soup on the default store (a union soup contains multiple soups on separate stores). The default store is set by the user in Preferences. The user can choose either the internal store or the store on a storage card as the default store. unionSoup frame The union soup object to which the specied frame is to be added. The frame to be made into an entry in the specied union soup.

The AddToDefaultStore method calls store:Add(frame) for the appropriate store. This operation destructively modies the frame passed to the AddToDefaultStore method. For more information see the description of the Add method, earlier in this section.
IMPORTANT

The AddToDefaultStore method destructively modies the frame that is presented to it, creating special slots in the entry to identify it as belonging to a soup. One example of such a slot is the uniqueID slot. Thus, if its important that the original frame remain unmodied, you may want to clone it rst and pass the copy as the argument to this method. s AddWithUniqueId soup:AddWithUniqueId(frame) Replaces in the specied soup the frame having a uniqueID slot matching that in the frame specied by the argument to this method. This special-purpose function is intended only for restoration of soup data; most applications should not use it.

Soups

7-37

CHAPTER

Data Storage and Retrieval

frame

The frame to be added to the specied soup. This frame must already contain the slots necessary to mark it as a soup entry rather than a standard frame. Specically, it must have a uniqueID slot having a value matching the uniqueID value of a currently-existing entry in the specied soup.

Normally, applications use the soup:Add method to add a frame to a specied soup. The soup:Add method generates a new uniqueID value for the frame it adds to the soup; the AddWithUniqueID method does not generate a new uniqueID value, but attempts to replace the frame having the same uniqueID value as the frame to be added, thereby maintaining the uniqueID value between the original entry and the frame that replaces it.
IMPORTANT

Use with extreme caution to avoid soup corruption. BroadcastSoupChange BroadcastSoupChange(soupNameString) soupNameString

A string that is the name of the soup that changed

Noties all applications that use the specied soup that it has changed by sending them a SoupChanged message. In order for your application to be notied, it must be registered in the global soupNotify array (see the Globals section in the chapter Accessing System Data). You should call this function if you make a change to a soup used or owned by another application. This function always returns NIL. CopyEntries sourceSoup:CopyEntries(destSoup ) Copies the entries in the source soup to the destination soup, preserving the values of the _uniqueID slots in the copied entries. sourceSoup The soup that is to be copied.

7-38

Soups

CHAPTER

Data Storage and Retrieval

destSoup

The soup in which the copied entries are written. This soup must be empty; this method does not perform error checking for duplicate _uniqueID values in the soup specied by destSoup . This soup must not be a union soup, else a kFramesErrCantCopyToUnionSoup exception is thrown.

Flush soup:Flush() This special-purpose method is intended for use by backup/restore applications; it writes all changed entries back to the soup. Do not use this method unless your application is the only one using the soup that is ushed, else you may interfere with another applications entries. Instead, use the EntryChanged function to mark individual entries to be written back to the soup. soup GetAllInfo soup:GetAllInfo() Returns the frame residing in the soups info slot. This special-purpose method is intended for use by backup/restore applications only; most applications need not use it. Unless an application stores data in it, this slot may not exist in every soup. Applications can use the GetInfo method to get their own slot from the soup information frame. For more information, see the description of the GetInfo method, later in this section. Note that soups created by the store:CreateSoup method do not contain an info slot; on the other hand, soups created by the global function RegisterCardSoup have a default info slot that contains the slots applications and itemNames. For more information, see the descriptions of the RegisterCardSoup function and the CreateSoup method in this chapter. The soup or union soup to be written to the store.

Soups

7-39

CHAPTER

Data Storage and Retrieval

GetIndexes soup:GetIndexes() Returns an array of index specication frames (see soup:AddIndex) corresponding to the indexes that exist in the soup. This function does not return the default index. (Every soup has a default index that uses the _uniqueId slot as the path.) GetInfo soup:GetInfo(slotSymbol ) Returns the contents of the specied slot in the soups information frame; this function returns NIL if the slot does not exist. soup The soup having the information frame to be returned. This soup must be a single soup, not a union soup. This function is undened for union soups. The slot to be returned. This value must be a symbol.

slotSymbol

Note that soups created by the store:CreateSoup method do not contain an info slot; on the other hand, soups created by the global function RegisterCardSoup have a default info slot that contains the slots applications and itemNames. For more information, see the descriptions of the RegisterCardSoup function and the CreateSoup method in this chapter. The following example gets the contents of the myText slot from the mySoup soup. mySoup:GetInfo('myText); GetName soup:GetName() Returns a string that is the name of the soup or union soup object soup.

7-40

Soups

CHAPTER

Data Storage and Retrieval

For example, theStore:=getStores()[0]; currentSoup:=theStore:GetSoup(ROM_CalendarSoupName); currentSoup:GetName(); returns the string "Calendar". GetNextUid soup:GetNextUid() Returns the value to be stored in the _uniqueID slot of the next entry added to the soup. This special-purpose method is intended for use by backup/restore applications. Because the soup:Add method and the AddToDefaultStore function automatically assign _uniqueID values, it is not necessary for most applications to call this method. GetSignature soup:GetSignature() Returns an integer that is the signature for the soup. Using this signature, you can tell if a soup has been deleted and replaced by another with the same name. The signature is a random integer assigned when the soup was created, unless a specic signature was set using the method soup:SetSignature. GetStore soup:GetStore() Returns a reference to the store on which the soup object soup resides. For example: theStore:=getStores()[0]; currentSoup:=theStore:GetSoup(ROM_CalendarSoupName); store:=currentSoup:GetStore();

Soups

7-41

CHAPTER

Data Storage and Retrieval

GetUnionSoup GetUnionSoup(soupNameString) Returns a reference to the union soup object named by the value of the soupNameString parameter. A union soup merges all soups with the specied name in all stores. Here is an example: allnotes:=GetUnionSoup("Notes") You can call the following soup methods on a union soup: Add(), AddToDefaultStore(), AddIndex(), RemoveIndex(), GetName() and Flush(). IndexSizes soup:IndexSizes() Returns an array of integers representing the size in bytes of each of the soups indexes. The rst element in the array is the size of the default index. (Every soup has a default index that uses the _uniqueId slot as the path.) IsSoupEntry IsSoupEntry(object) Returns TRUE if the data object passed to this function is a soup entry. Otherwise, returns NIL. RegisterCardSoup :RegisterCardSoup(soupName,indexArray,appSymbol ,appObject) Creates the specied union soup on the internal store and any currentlyavailable external stores and returns the union soup. The constituent soups of the union are only created as necessary; that is, if a soup having the specied name already exists on a particular store, that soup is used as one of the constituents of the union soup.The union soup created by this method is registered with the system to ensure that its constituent soups are created on any stores that subsequently become available. All constituent soups are

7-42

Soups

CHAPTER

Data Storage and Retrieval

created with the specied indexes. This method also stores the specied application symbol and appObject frame in the soups info frame. This information describes the owner of the soup and the items stored in it to applications and system services that use the soup. soupName indexArray A case-insensitive string up to 39 characters long that species the name with which the soup is to be created. An array of frames specifying the characteristics of indexes that you want the soup to possess. Each indexArray frame has the following slots: structure Species the kind of index. Currently, only the symbol 'slot can be specied, indicating that the index key is the value of a slot in each soup entry. path The path to the slot which is the index key. This is a path expression, which means it is either a symbol (for a simple path) or an array of class PathExpr in which individual elements are symbols for example, [PathExpr:'x.y.z] would be one example of such an array. For a complete explanation of path expressions, see The NewtonScript Programming Language. type The data type of the index key slot. This can be an integer (specify 'int), a string (specify 'string), a character (specify 'char), a real number (specify 'real), or a symbol (specify 'symbol). appObject An array of two strings. The rst element of the array species the singular case of your applications data items and the second element species the plural case, as shown in the following example code fragment. ["note", "Notes"]

Soups

7-43

CHAPTER

Data Storage and Retrieval

appSymbol

The application symbol of the application that owns this soup. For more information about application symbols, see the section Creating an Application Identier Symbolin Chapter 12, Additional System Services.

Note

This function may not be dened in ROM it may be supplied by NTK. u RemoveAllEntries soup:RemoveAllEntries() Deletes all of the entries from the specied soup. The soup object to which this message is sent must be a single soup; this method is not implemented for union soups. RemoveFromStore soup:RemoveFromStore() Removes the soup object soup from its store and deletes all of its entries. You cannot use this method on a union soup (see GetUnionSoup, described elsewhere in this section). Here is an example: theStore:=getStores()[0] currentSoup:=theStore:GetSoup(mySoup) currentSoup:RemoveFromStore() RemoveIndex soup:RemoveIndex(indexPath) Removes an index from the soup or union soup object soup. indexPath The index path to be removed. Specify the same index path symbol used to create the index.

7-44

Soups

CHAPTER

Data Storage and Retrieval

SetAllInfo soup:SetAllInfo(frame) Writes the specied frame in the soups info slot. This special-purpose method is intended for use by backup/restore applications only; most applications need not use it. Instead, applications should use the soup:SetInfo method to store data in a single slot in the soup information frame. For more information, see the description of the SetInfo method, later in this section. frame SetInfo soup:SetInfo(slotSymbol ,value) Sets the value of the specied slot in the soups info frame. If the slot does not exist, this function creates it and sets it to the specied value. Returns NIL if the value was set successfully, else throws an exception. Applications can use this method to store information associated with every entry in the soup. slotSymbol The name of the slot to be set. This value must be a symbol. Because the soup information frame is shared by all applications using the soup, it is strongly recommended that your application follow the same guidelines for creating its slot in the soup information frame as for creating a slot in another applications soup. For more information, see the sections Making Changes to Other Applications Soups and Making Information Available to All Entries in a Soup. value
Note

The frame to be written in the soups info slot.

The value to be stored in the specied slot.

To avoid dangling references that may bring up the Newton needs the card dialog, wrap the arguments to this function in calls to the EnsureInternal function. u

Soups

7-45

CHAPTER

Data Storage and Retrieval

The following example creates or sets the slot kind in the information frame of the mySoup soup. myInfo := {flavor:"chicken", noodles:TRUE} mySoup:SetInfo(EnsureInternal('kind), EnsureInternal(myInfo)); SetName soup:SetName(soupNameString) Sets the name of the soup to the string soupNameString and returns the new name of the soup. If you try to set the name to an invalid value (for example, one that is already in use) this method throws an exception. Generally, you should exercise extreme caution when changing the names of soups, even if they are your own; other applications may be using them.
IMPORTANT

Do not under any circumstances change the names of the built-in soups. s SetSignature soup:SetSignature(signature) Sets the soup signature to the specied integer value and returns the signature. UnRegisterCardSoup :UnRegisterCardSoup(soupName) Unregisters the specied soup with the system; the system no longer automatically creates the union soups constituent soups on cards that are presented after the UnRegisterCardSoup method is invoked. soupName A case-insensitive string up to 39 characters long that species the name of the soup

Note

This function may not be dened in ROM it may be supplied by NTK. u

7-46

Soups

CHAPTER

Data Storage and Retrieval

Queries and Cursors


Once you have used the soup and store methods described previously to obtain the soups with which your application works, most of the work you do with soup data is performed using the query and cursor methods described in this section.

Performing a Query
To retrieve entries from a soup, you perform a query on the soup using the global function Query. This function accepts as its arguments a soup reference and a query specication (also called a query spec). The query specication is a frame that species the kind of data on which the query searches (indexes, word beginnings or any text string); it can optionally specify additional qualications and tests. Some of these options are used to make the query speedier; for example, you can specify that only a particular slot be searched. Other options allow you to dene your own comparison functions for determining which entries are to be included in the cursors data set. These options are discussed in detail in the description of the Query function, later in this section.

The Cursor
The Query function returns a cursor, which is an object that points to the set of entries satisfying the query spec. As entries in the soup are added, deleted and changed, the set of entries to which the cursor points is updated dynamically. The entries in the cursor are sorted in index order. If no other index was specied when the soup was created, its entries are indexed by default on the uniqueID slot. Because the values in each soup entrys uniqueID slot are assigned in incremental order as the entries are created, the result is that the default index sorts entries in the order that they were created (although 7-47

Queries and Cursors

CHAPTER

Data Storage and Retrieval

this is not guaranteed; if you rely on uniqueID ordering, then you need to specify an index path of indexPath: 'uniqueID when creating the soup index.) The cursor serves as an iterator object that returns entries in response to the messages it receives. Initially, the cursor points to the rst soup entry in the data set that satises the query. It can be advanced to the next entry in the set or moved back to the previous entry by the Next and Prev methods, respectively. You can also use the GoTo and GoToKey methods to position the cursor directly rather than incrementally. Because pointers between soups are not supported, you must use multiple queries to obtain information from dissimilarly-named soups. For example, to obtain information on someone you have a meeting with, you need to query the Names soup with the name of the person (or other identifying information) and query the Dates soup for the time of the meeting.

Counting the Number of Entries in a Soup


Because the user can add or delete entries at any time, its difcult to determine with absolute certainty the number of entries in a soup. With that in mind, you can use the CountCursorEntries function shown in the following code example to return the number of entries in a soup at the time the function is executed. func CountCursorEntries (cursor) begin cursor := cursor:Clone(); cursor:Reset(); if cursor:Entry() = NIL then return 0; local count := 1; while cursor:Next() do count := count + 1; count end

7-48

Queries and Cursors

CHAPTER

Data Storage and Retrieval

While you might nd it faster to use the MapCursor function to count the entries, the approach taken by the CountCursorEntries function uses memory more efciently.

Query and Cursor Functions


This section describes the global function Query, which returns a cursor referencing a set of soup entries, the cursor method Clone, which duplicates a cursor, and various other methods that manipulate the cursor to obtain individual entries.

About the Cursor Metasymbol


Many of the methods described in this section take the form of messages that are sent to an object. The notation cursor is a replaceable metasymbol representing the cursor object to which the message is sent in order to invoke its method. For example, the notation cursor:Entry() means send the Entry message to the cursor object represented by the cursor metasymbol. In your application, the code to invoke this method would look similar to the following code example. cardCursor:Entry(); Clone cursor:Clone() This method clones (makes a copy of) cursor and returns the clone. You might clone a cursor to use for rummaging around in the soup without disturbing the original cursor. For example: theStore:=getStores()[0] cardSoup:=theStore:GetSoup("CardFile") cardCursor := query(cardSoup, {type:'index}) cursorCopy:=cardCursor:Clone()

Queries and Cursors

7-49

CHAPTER

Data Storage and Retrieval

Note

Do not use the global functions Clone or DeepClone to clone cursors. Instead, use the Clone method for cursors, as described here. u Entry cursor:Entry() Returns the current soup entry referenced by cursor. If the current entry is deleted from the soup, the entry reverts to a plain frame (rather than a soup entry), and the method cursor:Entry returns the symbol 'deleted. Make sure your code can handle gracefully a return value of 'deleted from the cursor:Entry method. If the cursor is advanced past the last entry or moved before the rst entry in the set, the current entry pointed to by the cursor has the value nil. Make sure your code can also handle gracefully a nil value returned from the cursor:Entry method. If the current entry is altered in a way that causes it to move to a different place within the set of entries returned from the query, the cursor does not move with it, but continues to point to the same place, relative to the rst entry, in the set of results. The following code example shows the typical use of this method. theStore:=getStores()[0]; cardSoup:=theStore:GetSoup("CardFile"); cardCursor := query(cardSoup, {type:'index}); cardCursor:Entry(); Goto cursor:GoTo(entry) If the specied entry is valid, this method moves the cursor to the specied entry and returns TRUE. If the specied entry is not valid the cursor does not move and this method throws an exception.

7-50

Queries and Cursors

CHAPTER

Data Storage and Retrieval

entry

The entry to which the cursor is moved. You cannot create an entry procedurally by creating a frame with the appropriate attributes. The only valid entries are those returned by the various cursor and entry methods.

Although you cannot create entries procedurally, you certainly can assign the return values of cursor functions to variables and pass those variables to the various cursor functions. For example, myEntry:= theCursor:Entry() theCursor:Reset(); theCursor:GoTo(myEntry); GotoKey cursor:GoToKey(key) Moves the cursor to the rst valid entry with the specied key, or to the next entry in key order if there is no entry with the specied key, and returns the entry. If no entries have the specied key, or the key is invalid, the cursor tests each entry until it runs out of entries, at which point this method returns NIL. This method works only with cursors generated by an index query. The soup against which the cursor was generated must be indexed on the slot containing the key value. The data type of the key value must be the type specied for the key in the index. key The slot value for which this method searches.

For example, consider the following example code, which is a simplication of the PIE DTS code sample Soup Tour. // create a soup thats indexed on the name slot thePizzas:= theStore:CreateSoup("pizzaSoup", [{structure: 'slot, path: 'name, type: 'string}]) // add some entries to the soup thePizzas:Add( {name: "Keith", toppings: ["cheese","pepperoni","sausage"]});

Queries and Cursors

7-51

CHAPTER

Data Storage and Retrieval

thePizzas:Add( {name: "Nige", toppings: [ "pepperoni","sausage","pineapple"]}); // now get a cursor to work with myCursor:= Query(thePizzas, {type: 'index, indexPath: 'name}); Following are some examples of how to use the GoTo method with the myCursor cursor. // go to the first entry that has a name slot myCursor:GotoKey('name); // see what weve got myCursor:Entry(); // a reset puts us back to where we started myCursor:Reset(); // return the first entry that has // the value "Nige" in the name slot myCursor:GotoKey("Nige"); myCursor:Entry(); // this wont work -- wrong data type for our index // Also, this value not stored in any of our slots anyway myCursor:GoToKey(2); For many more examples of the use of queries, cursors, and indexes, see the PIE DTS Soup Tour code sample.

7-52

Queries and Cursors

CHAPTER

Data Storage and Retrieval

MapCursor MapCursor(cursor, function) Applies the specied function to each of the cursors entries in turn and returns an array of the results. If function is nil, the returned array consists simply of the cursor entries themselves. function The function that is to be mapped to the cursors entries. This function you supply for this argument must accept one parameter, an entry. Note that if the function returns a NIL result for an entry, that entry is not added to the return array. NIL results are discarded. Move cursor:Move(n) Moves the cursor n entries forward from its current position and returns that entry. If n is negative, the cursor is moved backwards. If the cursor is advanced past the last entry or moved before the rst entry in the set of entries it references, the current entry pointed to by the cursor has the value NIL. For example, instead of coding cursor movement explicitly as in the example for i := 1 to n do cursor:Next(). you can obtain faster results by using the Move method, as in the following example. cardCursor:Move(n)

Queries and Cursors

7-53

CHAPTER

Data Storage and Retrieval

Next cursor:Next() Moves the cursor to the next entry in the set of entries referenced by the cursor and returns the entry. If the cursor is advanced past the last entry in the set of entries it references, the current entry pointed to by the cursor has the value NIL. You can use the Next method as in the following example. cardCursor:Next(); Prev cursor:Prev() Moves the cursor to the previous entry in the set of entries referenced by the cursor and returns the entry. If the cursor is moved before the rst entry in the set of entries it references, the current entry pointed to by the cursor has the value NIL. You can use the Prev method as in the following example. cardCursor:Prev(); Query Query (soupRef, querySpec ) Performs a query on the soup soupRef , according to the query specication frame querySpec , and returns a cursor to the rst entry in the set of results that satisfy the query. The slots in the querySpec frame are described below.
querySpec

type

Species the type of query to perform. You can specify one of these symbols: 'index To query by the value of an index. For more information, see the description of the method soup:AddIndex for a discussion of index specications.

7-54

Queries and Cursors

CHAPTER

Data Storage and Retrieval

indexPath

startKey

validTest

endTest

To query by word. This searches all strings in each soup entry for the word beginnings listed in the words array. The search is not case-sensitive. 'text To query by any string. This searches all strings in each soup entry for the string specied in the text slot. The search is not limited to word boundaries. This search is not sensitive to case or to diacritical marks within the string. This type of query is slower than a 'words query. Optional. It species the path to the slot on which the soup is to be indexed. The results are sorted according to the value of this index slot. Can be used by any of the query types. Optional. Used only for index queries; it species the starting point for the query. The rst entry returned will be the rst one whose index key slot has a value equal to or greater than the value of the startKey slot. Optional. Used only for index queries. It is a function that returns NIL if the entry is not to be returned by the cursor, and returns any non-zero value if the entry is to be returned by the cursor. If you use a validTest along with a startKey and an endTest, the validTest is called for all entries that are equal to or greater than the startKey and less than the endTest. The validTest is called before the endTest, so it may be called with an entry that is valid but fails the endTest. Optional. Used only for index queries. It is a function that returns TRUE if the cursor is to stop before returning the entry and returns NIL if the cursor is to return the entry. If this function returns TRUE for an entry, no subsequent entries are returned from this query. 'words

Queries and Cursors

7-55

CHAPTER

Data Storage and Retrieval

words

text

Optional. Used only for words queries; it species an array of strings that are matched with word beginnings in each entry. If you specify multiple array elements, each string must appear somewhere in the entry for it to be selected. This query will only nd the specied strings if they are word beginnings; it will not nd a string in the middle of a word in the entry. Because each element in the array is a string, each word in a word query can actually contain multiple words and punctuation. The query is not case-sensitive. Optional. Used only for text queries; it species a string for which to search.

Here is an example of an index query that returns all soup entries: theStore:=getStores()[0]; cardSoup:=theStore:GetSoup("CardFile"); cardCursor := query(cardSoup, {type:'index}); Here is an example of an index query that returns only entries whose name slot starts with Bob (StartsWith is a function that does this test): myCursor := query(cardSoup, {type:'index, validTest: func (entry) StartsWith(entry.name, "Bob")}); If the name slot in the previous example is indexed, the same query can be done faster like this: myCursor := query(cardSoup, {type:'index, indexPath: 'name, startKey: "Bob", endTest: func (entry) not StartsWith(entry.name, "Bob")});

7-56

Queries and Cursors

CHAPTER

Data Storage and Retrieval

Note

Traversing the soup creates a frame for each soup entry as it is encountered. They are cached, so you dont pay a penalty for visiting the same entry twice, but using indexes and start keys to limit your search can speed up your searches and reduce the RAM requirements necessary to complete the search. Using a validTest function doesnt reduce RAM requirements because the entry frame has to be created in order to pass it to the validTest function. u Here is an example of a words query that returns entries that contain words beginning with the string "Bob". myCursor := query(cardSoup, {type:'words, words: ["Bob"]}); This query will nd entries containing the words "Bob" and "Bobby", and so forth, but not words such as "JoeBob". Here is an example of a words query that returns entries that contain both words beginning with the string "Bob" and words beginning with the string "Sunnyside". myCursor:=Query(cardSoup,{type:'words, words:["Bob", "Sunnyside"]}); To reliably return a cursor to the rst entry in a soup, use this form: firstEntry := query(soup, {type:'index}); To get the last entry in a soup, use this trick (assuming a string index): cursor.GotoKey("\u7FFF"); // really big key while cursor.Next() do nil;// in case it's not big enough cursor.Prev(); This will leave you on the last entry , if any; you can omit the Prev() method to be left just beyond the last entry. For other index types, use the appropriate big key.
Note

The more unique the search string is, the more quickly a 'words search proceeds. Thus, 'words queries are slow for search words that have only one or two characters in them. u 7-57

Queries and Cursors

CHAPTER

Data Storage and Retrieval

Reset cursor:Reset() Resets the query cursor to its initial state (pointing to the rst entry satisfying the query). For example: cardCursor:Reset();

Entries
An entry is a connected group of data structures rooted in a frame. An entry is created by the method soup:Add (or unionSoup:AddToDefaultStore), and consists of the frame presented to Add and the transitive closure of that frame's pointers (that is, everything that frame points to, everything those data structures point to, and so on). Circular pointers within an entry are supported; however, entries by denition cannot point outside themselves. They cannot contain pointers to other entries or to data structures in RAM or ROM. Each entry must be an independent piece of data. (An entry can refer another by using the value of the other entrys _uniqueID slot, however.) You can put any slots you like in your entries, and you can vary them from entry to entry. The only slots to which you must pay special attention are those that are indexed. When you create the soup, you specify which slots are to be indexed. Indexed slots must contain data of the type specied by the index. For example, if you specify that an index is to be built on slot foo and that foo contains a text string, then its important that every foo slot in every entry in the indexed soup contains a text string. Entries that do not have a foo slot will not be found in queries on the foo index. Entries having a foo slot that contains data of some type other than text will cause the query to return an index inconsistency error.

7-58

Entries

CHAPTER

Data Storage and Retrieval

Note

In Newton system software prior to version 1.05, storing a value of nil in the indexed slot of an entry returns nil to the query for that entry; that is, the query failed to nd the entry. To work around this problem, make sure your indexed slots store appropriate values. System software version1.05 and later throws an exception when a soup entry is created with a nil value in an indexed slot. u The only way to get a valid entry is by performing a query on a soup. The query returns a cursor, which is an object that iterates over a set of entries and returns them in response to messages directing the position of the cursor. You cannot create an entry procedurally by creating a frame having certain slots and values. The only valid entries are those returned by the various cursor and entry methods.

Entries and RAM


Only one copy of a particular soup entry exists at any time, no matter how the entry was obtained. Thus, if two cursors from two different queries happen to be pointing at identical entries, they are actually both pointing at the same entry. When rst retrieved from a soup, an entry is just an identier. When the entry is accessed as a frame (by getting or setting one of its slots), the complete entry frame is constructed. The frame is specially marked to identify it as a member of the soup from which it came. When the entry is constructed, it is cached in memory until the EntryChange method is called (which writes the entry to the soup) or the function EntryUndoChanges is called (which disposes of the cached entry frame and restores the reference to the original entry). You can also use the global function EntryUndoChanges to dispose of the cached entry frame when appropriate, but note that referencing the entry again afterwards requires reconstructing it, which is relatively slow.

Entries

7-59

CHAPTER

Data Storage and Retrieval

To minimize memory usage, destroy references to entries as soon as they are no longer needed. Until the reference is destroyed, the entry frame remains in RAM, regardless of whether the entry has been written to the soup. Building an array of entries, for example, ties up a lot of memory; the reference to the array should be disposed of (set to nil) as soon as the array is no longer needed.

Sharing Entry Data


Shared soups (and therefore their entries) need to be in a well-documented format to allow other applications to use them. For an example of how to document the structure of your soup entries, refer to Chapter 8, Accessing System Data, to see descriptions of the soups used by the built-in applications on the MessagePad.

Entry Functions
This section describes the functions used to manipulate individual entries that have been returned by a cursor.

About the Entry Metasymbol


The methods described in this section accept soup entries as their arguments. The notation entry is a replaceable metasymbol representing the entry object to be passed to the function. For example, the notation EntryChange(entry) means pass the soup entry object represented by the entry metasymbol to the EntryChange function. In your application, the code to invoke this method would look similar to the following code example. myCursor := query(cardSoup, {type:'index}); myEntry := myCursor:Entry(); myEntry.text := foo; EntryChange(myEntry);

7-60

Entries

CHAPTER

Data Storage and Retrieval

EntryChange EntryChange(entry ) Puts a presumably altered entry back into its soup for permanent storage. Returns an error if entry is not a valid soup entry. The following code example gets an entry from the cardSoup soup, changes it, and then writes the changed entry back to the soup. theStore:=getStores()[0]; cardSoup:=theStore:GetSoup("CardFile"); cardCursor:=query(cardSoup, {type:'index}); theEntry:=cardCursor:Entry(); theEntry.cardType:=4; EntryChange(theEntry); Deciding when to call EntryChange is sometimes difcult. For example, it would be inappropriate to call EntryChange from the viewChangedScript method of a protoLabelInputLine view. If the user enters data into the line with the keyboard, your viewChangedScript would be called after every key press. Calling EntryChange with every key press would be noticeably slow. In some situations, the appropriate time to call EntryChange is more obvious. For example, a natural time to call EntryChange is when the user dismisses a dialog box. Other cases, however, may not be as clear cut. For example, the built-in Notepad application uses a viewIdleScript to call EntryChange once every ve seconds or so. Thats why the Newton user manual suggests waiting 510 seconds before removing a PCMCIA card to avoid data loss. If you manage to corrupt the Notepad or its soup while hacking around, you may see error dialogs every ve secondseach time the Notepad application tries to write to its soup.

Entries

7-61

CHAPTER

Data Storage and Retrieval

EntryChangeWithModTime EntryChangeWithModTime(entry ) Puts a presumably altered entry back into its soup for permanent storage, setting the value of its modTime slot to that stored in the original (unmodied) entry. This special-purpose method is intended for use by backup/restore applications only; most applications need not use it. EntryCopy EntryCopy(entry , newSoup) Copies entry into the new soup referenced by the soup object newSoup. The new entry is returned. EntryModTime EntryModTime(entry ) Returns the time that this entry was last modied. The time is expressed as an integer that is the number of minutes passed since midnight, January 1, 1904. This function get this information directly from the soup, which is faster than referencing the _modTime slot in the entry; the latter approach would require that the entire entry frame be constructed. EntryMove EntryMove(entry , newSoup) Safely moves entry into the new soup referenced by the soup object newSoup . The entry is duplicated in the new soup, the integrity of the duplicate entry is veried, and then the original entry is deleted. EntryRemoveFromSoup EntryRemoveFromSoup(entry ) Removes entry from its soup. The entry frame is converted to a plain frame (unmarked as belonging to a soup).

7-62

Entries

CHAPTER

Data Storage and Retrieval

EntryReplace EntryReplace( oldEntry, newEntry ) Replaces the contents of the soup entry oldEntry with the newEntry entry. oldEntry newEntry The soup entry to be replaced. This value must be an entry, not a normal frame. The soup entry to be added. This value must be an entry, not a normal frame.

EntryReplaceWithModTime EntryReplaceWithModTime(originalEntry , replacementEntry ) Replaces the entry specied by originalEntry with that specied by replacementEntry and records in the modTime slot of the replacementEntry frame the value stored in the modTime slot in the originalEntry frame. This special-purpose method is intended for use by backup/restore applications only; most applications need not use it. originalEntry replacementEntry The soup entry to be replaced. This value must be an entry, not a normal frame. The soup entry to be added. This value must be an entry, not a normal frame.

EntrySize EntrySize(entry ) Returns the number of bytes that entry occupies in the store. EntrySoup EntrySoup(entry ) Returns a reference to the soup in which entry resides.

Entries

7-63

CHAPTER

Data Storage and Retrieval

EntryStore EntryStore(entry ) Returns a reference to the store in which entry resides. EntryTextSize EntryTextSize(entry ) Returns the number of bytes of entry that are occupied by text. EntryUndoChanges EntryUndoChanges(entry ) Disposes the cached entry frame. Any changes made to the frame are lost and the entry frame reverts to the version stored in the soup. EntryUniqueId EntryUniqueId(entry ) Returns the value stored in the specied entrys _uniqueID slot. This function get this information directly from the soup, which is faster than referencing the _uniqueID slot in the entry; the latter approach would require that the entire entry frame be constructed. FrameDirty FrameDirty(frame) Returns TRUE if the specied frame in memory has been written to since it was retrieved from a soup. Otherwise, returns FALSE.

7-64

Entries

CHAPTER

Data Storage and Retrieval

Advanced Techniques
The material in this section is optional reading. It assumes an intimate knowledge of the material covered in preceding sections. Most applications will not need to apply these techniques, many of which arose in the course of investigating solutions to specic questions sent to PIE DTS by Newton application developers.

Getting or Setting the Default Store


This section describes the functions GetDefaultStore and SetDefaultStore, and includes code that you can place in your applications Project Data le to dene these functions. Note that applications using union soups normally do not need to use either of these functions; the system-supplied functions that accept union-soup arguments handle the details of storing and retrieving soup data according to the preferences specied by the user in the Card dialog box. Because these functions may be included in the NTK Platforms le or in ROM on a future Newton device, each of the code examples here tests for the availability of the system-supplied function before using its own implementation. GetDefaultStore GetDefaultStore() Returns a reference to the current default store.
Note

This function may not be dened in ROM it may be supplied by NTK. u

Advanced Techniques

7-65

CHAPTER

Data Storage and Retrieval

SetDefaultStore SetDefaultStore(newDefaultStore) Sets the default store to the one specied and returns a reference to the new default store. newDefaultStore
Note

A reference to the store to be set as default.

This function may not be dened in ROM it may be supplied by NTK. u Example: Toggling the Default Store The following code example uses both of these functions to toggle the default store between the internal and external stores. local theDefault:=GetDefaultStore(); local internal := GetStores()[0]; local external := GetStores()[1]; if theDefault.name == internal.name then SetDefaultStore(external); else SetDefaultStore(internal);

Detecting Null Union Soups


Under unusual circumstances you may encounter a union soup that doesnt contain any constituent soups. Queries on such a union soup fail. This situation should not normally arise; however, some cases in which you may encounter this problem are described here. This section also documents the UnionSoupIsNull function, which you can use to test for this condition. Null union soups are most often found in the aftermath of a debugging sessionfor example, if in the Inspector you have deleted various soups to test the cases in which your application needs to create its own soups, and neglected to restore things to their normal state afterwards.

7-66

Advanced Techniques

CHAPTER

Data Storage and Retrieval

Null union soups can also occur as a result of the application soup not being created properly. Ejecting the card normally leaves behind the internal store constituent of a union soup; however, if this soup was not created or has been deleted, the union soup referencing it will be null when the card is ejected. If you follow the guidelines for the creation of union soups outlined in the section Creating Your Applications Soups, earlier in this chapter, your soup will always exist on the internal store and this problem will not occur. This problem can also occur if another application deletes one or more soups that your application uses. Hopefully, any program that deletes soups would at least call the BroadcastSoupChange function; your applications SoupChanged method could then detect this problem and deal with it. In summary, empty union soups dont normally occur with applications that follow the soup-creation guidelines outlined earlier in this chapter. If youre running into them, you need to think carefully about your code. You can use the UnionSoupIsNull function to detect this problem if necessary. For now, this function is dened in the NTK Platforms le; future Newton platforms will likely dene an IsNull method for union soups. UnionSoupIsNull UnionSoupIsNull(unionSoup) unionSoup The soup to be tested for validity

Returns TRUE if the specied union soup has no constituent soups.


Note

This function may not be dened in ROM it may be supplied by NTK. u

Advanced Techniques

7-67

CHAPTER

Data Storage and Retrieval

Summary of Functions and Methods


This section categorizes the data storage functions and methods by task.

Accessors
These functions and methods allow you to get and set soup, store and entry data.

Stores
store:CheckWriteProtect() store:GetInfo(slotSymbol ) store:GetKind() store:GetName() store:GetPackageDirectory() GetPackages() store:GetSignature() store:GetSoup(soupNameString) store:GetSoupNames() GetStores() store:HasSoup(soupName) store:IsReadOnly() RemovePackage(packageFrame) store:RestorePackage(packageObject) store:SetInfo(slotSymbol ,value ) store:SetName(storeNameString) store:TotalSize() store:UsedSize()

7-68

Summary of Functions and Methods

CHAPTER

Data Storage and Retrieval

Soups
soup:Add(frame) soup:AddIndex(indexSpec) unionSoup:AddToDefaultStore(frame) soup:AddWithUniqueId(frame) sourceSoup:CopyEntries(destSoup ) soup:Flush() soup:GetIndexes() soup:GetInfo(slotSymbol ) soup:GetName() soup:GetSignature() soup:GetStore() GetUnionSoup(soupNameString) soup:IndexSizes() IsSoupEntry(object) soup:RemoveAllEntries() soup:RemoveFromStore() soup:RemoveIndex(indexPath) soup:SetInfo(slotSymbol ) soup:SetName(soupNameString) soup:SetSignature(signature) UnionSoupIsNull(unionSoup)

Entries
EntryChange(entry ) EntryCopy(entry , newSoup) EntryModTime(entry ) EntryMove(entry , newSoup) EntryRemoveFromSoup(entry ) EntryReplace(oldEntry, newEntry) EntrySize(entry ) EntrySoup(entry )

Summary of Functions and Methods

7-69

CHAPTER

Data Storage and Retrieval

EntryStore(entry ) EntryTextSize(entry ) EntryUndoChanges(entry ) EntryUniqueId(entry ) FrameDirty(frame)

Queries and Cursors


These functions allow you to query a soup and manipulate the cursor returned by the query. Query (soupRef, querySpec ) cursor:Clone() cursor:Entry() cursor:GoTo(entry) cursor:GoToKey(key) MapCursor(cursor, function) cursor:Move(n) cursor:Next() cursor:Prev() cursor:Reset()

Notication
These functions are used register or unregister soups with the notication mechanism and propagate notications to applications registered with a particular soup. Though some of these functions also create soups, none of them remove soups. BroadcastSoupChange(soupNameString) :RegisterCardSoup(soupName,indexArray,appSymbol ,appObject) SetupCardSoups() :UnRegisterCardSoup(soupName)

7-70

Summary of Functions and Methods

CHAPTER

Data Storage and Retrieval

Soup Creation
These functions allow you to create soups and union soups. store:CreateSoup (soupName, indexArray ) :RegisterCardSoup(soupName,indexArray,appSymbol ,appObject) SetupCardSoups()

Special-Purpose
These functions are intended for use by special-purpose data backup and restoration programs only. Many of them intentionally defeat the errorchecking features upon which the system relies to maintain unique values in the _uniqueID and _modTime slots. store:GetAllInfo() store:SetAllInfo(frame) store:SetSignature(signature) soup:GetAllInfo() soup:GetNextUid() soup:SetAllInfo() EntryChangeWithModTime(entry ) EntryReplaceWithModTime (originalEntry , replacementEntry )

Utility
These methods allow you to perform maintenance functions. store:Erase( )

Summary of Functions and Methods

7-71

CHAPTER

Accessing System Data

This chapter describes the structure of the data stored in soups by the Newton built-in applications. It also describes the system globals to which you have access. For safest access to the soups of the built-in applications, you should use compile-time constants to get references to the soup names. These constants are listed in each section, along with the actual soup names. However, as with much software, the names are subject to change in the future, so its safer to use the constants, which will continue to evaluate properly. Every soup entry documented in this chapter includes two slots that all soup entries contain: _uniqueID _modtime A unique identier for the entry within the soup. Contains an immediate value; the date and time that the entry was last modied, in the number of minutes passed since midnight, January 1, 1904. Note that this slot is not present unless the entry has been modied.

These slots are included in every soup entry because they are added by the system. They are not mentioned in the following soup descriptions.

8-1

CHAPTER

Accessing System Data

Notepad Application
The Notepad application stores all notes written on the notepad in a single soup. You should use the compile-time constant ROM_PaperRollSoupName to get a reference to the name of the notepad soup (Notes). A note in the notepad consists of all of the information stored under one date bar up to the next bar. The notepad soup contains one entry for each note. Each entry is a frame containing the following slots:
Slot Name Description

viewStationery Always contains the symbol 'paperroll height Contains an immediate value that is the height, in pixels, of the note. data An array of frames containing either text objects, polygons, or ink objects. There is one frame for each text paragraph, polygon, or ink object written in the note. The text object frames have these slots: viewStationery Always contains the symbol 'para viewBounds The bounds of the text object text A string that is the text contained in the paragraph tabs Optional. An array of tab stops styles Optional. An array holding font style information for the text For more information on the slots particular to paragraph views, refer to the section Text View (clParagraphView) beginning on page 4-6. The polygon object frames have these slots: viewStationery Always contains the symbol 'poly

8-2

Notepad Application

CHAPTER

Accessing System Data

viewBounds The bounds of the polygon points Contains a binary data structure holding polygon data. For more information, refer to the section Shape View (clPolygonView) beginning on page 4-16. The ink object frames have these slots: ink Contains a binary data structure of the class 'ink that holds the ink data. viewBounds The bounds of the ink object Contains an immediate value; the date and time that this note was created, in the number of minutes passed since midnight, January 1, 1904.

timestamp

A note entry frame may also contain the following optional slot:
Slot Name Description

labels

A symbol specied by the user as a label (le folder) for the note.

Names Application
The Names application stores its data in a single soup that contains an entry for each card. You should use the compile-time constant ROM_CardFileSoupName to get a reference to the name of the names soup (Names). Each entry consists of a frame containing the following required slots:
Slot Name Description

cardType sortOn

Contains an immediate value that species what type of card layout the card has. A string by which this card is to be sorted. The string is equivalent to the last name or the company name, whichever the user has indicated this card should

Names Application

8-3

CHAPTER

Accessing System Data

name

company

be sorted by. This string is of class 'Name if it is the last name, or it is of class 'Company if it is the company name. This slot is required only if no Company is entered on the card. Contains a frame of class 'Person with these slots: first A string; the person's rst name. last A string; the person's last name. Has the class 'Name. honorific A string; the prex Mr., Ms., Dr., etc. title A string; the person's title. This slot is required only if no Name is entered on the card. Contains a string of class 'Company whose value is the company name.

Each frame may also contain the following optional slots:


Slot Name Description

address address2 city region postal_code country phones

bday

email labels

A string; the person's street address. A string; the second line of the address. A string; the person's city. A string; the person's state or province. A string; the person's zip code. A string; the person's country. Contains an array of up to four phone number strings. Each string has one of these classes to tag it as a particular type of phone number: 'phone, 'faxPhone, 'homePhone, 'workPhone, 'otherPhone, 'carPhone, 'beeperPhone, or 'mobilePhone. Contains an immediate value; the date entered for the birthday, in the number of minutes passed since midnight, January 1, 1904. A string; the persons e-mail address. A symbol specied by the user as a label (le folder) for the card.

8-4

Names Application

CHAPTER

Accessing System Data

notes

Contains an array of card note objects. Card notes are visible when the notes portion of the card is showing. Card notes consist of text objects, polygons, or ink objects. These objects have the same format as data objects in the Notes soup. For information on the format of these objects, see the description of the data slot in the section Notepad Application beginning on page 8-2. Text objects have, in addition, a viewFont slot specifying the font of the text.

Dates Application
The Dates application stores meeting information, notes, and to-do list items in the following soups:
Soup (name string)

Description

ROM_CalendarSoupName (Calendar) Entries are meeting frames for nonrepeating meetings. Also stores all calendar annotations (notes on the calendar not associated with a meeting). Annotations are stored as text objects, polygons, or ink objects. These objects have the same format as data objects in the Notes soup, except they also have a mtgStartDate (see below) slot. For information on the format of these annotation objects, see the description of the data slot in the section Notepad Application beginning on page 8-2. ROM_RepeatMeetingName (Repeat Meetings) Entries are meeting frames for repeating meetings. A single entry describes all of the daily instances of a repeating meeting. ROM_CalendarNotesName (Calendar Notes) Entries are meeting frames. Stores all notes written in the crib note area of the calendar (the blank space to the left of the small month calendar).

Dates Application

8-5

CHAPTER

Accessing System Data

ROM_RepeatNotesName (Repeat Notes) Entries are meeting frames for repeating crib notes. ROM_TodoSoupName (To do) Entries are to-do frames. Stores all to-do list information. The slot structure of meeting frames and to-do frames is described in the following sections.

Meeting Frames
Each meeting frame contains the following required slots:
Slot Name Description

viewStationery In the Calendar soup always contains the value 'Meeting for a meeting or 'Para or 'Poly for a calendar annotation. In the Repeat Meetings soup always contains the value 'repeatingMeeting. In the Calendar Notes and Repeat Notes soups always contains the value 'CribNote. mtgStartDate Contains an immediate value; the start date of the meeting (or date the crib note was entered) in the number of minutes passed since midnight, January 1, 1904. mtgDuration Contains an immediate value; the duration of the meeting in minutes (this value is meaningless for crib notes). mtgText A string containing the meeting text or crib note. A meeting frame may also contain the following optional slots:
Slot Name Description

mtgStopDate

Used for repeating meetings. An immediate value; the date that the meeting should stop repeating, in the number of minutes passed since midnight, January 1, 1904.

8-6

Dates Application

CHAPTER

Accessing System Data

repeatType

mtgInfo

Contains one of the following constants that describe how often the meeting repeats: kDayofWeek (0), kWeekInMonth (1), kDateInMonth (2), kDateInYear(3), kPeriod(4), kNever(5). An immediate value containing packed repeating meeting information. This slot is interpreted differently, depending on the value of the repeatType slot, as follows: repeatType = kDayOfWeek mtgInfo is set to any combination of the following constants: kSunday 0x00000800 kMonday 0x00000400 kTuesday 0x00000200 kWednesday 0x00000100 kThursday 0x00000080 kFriday 0x00000040 kSaturday 0x00000020 kEveryday 0x00000FE0 kFirstWeek 0x00000010 kSecondWeek 0x00000008 kThirdWeek 0x00000004 kFourthWeek 0x00000002 kLastWeek 0x00000001 kEveryWeek 0x0000001F repeatType = kWeekInMonth mtgInfo is set to a single constant from the rst group above, and any combination from the second group. repeatType = kDateInMonth mtgInfo is set to the date in the month on which the meeting is to repeat.

Dates Application

8-7

CHAPTER

Accessing System Data

repeatType = kDateInYear mtgInfo is set to ( month<<8) + date , where month is the number of the month in the year (January = 1) and date is the date in the month on which the meeting is to repeat. repeatType = kPeriod mtgInfo is set to ( mtgDay<<8) + period, where mtgDay is the date, measured in days, of the meeting. This is the same as mtgStartDate, but in days, instead of minutes (that is, TotalMinutes(Date (mtgStartDate)) DIV 1440). period is the number of days between meetings. Technically, period can range between 1 and 255, however, the current Newton user interface allows the user to choose only every other week (14 days) for this kind of meeting. Opening a kPeriod meeting will always display it as an Every other week meeting type and reset its period to 14.
Note

mtgInfo uses only the least significant 24 bits of the integer. The remaining bits are reserved for future expansion. Always be sure to mask out the upper bits so a future change in format will not overow your values. u mtgAlarm Contains an immediate value. For single (nonrepeating) meetings, this is the time when the alarm should occur. This is represented as the number of minutes passed since midnight, January 1, 1904. For repeating meetings, this slot contains the number of minutes before the meeting that the alarm should occur.

8-8

Dates Application

CHAPTER

Accessing System Data

notesData

viewBounds exceptions

Contains an array of meeting note objects. Meeting notes are the notes visible when you tap on a meeting to open its notes view. Meeting notes can consist of text objects, polygons, or ink objects. These objects have the same format as data objects in the Notes soup. For information on the format of these objects, see the description of the data slot in the section Notepad Application beginning on page 8-2. Text objects have, in addition, a viewFont slot specifying the font of the text. A bounds frame used only for double-booked meetings. Used in the Repeat Meetings soup only. This is an array of arrays representing meetings that are exceptions to the normal repeating time for the meeting. For example, the user may have erased one of the meeting instances or changed the starting time or duration of one of the meetings. It would then be listed in this array as an exception. The internal format of meetings is subject to change, so you should treat this array as read-only, and not attempt to add to it. Each sub-array represents one exception. There are two elements in each array. The rst is an integer specifying the normal time of the meeting, in the number of minutes since midnight, January 1, 1904. The second element is either nil, meaning the meeting has been erased, or a clone of the meeting frame for this meeting. The cloned meeting frame contains the changed information, such as a different mtgStartDate or mtgDuration. Note that the viewStationery slot of the cloned meeting frame contains the symbol 'exceptionMeeting.

Dates Application

8-9

CHAPTER

Accessing System Data

To-do Frames
Each to-do frame contains the following required slots:
Slot Name Description

viewStationery Always contains the value 'TodoItem. height Contains an immediate value that is the height in pixels of the to-do item. mtgStartDate Contains an immediate value; the date and time that this to-do item was entered, in the number of minutes passed since midnight, January 1, 1904. mtgDone Contains an immediate value; true if the item is marked as done, and nil if the item is not marked as done in the to-do list. mtgPriority Contains an immediate value that is the priority of the to-do list item, as set by the user: 0 = priority A 1 = priority B 2 = priority C 3 = no priority set (default) A to-do frame may also contain the following optional slot:
Slot Name Description

data

Contains an array of frames representing text objects, polygons, or ink objects. These objects have the same format as data objects in the Notes soup. For information on the format of these objects, see the description of the data slot in the section Notepad Application beginning on page 8-2. Text objects have, in addition, a viewFont slot specifying the font of the text.

8-10

Dates Application

CHAPTER

Accessing System Data

System and User Preferences Data


The system stores user preferences and other system information in a soup. You should use the compile-time constant ROM_SystemSoupName to get a reference to the name of the system soup (System). The system soup initially contains only a single entry containing all user preference and system related settings in the slots in that entry. Each application that needs to save user preference or state information should create a single entry in the system soup to store its data. For an example of how to do this, see the section Application Preferences Code Example beginning on page 8-19. Each entry in the system soup must contain a slot named Tag whose value is a string uniquely identifying the application to which the entry belongs. The system user preferences entry contains a Tag value of "userConfiguration". Other than the Tag slot, each entry can contain any other slots needed to store application-specic data. The system soup is indexed on the Tag slot, allowing quick access to your applications entry.

User Conguration Entry


This section describes the slots stored in the userConfiguration entry in the system soup. The slots are listed in alphabetical order. Note that not all slots listed here will necessarily be present. If an item hasnt been set yet and has no default value, then it wont appear in the entry.
Note

The global variable userConfiguration always contains the current userConfiguration entry from the system soup, so you dont need to query the system soup to retrieve this information. u

System and User Preferences Data

8-11

CHAPTER

Accessing System Data

Slot Name

Description

actionSoundEffects True if the user has checked the box Action Sound Effects in the Sound Preferences form, nil otherwise. address The string that the user entered as the rst line of their Address in the Personal Preferences form. alarmSoundEffects True if the user has checked the box Alarm Sound Effects in the Sound Preferences form, nil otherwise. bcards An array of bitmap frame objects which are the choices available for the Card Style item when creating or editing a card. beepSound A symbol identifying the sound to be used as the system beep sound. This is set by the user in the Sound Preferences form. blindDialing True for blind dialing (don't wait for dial tone), nil otherwise. This is set by the user with the checkbox Require Dial Tone, in the Modem Preferences form. calendarStartTime An integer representing a number of minutes past midnight. This time is the hour to which the Calendar was last opened; that is, the hour displayed at the top of the Calendar when it was last opened. When the Calendar is reopened, it will display the day beginning at this time. callingCard A string that is the number the user entered in the Credit Card eld of the Call Options slip. carrierDelay An integer specifying the number of seconds to wait for a carrier. This is set by the user in the Wait For Answer item in the Modem Preferences form. cityZip The string that the user entered as the second line of their Address in the Personal Preferences form. commaDelay An integer specifying the delay in seconds for a comma in the phone number when dialing.

8-12

System and User Preferences Data

CHAPTER

Accessing System Data

commonCountries An array of symbols representing common countries listed in the Country picker in the Personal Preferences form, the Names File address card, and other places. The string that the user entered as their Company name in the Personal Preferences form. The string that the user entered as their Country in the Personal Preferences form. A symbol representing the country specied by the user as their Country in the Personal Preferences form.

company country countrySlot currentAreaCode

The area code of the current or last number dialed. This is entered by the user in the Area Code eld of the Call Options slip. currentCountry A symbol representing the country specied by the user as their Country in the Personal Preferences form, or as their current location in the Time Zones map, whichever was set last. This symbol is used to determine if international dialing codes are needed when dialing phone numbers. currentDialNumber A string that is the current or last entire phone number dialed (includes dialing prex, area code, phone number, credit card number, and so on). This comes from the entries made by the user on the Call slip and its associated options slip. currentDialSpeaker A symbol identifying how the current number is to be dialed: 'modem (dial by modem) or 'speaker (generate tones through the Newton speaker). This is set by the user on the Call slip. currentFaxNumber A string that is the current or last entire fax phone number dialed (includes dialing prex, area code, phone number, credit card number, and so on). This comes from the entries made by the user on the Fax Slip and its associated options slip. 8-13

System and User Preferences Data

CHAPTER

Accessing System Data

currentFaxTitle A string used as the fax title. If not specied, the user's name and fax phone number are concatenated to create this string. currentPrinter A frame describing the last printer selected for use in a Print slip. currentZone A string holding the name of the current AppleTalk zone that the Newton is attached to. If the Newton is not attached, it holds an asterisk (*). curveShapeOption True if the user has checked the box Straighten Curves in the Recognizers Preferences form, nil otherwise. daylightSavings The number of seconds of daylight savings time offset. This slot is currently not used and is always zero. dialing A symbol identifying the dialing type: 'touchTone or 'pulse. This is set by the user with radio buttons in the Modem Preferences form. dialingPrefix A string that is the dialing prex of the current or last number dialed. This is entered by the user in the Prex eld of the Call Options slip. docker A frame containing preferences set by the Connection application. doShapeRecognition True if shape recognition is enabled, nil otherwise. This is controlled by the recognition toggle on the status bar. doTextRecognition True if text recognition is enabled, nil otherwise. This is controlled by the recognition toggle on the status bar. doubleTime An integer representing the maximum number of ticks between taps in a double-tap. faxPhone The string that the user entered as their Fax phone in the Personal Preferences form. faxResolution A symbol identifying the resolution at which faxes should be sent. The symbol 'normal uses 204 x 98 pixel 8-14

System and User Preferences Data

CHAPTER

Accessing System Data

resolution; the symbol 'fine uses 204 x 196 pixel resolution. (The system actually uses the highest resolution supported by the receiving fax machine.) gravityShapeOption True if the user has checked the box Close Shapes in the Recognizers Preferences form, nil otherwise. guestAccessOption True if the user has checked the box Configure for Guest User in the Handwriting Style Preferences form, nil otherwise. homePhone The string that the user entered as their Home phone in the Personal Preferences form. keyboard A string that the user selected as their Keyboard in the Locale Preferences form. lcdContrast An integer holding the current LCD contrast setting. This is set by the user with the Contrast control at the bottom of the Extras drawer. letterheadForm A frame dening the template to be used as the letterhead when printing. lettersCursiveOption True if the user has checked the box Words Not in Word Lists in the Recognizers Preferences form, nil otherwise. letterSetSelection An integer representing the choice that the user selected for their handwriting style in the Handwriting Style Preferences form. Zero represents Mixed Cursive & Printed, one represents Cursive Only, and two represents Printed Only. letterSpaceCursiveOption An integer value from 0 to 9 that species how close together the user writes words. This item is set by the user in the Handwriting Style Preferences form. locale A string that the user selected as their Country in the Locale Preferences form.

System and User Preferences Data

8-15

CHAPTER

Accessing System Data

A frame containing information about the current location set in the WorldClock. The location frame contains these slots: name A string that is the name of the city. latitude The encoded city latitude. longitude The encoded city longitude. gmt The offset of the city, in seconds, from GMT. country A symbol that identies the country. areaCode The area code of this location. longDistanceAccess A string that is the number the user entered in the Access Code eld of the Call Options slip. mailAccount A string that is the user s e-mail account name, entered in the E-mail Account eld of the Mail Preferences form. mailNetwork A symbol representing the e-mail network selected in the Network eld of the Mail Preferences form. mailPhone A string that is the number entered in the Phone Number eld of the Mail Preferences form. mailSystem A string that is the e-mail system identier entered in the System ID eld of the Mail Preferences form. modemSoundVolume An integer (from 0 to 4) specifying the modem speaker sound volume. This is set by the user in the Modem Volume item in the Modem Preferences form. name The string that the user entered as their Name in the Personal Preferences form. numbersCursiveOption True if the user has checked the box Numbers in the Recognizers Preferences form, nil otherwise. paperSize A frame describing the Paper Size selected by the user in the Locale Preferences form. The frame contains these slots: top The top paper coordinate (usually 0). left The left paper coordinate (usually 0). location

8-16

System and User Preferences Data

CHAPTER

Accessing System Data

paperSizes

bottom The bottom paper coordinate. right The right paper coordinate. title A string that describes the selected choice. id A symbol identifying the paper size. An array of paperSize frames. These are the paper sizes currently installed in the system. They appear as choices for the Paper Size item in the Locale Preferences form.

penSoundEffects True if the user has checked the box Pen Sound Effects in the Sound Preferences form, nil otherwise. phone The string that the user entered as their Ofce phone in the Personal Preferences form. punctuationCursiveOption True if the user has checked the box Words With Punctuation in the Recognizers Preferences form, nil otherwise. sleepTime An integer that is the number of seconds after which the Newton should go into sleep mode if there has been no user activity. This item is set by the user in the Sleep Preferences form. soundVolume An integer (from 0 to 4) specifying the system speaker sound volume. This is set by the user in the Sound Preferences form or by the slider control at the bottom of the Extras drawer. speedCursiveOption An integer value from 0 to 9 that species the speed with which to recognize handwriting. Note that faster speeds yields less accurate results. This item is set by the user in the Handwriting Style Preferences form. symmetryShapeOption True if the user has checked the box Make Shapes Symmetrical in the Recognizers Preferences form, nil otherwise.

System and User Preferences Data

8-17

CHAPTER

Accessing System Data

timeoutCursiveOption An integer value from 15 to 60 that species the timeout after writing before which the writing is recognized. This item is set by the user in the Handwriting Style Preferences form. useDateDomain True if the user has checked the box Dates in the Recognizers Preferences form, nil otherwise. useGeneralShapeDomain True if shape recognition is enabled, nil otherwise. This is controlled by the recognition toggle on the status bar. usePhoneDomain True if the user has checked the box Telephone Numbers in the Recognizers Preferences form, nil otherwise. usePassword True if the user has enabled a system password, nil otherwise. userFolders A frame containing the names of folders where items (notes, cards, etc.) can be led. If the user adds new folders, they are added to this frame, and the slots are sorted in alphabetical order. Each slot name is the name of a folder, and the slot value is the string representation of the folder name. userFont An integer specifying the font set by the user in the Styles palette. This integer is a packed value representing the current font family, size and face. For details on font specications, see the section Specifying a Font beginning on page 4-11. userPenSize The thickness in pixels of the electronic ink left by the pen when writing on the screen. This is set by the user in the Styles palette. useTimeDomain True if the user has checked the box Times of Day in the Recognizers Preferences form, nil otherwise. wordsCursiveOption True if the user has checked the box Words in Word Lists in the Recognizers Preferences form, nil otherwise.

8-18

System and User Preferences Data

CHAPTER

Accessing System Data

zapAutoReceive True if the user has checked the box Receive Beams Automatically in the Beam Preferences form, nil otherwise. zapAutoRoute True if the user has checked the box Put Away Beams Immediately in the Beam Preferences form, nil otherwise. zapCloseInBox True if the user has checked the box Close InBox After Receiving in the Beam Preferences form, nil otherwise. zapConfirmReceive True if the user has checked the box Confirm Before Receiving in the Beam Preferences form, nil otherwise. zapOpenInBox True if the user has checked the box Open InBox While Receiving in the Beam Preferences form, nil otherwise.

Application Preferences Code Example


The following code example retrieves application preferences data from the system soup. If the application preferences entry is not found in the system soup, it is created. local sysSoup := GetStores()[0]:GetSoup(ROM_SystemSoupName); local cursor := Query(sysSoup, {type: 'index, indexPath: 'tag, startKey: kAppString, endTest: func(e) NOT StrEqual(e.tag, kAppString)}); prefsEntry := cursor:Entry(); if NOT prefsEntry then prefsEntry := sysSoup:Add({tag: kAppString, appSpecificSlot: nil}); // kDefaultPreferencesFrame is a constant that you // have previously defined. It contains default // preferences for your app prefsEntry._proto := kDefaultPreferencesFrame;

System and User Preferences Data

8-19

CHAPTER

Accessing System Data

If your application has default preferences, it is a good idea to make a default preferences frame and assign it to a constant or a slot in your application. Then when you read your preferences entry from the system soup, you should add to the entry frame a _proto slot that points to the default preferences frame. That way, only changes to the default are saved in the soup, minimizing RAM use.The last line of code in the example shows how to do this. The _proto slot is automatically removed by the system if the soup entry is changed and rewritten to the soup, since _proto slots are not allowed in soup entries.

Globals
There are several global variables dened in the Newton system that you may need to reference. They are documented here in alphabetical order.
Variable Description

availablePrinters An array of printer drivers currently available in the system. Each element is a frame whose Name slot holds a string that names the printer. cardSoups An array containing the names of soups that can be stored on PCMCIA cards. There are two array entries for each soup; the rst is a string that is the name of the soup, and the second is an array of index specication frames describing the indexes that exist for the soup. You shouldnt directly modify the cardSoups array. Use the RegisterCardSoup function, which you can nd documented in the chapter Data Storage and Retrieval. classes A frame used to record new object classes, and the superclasses from which they descend. Each slot is the name of a new subclass. The slot value is a symbol that names the superclass from which the new subclass descends. You can create a new subclass by adding a slot to this frame.

8-20

Globals

CHAPTER

Accessing System Data

dictionaries

findApps fonts

formulaList

inCategories international

ioBusy

ioStopping lastEx

lastExError

An array of dictionaries installed in the system. Each array element is a frame describing a dictionary. In each of these frames, the Name slot holds a string that is the dictionary name. An array of symbols identifying applications that have been registered as supporting global Finds. A frame containing a slot for each screen font installed in Newton. The name of each slot is a font name, and the value of each slot is a font description frame. In a font description frame, the name slot holds a string that is the font name. An array of templates to be used for the views in the Formulas application. The Formulas application is built on a protoRollBrowser, and this array is used for the rollItems slot. A frame containing slots that identify the inbox categories that are installed in the system. A frame containing the international resources available in the system. Do not change any values in this frame. The information in this frame is subject to change in future system software versions. A Boolean set to true when the inbox or outbox is performing input or output, and set to nil when there is no input/output activity. You can check this value before performing custom input/output operations to ensure that the system is not already busy. A Boolean set to true when the system is aborting input/output activity. Normally, this global is nil. For debugging purposes. This slot contains a string that is the name of the last exception that occurred in the system. For debugging purposes. This slot contains an integer that is the error code associated with the last exception that occurred in the system.

Globals

8-21

CHAPTER

Accessing System Data

For debugging purposes. This slot contains a string that is the message associated with the last exception that occurred in the system, if that exception contained a message. notifications An array of frames that is a log of notications that have been sent to the user by the system notication facility. (Only the last four notications are saved in the log.) Each notication frame contains the following slots: timestamp The time the notication was sent. overview A string that serves as a title (it usually identies who or what sent the notice). nfText A string that is the notice text. nfType The level of notication where 1=kNotifyLog, 2=kNotifyMessage, 3=kNotifyAlert, and 4=kNotifyQAlert (see the Notify method for details) height The height of the notice view. outCategories A frame containing slots that identify the outbox categories that are installed in the system. powerOffHandlers An array of views that have registered themselves as power-off handlers by using the global function AddPowerOffHandler. preferences An array of templates to be used for the views in the Preferences application. The Preferences application is built on a protoRollBrowser, and this array is used for the rollItems slot. printDepth For debugging purposes. This slot contains an integer that indicates the number of levels of objects that are to be expanded when a frame is printed in the Inspector. psFonts Same as fonts, but contains references to font width tables for printing on PostScript printers. routing A frame containing a slot for each application that supports routing. Each slot name identies an applicalastExMessage

8-22

Globals

CHAPTER

Accessing System Data

tion and the slot value is a frame describing the kinds of routing supported by that application. soupNotify An array of soup-name/application-name pairs. The rst item in each pair of elements is a string that is a soup name. The second item is a symbol identifying the application that maintains that soup. The system uses this array when a soup changes, to nd the application that maintains it. A SoupChanged message is then sent to that application, and one parameter is passed which is a string that is the name of the soup that changed. This allows an application to take an action when its soup is changed by a different application. trace For debugging purposes. This slot controls the level of tracing output that appears in the Inspector. Set this slot to the symbol 'functions to view function calls and message sends. Set this slot to true to view function calls, message sends, and each access of frames and variables. Set this slot to nil to turn off tracing (you can do this by clicking the Trace Off button in the lower-left corner of the Inspector window). userConfiguration A reference to the user preferences soup entry. This frame contains all of the default system settings and user preferences. For details, see the section System and User Preferences Data beginning on page 8-11. For more information about using the debugging-related slots, refer to the chapter Debugging in the Newton ToolKit Users Guide.

Globals

8-23

CHAPTER

Drawing

This chapter describes how to draw simple graphics and text inside of views on the Newton. With the Newton drawing system, you can draw these kinds of objects:
n n n n n n n n n n

Lines Rectangles Rounded rectangles Ovals (including circles) Polygons Wedges Regions Text Pictures Bitmaps

9-1

CHAPTER

Drawing

In addition to drawing these shapes, you can manipulate shapes in these ways:
n n n

Offsetting (moving) Scaling Hit testing (see the chapter Written Input and Recognition for a discussion of hit testing)

Overview
When a view is shown on the screen, the Newton system draws it according to the parameters you have specied in the view template. When the system is done drawing, it sends the viewDrawScript message to the view. If you want to do your own drawing, you must provide a viewDrawScript method to handle this message. Your viewDrawScript method should call whatever drawing routines you want. Your viewDrawScript method is called whenever your view is redrawn. This can happen as a result of a system or user operation, or if your view receives the Dirty message. In fact, if you want to execute your drawing calls explicitly at particular times, just send your view the Dirty message and the system will respond by redrawing your view and then sending you the viewDrawScript message so your drawing routines get executed. There may be other times when you want to draw in a view besides when the whole view is redrawn. For example, you may have some drawing routines that you want to call just when the user clicks in the view. In this and other cases where you want to draw outside of the viewDrawScript method, use the DoDrawing method. The DoDrawing method simply calls another method that you supply and that contains drawing routines.

9-2

Overview

CHAPTER

Drawing

How to Draw
Drawing on the Newton is a simple two-part process. First you call a function (or several functions) to create a shape, such as MakeRect, which returns a shape object. And then you call the method DrawShape to draw the shape. In addition to the shape object, DrawShape accepts a second parameter which is a style frame. This is a frame specifying the style attributes to use in drawing the shape. Style attributes include things like pen size, pen pattern, ll pattern, transfer mode, and so on. This system is versatile because it separates the shapes from the styles with which they are drawn. You can create a single shape and then easily draw it using different styles at different times. Another feature is that DrawShape can accept an array of shapes instead of just a single one. You can create a series of shapes and draw them all at once with a single call to DrawShape. Additional style frames can be included in the shape array to change the drawing style for the shapes that follow them. For all of the functions described in this chapter,
n

The coordinates you specify are interpreted as local to the view in which the object is drawn The origin of the coordinate plane (0,0,) is the upper-left corner of the view in which the object is drawn Positive values are towards the right or towards the bottom of the screen from the origin.

How to Draw

9-3

CHAPTER

Drawing

Function Reference
The drawing functions and methods are described in the next two sections. The rst section, Shape-Creation Functions, describes functions that create different kinds of shapes. The second section, Shape Operations, describes operations, including the DrawShape method, that you can perform on shapes.

Shape-Creation Functions
These global functions create shape objects which you can draw using the DrawShape method (described in the section Shape Operations). MakeLine MakeLine (x1, y1, x2, y2) Creates and returns the specied line shape. x1 y1 x2 y2 MakeRect MakeRect (left, top, right, bottom) Creates and returns the specied rectangle shape. left top right bottom The x-coordinate of the top-left corner of the rectangle The y-coordinate of the top-left corner of the rectangle The y-coordinate of the bottom-right corner of the rectangle The x-coordinate of the bottom-right corner of the view. The x-coordinate of the rst point drawn The y-coordinate of the rst point drawn The x-coordinate of the last point drawn The y-coordinate of the last point drawn

9-4

Function Reference

CHAPTER

Drawing

MakeRoundRect MakeRoundRect (left, top, right, bottom, diameter) Creates and returns a rounded rectangle shape (a rectangle having rounded corners.) left top right bottom diameter The x-coordinate of the top-left corner of the rectangle The y-coordinate of the top-left corner of the rectangle The y-coordinate of the bottom-right corner of the rectangle The x-coordinate of the bottom-right corner of the rectangle The curvature of the rectangle corners, specied as if a circle of the specied diameter, in pixels, was placed in each of the rectangles corners

MakeOval MakeOval (left, top, right, bottom) Creates and returns an oval shape. The oval is shaped to t just inside the specied rectangle. If you specify a rectangle that is square, this method draws a circle. left top right bottom The x-coordinate of the top-left corner of the ovals enclosing rectangle The y-coordinate of the top-left corner of the ovals enclosing rectangle The y-coordinate of the bottom-right corner of the ovals enclosing rectangle The x-coordinate of the bottom-right corner of the ovals enclosing rectangle

Function Reference

9-5

CHAPTER

Drawing

MakeWedge MakeWedge (left, top, right, bottom, startAngle, arcAngle ) Draws an arc as a part of an oval that ts just within the specied rectangle. If you draw the wedge with no ll, you see just the arc line. If you draw the shape with a visible ll pattern, you see a solid wedge shape. left top right bottom startAngle arcAngle The x-coordinate of the top-left corner of the arcs enclosing rectangle The y-coordinate of the top-left corner of the arcs enclosing rectangle The y-coordinate of the bottom-right corner of the arcs enclosing rectangle The x-coordinate of the bottom-right corner of the arcs enclosing rectangle The angle at which the arc begins, in positive (clockwise) or negative (counterclockwise) degree values. The angle through which the arc extends, in positive (clockwise) or negative (counterclockwise) degree values.

The angles are given in positive or negative degrees; a positive angle goes clockwise, while a negative angle goes counterclockwise. Zero degrees is at 12 o'clock high, 90 (or -270) is at 3 o'clock, 180 (or -180) is at 6 o'clock, and 270 (or -90) is at 9 o'clock. Other angles are measured relative to the enclosing rectangle: A line from the center of the rectangle through its top right corner is 45 degrees, even if the rectangle isn't square; a line through the bottom right corner is at 135 degrees, and so on. MakePolygon MakePolygon (pointArray ) Creates and returns the specied polygon shape. pointArray An array of x and y coordinate pairs specifying the vertices of the polygon

9-6

Function Reference

CHAPTER

Drawing

MakeShape MakeShape (object) Creates and returns a shape based on object. The following kinds of shapes are created, depending on what kind of object is passed in object: rectangle You can pass in a bounds frame describing a rectangle. A bounds frame has the following slots: left, top, right, bottom. A rectangle shape is created and returned. You can pass in the value stored in the points slot in a view of class clPolygonView. This is a binary data structure that has a class of 'polygonShape and contains data describing a polygon shape. A polygon shape is created and returned.
Note

points

This option is intended to create a shape from data you retrieve from a clPolygonView. However, you can manually create the points data structure by using the ArrayToPoints routine. This routine is described in the discussion of Shape View in the chapter Working with View Classes. u bitmap You can pass in a bitmap frame object. A bitmap shape is created and returned.You can use the compile-time function GetPictAsBits to create a bitmap from a 'PICT' resource; for more information, see the Using Resources appendix in Newton Toolkit User's Guide. You can pass in a picture. A picture shape is created and returned.

picture

MakeRegion MakeRegion (shapeArray ) Creates and returns a region of arbitrary size, shape, and complexity. You dene a region by dening its boundary with other shape drawing functions. The boundary can be any set of lines and shapes (even including other regions) forming one or more closed loops. A region can be concave or

Function Reference

9-7

CHAPTER

Drawing

convex, can consist of one connected area or many separate ones, and can even have holes in the middle. shapeArray An array of shapes returned by any of the shape-making functions described in this section.

MakePict MakePict (shapeArray , styleFrame) Creates and returns a picture shape that is created by recording a sequence of drawing operations. This groups several drawn shapes into a single graphic entity which is easier, smaller, and faster to use in subsequent drawing operations than drawing each of the shapes individually each time. This function works exactly like the DrawShape method except that the shapes are not drawn on the screen, but are drawn into a picture shape object that is returned. shapeArray An array of shapes to draw using the style attributes specied in styleFrame. The shapes can be any of the shapes returned by the shape creation functions, and the shape array can include other style frames intermixed with the shapes. If a style frame is included in the shape array, it applies to all subsequent shapes in the array , until overridden by another style frame. A frame having one or more style attribute slots. If this frame is nil, the default style attributes are used. If any single attribute slot is not provided, the default for that attribute is used. See the DrawShape method in the next section for a description of the style attribute slots.

styleFrame

Note that the picture shape returned is the same as a Macintosh QuickDraw picture ( 'PICT' resource.)

9-8

Function Reference

CHAPTER

Drawing

MakeText MakeText (string, left, top, right, bottom) Creates and returns a text shape drawn within the specied rectangle. The font used for the text is specied as one of the style attributes in the DrawShape method. string left top right bottom The text string to be drawn The x-coordinate of the top-left corner of the texts enclosing rectangle The y-coordinate of the top-left corner of the texts enclosing rectangle The y-coordinate of the bottom-right corner of the texts enclosing rectangle The x-coordinate of the bottom-right corner of the texts enclosing rectangle

When drawn, the baseline of the text is placed at the bottom of the rectangle you specify as an argument to the DrawShape method. The text is clipped horizontally to the nearest letter boundary within the rectangle but it is not clipped vertically. The text is aligned to the left, right, or center of the rectangle you specify, as controlled by the justication style attribute (see the description of the DrawShape method for more details on style attributes that apply during drawing).

Shape Operations
These methods and global functions operate on shapes returned from the shape creation functions described in the previous section. You also can do hit testing on shapes using the HitShape method. This method is described in the chapter Written Input and Recognition.

Function Reference

9-9

CHAPTER

Drawing

DrawShape view:DrawShape (shape, styleFrame ) Draws the specied shape (or shapes) in the view using the style attributes given in styleFrame . shape Any of the shapes returned by the shape-creation functions, or an array of such shapes intermixed with optional style frames. If a style frame is included in the shape array, it applies to all subsequent shapes in the array, until overridden by another style frame. A frame having one or more of the style attribute slots listed here. If this frame is nil, the default style attributes are used. If any single attribute slot is not provided, the default value for that attribute is used. transferMode The drawing transfer mode for the pen (or for the text, if text is being drawn). Specify one of these standard constants: modeCopy, modeOr, modeXor, modeBic, modeNotCopy, modeNotOr, modeNotXor, modeNotBic. The default value is modeOr. These constants are described in the section viewTransferMode Slot in the chapter Views. penSize The size of the pen in pixels. You can specify a single integer to indicate a square pen of the specied size, or you can specify an array giving the pen width and height (e.g., [1, 2]). This style attribute is not used for drawing text. The default value is 1. penPattern The pen pattern. You can specify the following patterns: vfNone, vfWhite, vfLtGray, vfGray, vfDkGray, and vfBlack. The default value is vfBlack.

styleFrame

9-10

Function Reference

CHAPTER

Drawing

fillPattern The ll pattern. You can specify the same patterns as for the pen. This style attribute is not used for drawing text. The default value is vfNone. font The font to be used for drawing text. The default is the font selected by the user in the Styles palette (stored in the slot userConfiguration.userFont). justification The alignment of text in the rectangle specied for it. Specify one of the following symbols: 'left, 'right, 'center. The default value is 'left. You can use custom pen and ll patterns by setting the value of the penPattern and fillPattern slots to a binary data structure containing a custom pattern. A pattern is simply an eight-byte binary data structure with the class 'pattern. You can use this NewtonScript trick to create binary pattern data structures on the y: myPattern := SetClass(Clone("\uAAAAAAAAAAAAAAAA"),'pattern); This code clones a string, which is already a binary object, and changes its class to 'pattern. The string is specied using hex character codes whose binary representation is used to create the pattern. Each two-digit hex code creates one byte of the pattern. Note that style attributes dont apply when drawing shapes that are pictures. They are drawn as is. When drawing bitmaps, only the transferMode style attribute is used; the other attributes dont apply.

Function Reference

9-11

CHAPTER

Drawing

OffsetShape OffsetShape (shape, deltaH, deltaV ) Returns the shape with its bounds offset from the original bounds as specied. shape deltaH deltaV The shape to be offset The horizontal amount by which the specied shape is to be offset from its original bounds The vertical amount by which the specied shape is to be offset from its original bounds

horizontal amount deltaH and the vertical amount deltaV. You can specify an array of shapes for shape and in this, each shape in the array will be offset. This function is destructive to the shape you pass it; that is, it modies and returns that shape. ScaleShape ScaleShape (shape, srcRect, dstRect) Enlarges or reduces one or more shapes from the size specied by the rectangle srcRect to the size specied by the rectangle dstRect and returns the scaled shape(s). This function is destructive to the shape argument; that is, it modies and returns its value. shape srcRect A shape or array of shapes to be scaled A view bounds frame dening a rectangle that encloses the shape at its original size. The frame has the slots left, top, right, bottom. If this frame is nil, the shapes original bounds are used as the source rectangle, effectively scaling the shape from its current size to the size of the destination rectangle. A view bounds frame dening a rectangle that encloses the shape at its modied size. The frame has the slots left, top, right, bottom.

dstRect

9-12

Function Reference

CHAPTER

Drawing

Note

If the widths and heights of the source and destination rectangles are not proportionate, the returned shape is distorted to t exactly within the destination rectangle, even if this means that the width and height of the shape are scaled unequally. u ShapeBounds ShapeBounds (shape) shape A shape or array of shapes

Returns a bounds frame describing the rectangle that encloses the shape. The bounds frame has the following slots: left, top, right, bottom. You can specify an array of shapes for shape, and in this case, this function returns the rectangle that encloses the entire group of shapes.

Other Drawing Functions


This section describes additional drawing functions and methods. DoDrawing view:DoDrawing(drawMethodName ,parameters) Sets the clipping according to the setting of the vClipping ag for the specied view, sends the view the drawMethodName message, and restores the clipping to what it was before the drawMethodName method was called. drawMethodName parameters A method that performs drawing operations An array of parameters to pass to the drawMethodName method. Set the value of this argument to nil if the drawMethodName method accepts no arguments.

Function Reference

9-13

CHAPTER

Drawing

Note

If the views vClipping ag is not set, drawing is not clipped to the views bounds but to the view bounds of the hierarchically-closest parent view having its vClipping flag set. u The DoDrawing method ensures that any drawing done by the drawMethodName method does not overwrite other obscuring views (such as oating views that may be partially obscuring the view in which this method draws.) Using the DoDrawing method is the preferred way to do drawing other than in a views viewDrawScript method. CopyBits view:CopyBits(picture, x, y, mode) Draws a bitmap in the specied location using the specied transfer mode. picture a reference to the bitmap object to be drawn. You can use the compile-time function GetPictAsBits to create a bitmap from a 'PICT' resource; for more information, see the Using Resources appendix in Newton Toolkit User's Guide. The x-coordinate of the top-left corner of the bitmap The y-coordinate of the top-left corner of the bitmap One of the standard drawing transfer modes: modeCopy, modeOr, modeXor, modeBic, modeNotCopy, modeNotOr, modeNotXor, modeNotBic. If you pass nil for mode, the default, modeCopy, is used. These constants are described in the section viewTransferMode Slot in the chapter Views.

x y mode

9-14

Function Reference

CHAPTER

Drawing

DrawXBitmap DrawXBitmap(bounds,picture,index ,mode) Draws a single bitmap from the specied portion of a picture composed of horizontal rows of equal width bitmaps. bounds picture the size of the bitmap and the location in which it is to be drawn in the current view a reference to the bitmap object to be drawn. You can use the compile-time function GetPictAsBits to create a bitmap from a 'PICT' resource; for more information, see the Using Resources appendix in Newton Toolkit User's Guide. the index in the bitmap resource of the particular bitmap that is to be drawn One of the standard drawing transfer modes: modeCopy, modeOr, modeXor, modeBic, modeNotCopy, modeNotOr, modeNotXor, modeNotBic. These constants are described in the section viewTransferMode Slot in the chapter Views.

index mode

The width of each row in the picture bitmap is assumed to be the width as specied in the bounds parameter; thus, if you specify a width of 20 pixels and an index of 2, the chunk of picture beginning at pixel 40 and extending horizontally through pixel 59 will be extracted and drawn.

Function Reference

9-15

CHAPTER

Drawing

GetPictAsBits GetPictAsBits(nameString, maskToo) Retrieves the specied PICT resource by name from an open resource le, converts the PICT to a bitmap, and returns a frame containing a bitmap object and an optional mask. nameString maskToo A string specifying the name of the resource to be retrieved. A Boolean value indicating whether to construct a mask for the bitmap. (A mask is a solid black bitmap whose outline usually follows the outline of the original image.) If the value of this parameter is True, this function automatically constructs a mask for the bitmap and returns it with the bitmap. If you specify Nil, this function searches for another resource having the name specied in nameString with an exclamation point at the end; that resource is assumed to be the mask. If the value of the maskToo parameter is Nil and no such resource is found, no mask is returned.

The bitmap object returned by this function is a frame with the following slots: bits bounds A reference to a binary object containing the bitmap data A bounds frame specifying the dimensions of the bitmap; for example, {left: 0, top: 0, right: bitmapWidth, bottom: bitmapHeight} mask This slot is included only if a mask has been constructed or supplied. It contains a reference to a binary object containing the mask bitmap.

Note

This function is available at compile-time only. For more information, see Newton Toolkit User's Guide. u 9-16

Function Reference

CHAPTER

Drawing

view:LockScreen view:LockScreen(lock) Prevents the screen from updating or reverses the effect of a previous call to the LockScreen method. lock A Boolean value; when set to true, the screen is locked and no updates can occur. To unlock the screen, call the LockScreen method again with lock set to nil.When the screen in unlocked, it forces an immediate screen update.

Normally, all drawing occurs in offscreen memory and the system periodically updates the screen bits from the offscreen memory. This function prevents the copying of bits to update the screen. This allows you to make drawing calls, or erase and redraw things without an accompanying icker if the screen would happen to update during your drawing sequence. When you are done drawing, call LockScreen(nil) to unlock the screen and force an immediate update. Heres how you would typically use LockScreen: ... :lockscreen(TRUE); :dodrawing(myDrawer, nil) :lockscreen(nil); ...
Note

The system automatically calls LockScreen before sending a view the viewDrawScript message, and unlocks the screen afterwards. So you dont have to call LockScreen in your viewDrawScript method, only when you want to draw at some other time. u

Function Reference

9-17

CHAPTER

10

Working With Sound

Currently, Newton devices play only sampled sounds; sound synthesis is not supported. The Newton ROM supplies a number of built-in sounds that you can use in your application. You can also use Newton Toolkit to create custom sounds from Macintosh-style sound resource les. You can easily associate any sound with a system event, or play sound on demand. The system allows you to play sound synchronously or asynchronously. This chapter describes how to use sound in your application and describes how to manipulate Newton sound frames to produce pitch shifting and other effects.

Event-related Sounds
Views can play sounds to accompany various events. For example, the system plays certain sounds to accompany user actions such as opening the Extras drawer, scrolling the notepad, and so forth.

Event-related Sounds

10-1

CHAPTER

10

Working With Sound

Sounds in ROM
The system provides in ROM a number of sounds that are played to accompany various events; these sounds are referenced by the following constants. ROM_alarmwakeup The sound played when the Newton powers on automatically to display an alarm ROM_bootsound ROM_click ROM_crumple The sound played when the Newton is powered on The sound played when the user taps on items such as buttons and close boxes The rst sound played when deleting an item from the Notepad; it accompanies an animated simulation of the note being wadded into a ball The sound played as the Extras drawer closes ROM_draweropen The sound played as the Extras drawer opens ROM_flip ROM_funbeep ROM_hilitesound The sound played to indicate to the user that the Newton device is in highlight mode, rather than inking mode. This sound plays when the user presses the stylus against the screen continuously; it is accompanied by the display of the highlighting mark. ROM_plinkbeep The Xylo sound in the user preferences Sound panel. The sound played when turning pages in a Book Maker book The Trill sound in the user preferences Sound panel

ROM_drawerclose

ROM_simplebeep The Bell sound in the user preferences Sound panel.

10-2

Event-related Sounds

CHAPTER

10

Working With Sound

ROM_wakeupbeep The sound played when the Newton is powered on. ROM_plunk The second sound played when deleting an item from the Notepad; it depicts the sound of the crumpled note hitting the Trash. The sound played when an item is scrubbed; it accompanies the animated cloud that depicts the item going up in smoke.

ROM_poof

Sounds for Predened Events


All views recognize a small set of predened slot names that can be used to specify sounds to accompany certain system events.To accompany one of these events with a ROM-based sound, simply store the name the ROM-based sound in the appropriate view slot. The following predened slots can be included in views to play event-related sounds: showSound hideSound scrollUpSound scrollDownSound This sound is played when the view receives a viewScrollDownScript message. For example, to play one of the sounds in ROM when the view opens, place its name in the views showSound slot. Actually, all of the ROM_soundName constants are pointers to Newton sound frames stored in ROM. Instead of using one of these constants you can store a Newton sound frame in any of these slots, causing the sound stored in that frame to be played in accompaniment to the event associated with that slot. The next section describes the format of a Newton sound frame. This sound is played when the view is shown. This sound is played when the view is hidden. This sound is played when the view receives a viewScrollUpScript message.

Event-related Sounds

10-3

CHAPTER

10

Working With Sound

The Sound Frame


A Newton sound frame stores binary data and some additional information used internally by the system. Like any other frame, a sound frame cannot be greater than 32KB in size. The sound frame has the following slots. sndFrameType Species the format of this sound frame. Currently, Newton sound frames always have the symbol 'simpleSound in this slot; future Newton devices may store other values here. A frame of class 'samples containing the binary sound data. The sound data must have been sampled at 11Khz or 22KHz. A oating-point value specifying the rate at which the sample data is to be played back Currently, the value of this slot is always k8bit, indicating 8-bit samples. Currently, the value of this slot is always kNone, indicating no compression.

samples

samplingRate dataType compressionType

Creating Sound Frames Procedurally


Youll usually need to create a copy of any sound frame you wish to modify. Obviously, you cannot modify sound frames in ROM, so you would need to copy them in order to modify the binary sample data for one of these sounds. In many cases, the same restriction applies to the binary data in a sound frame returned by the GetSound or GetSound11 functions. The samples slot in a sound frame as returned by the functions GetSound or GetSound11 does not contain the binary sample data itself. It actually contains a pointer to this data in your application package. You cannot write

10-4

The Sound Frame

CHAPTER

10

Working With Sound

to this slot because in doing so you are actually trying to write to read-only package data. Do not do this; it wastes your time and annoys the ROM. Cloning the original version of a sound frame you need to modify also allows you to reset values to their original state expediently and provides a means of recovering the original sound frame easily if an operation fails.

Cloning Sound Frames


You can use the Clone function to make a modiable copy of the sound frame by simply passing the frame or its reference to Clone and saving the result in a variable, as in the following example. clonedSound := clone(ROM_simpleBeep); This is an extremely efcient means of creating a modiable sound frame because the copy created is a shallow clone; that is, the cloned frame clonedSound does not actually store a copy of the ROM_simpleBeep binary data. Instead, the clonedSound frame stores a pointer to the ROM data in its samples slot. Thus, the clonedSound frame is fairly lightweight in terms of overhead in the NewtonScript heap.

Creating and Using Custom Sound Frames


The compile-time functions GetSound and GetSound11 allow you to use Newton ToolKit to create Newton sound frames from Macintosh 'snd ' resource data. This section summarizes the main steps required to create custom sound frames from Macintosh 'snd ' resources in NTK; for a complete discussion of this material, see Newton Toolkit Users Guide. Take the following steps to add a custom sound to your application. 1. Include the sound resource le in your applications NTK project. 2. In your application, create an evaluate slot used to reference the sound frame through a compile-time variable.

The Sound Frame

10-5

CHAPTER

10

Working With Sound

3. In your Project Data le, n Open the sound resource le using the functions OpenResFile or OpenResFileX. n If using OpenResFileX, store the le reference it returns. n Use the functions GetSound11 or GetSound to obtain the sound frame. n Use a compile-time variable to store the sound frame returned by GetSound or GetSound11. n Use the function CloseResFile or CloseResFileX, as appropriate, to close the sound resource le; if you use the CloseResFileX function, you need to pass as its argument the saved le reference originally returned by OpenResFileX. 4. In your application, n Set the value of the evaluate slot to the name of the compile-time variable that stores the sound frame. n Pass the name of the evaluate slot as the argument to the PlaySound or PlaySoundSync function. These run time functions play sound from anywhere in your code; they are discussed in the next section.

Playing Sounds on Demand


You can use the functions PlaySound and PlaySoundSync to play sound on demand. For example, you might want to play a sound when the user taps a button, or when a lengthy operation is complete. Sounds can be played synchronously or asynchronously, as described in the following section.

Synchronous and Asynchronous Sound


When a sound is played synchronously, the system waits for it to nish playing before beginning another task; when a sound is played asynchronously the playback can be interrupted because the system does not wait for the sound to nish playing before beginning another task (such as playing a different sound.)

10-6

Playing Sounds on Demand

CHAPTER

10

Working With Sound

When playback must be allowed to complete, use the PlaySoundSync function to guarantee uninterrupted playback. Synchronous playback is generally preferred unless the sound is so long as to be tedious or the application requires a high degree of responsiveness to the user. The processor can do nothing else until it completes synchronous playback. When using the PlaySound function to play a sound asynchronously, your application can call the sound chip before it nishes playing the current sound, which is useful for applications that must respond instantly to user input. For example, an application providing verbal instructions to the user may want to play them asynchronously to allow the user to cancel them at any point. Asynchronous sound can be also used to create interesting effects, such as playing a sample repeatedly to create a stuttering or echo-like effect. Both approaches have benets and drawbacks: synchronous playback can tie up the processor when its inconvenient to do so; on the other hand, asynchronous playback is never guaranteed to complete. Your use of synchronous or asynchronous sound playback depends on your applications needs.

Hearing Is Believing
The following code example demonstrates the difference between asynchronous playback and synchronous playback. To hear the demonstration of the two types of sound playback, type following code example into the Inspector as it is shown here, select all of these lines, and press Enter. print ("Synchronous sound demo"); call func() begin for i := 0 to 20 do PlaySoundSync(ROM_simplebeep); end with(); print ("Async sound demo"); call func() begin for i := 0 to 20 do PlaySound(ROM_simplebeep); end with();

Playing Sounds on Demand

10-7

CHAPTER

10

Working With Sound

The synchronous sound playback example plays the rom_simplebeep sound twenty times; each time the sound is allowed to play its entire length. Twenty times may seem a bit laborious until you hear how quickly the same calls are made in asynchronous mode. Note that the asynchronous version is able to call the sound chip fast enough that the sound does not have enough time to nish playing; as a result, part of the playback is clipped off with each new call to the PlaySound function. In fact, its likely that you wont hear twenty sounds in the asynchronous playback demo; the calls come faster than the sound chip in the MessagePad is able to respond to themwhich brings up an interesting point about the sound chip in the MessagePad.

About the Sound Chip


The sound chip in the MessagePad requires about 50 milliseconds to load a sound and begin playing it. It also requires about 50 milliseconds to clear its registers and ready itself for the next call after playback completes. Although most applications are not affected by this timing information, it is included for those developers that are interested, along with the following caution.
Note

Do not rely on the ramp-up and ramp-down times specied here; they may change in future Newton devices. u

Sounds Like Fun


This section describes advanced techniques for manipulating the sound frame or its playback. The topics discussed include pitch shifting and manipulating sample data to produce altered sounds.

10-8

Sounds Like Fun

CHAPTER

10

Working With Sound

Pitch Shifting
This section describes how to shift a sounds pitch by altering the value of the sound frames samplingRate slot. Remember when setting this slot that samplingRate must be a value of type float. You can experiment with pitch shifting by playing sounds in the Inspector using either the PlaySound or PlaySoundSync functions. You can use any of the ROM sounds or you can use your own custom sounds. // keep a copy of original for future use origSound := clone(ROM_simpleBeep); // make a copy to modify mySound := Clone(origSound); // play the original sound PlaySoundSync(mySound); // play at half original pitch mySound.samplingRate := origSound.samplingRate/2; PlaySoundSync(mySound); // note how easily we can return to normal pitch mySound.samplingRate := origSound.samplingRate // play at twice speed mySound.samplingRate := origSound.samplingRate*2; PlaySoundSync(mySound); By using the output from a control view to alter the value of the sound frames samplingRate slot, you can allow the user to interactively modify the pitch of playback. The following example code, taken from the PIEDTS

Sounds Like Fun

10-9

CHAPTER

10

Working With Sound

sample Heavy Metal Disco., changes the value of the samplingRate slot according to the setting of a protoSlider view. theSlider.changedSlider := func()begin if viewValue = maxValue then mySound.samplingRate := originalRate else mySound.samplingRate := (viewValue*1.01); PlaySound(mySound); end For an example that uses output from a view based on the protoKeypad prototype, see the PIEDTS sample Bitchin Piano.

Manipulating Sample Data


This section describes how to use the utility functions ExtractByte and StuffByte to manipulate individual bytes in sound sample data. Due to performance considerations, youll only want to manipulate sample data on the Newton when its absolutely necessaryeven simple operations like the example here can take a long time to perform on a relatively small sound sample. The following example, taken from the PIEDTS sample SoundTricks, extracts bytes from the end of the sample data and adds them to its beginning, thus reassembling the samples in reverse order to create a backwards sound. s WARNING The destination object into which you stuff bytes using the StuffByte function must be large enough to hold all the data you are placing in it or youll overwrite other items in memory, corrupting the NewtonScript heap. s // backWardSound is a slot in the apps base view // if its nil then create the backward sound if (not backWardSound) then

10-10

Sounds Like Fun

CHAPTER

10

Working With Sound

begin // get a frame to work with backwardSound := deepclone(ROM_funbeep); // a var to store the modified sample data local sampleHolder := Clone(backwardsound.samples); local theSize := Length(sampleHolder) -1 ; // Copy bytes from one end of the binary object // to the other. for i := 0 to theSize do StuffByte(backwardSound.samples,i, ExtractByte(sampleHolder,theSize-i)); end; The code in this example executes in the applications viewSetupFormScript method; as a result, the SoundTricks application takes an unacceptably long time to open. A better solution is to provide the backwards sound as a resource that can be played just like any other sound; there are a number of Macintosh sound editors available that you might use to create such a resource.

Function Reference
The following global functions play sounds or allow you to get and set the playback volume. GetVolume GetVolume() Returns the current volume setting for sounds. This will be an integer from zero to 4.

Function Reference

10-11

CHAPTER

10

Working With Sound

PlaySound PlaySound(soundFrameRef) Plays a sound dened by the specied sound frame. The sound is played asynchronously; that is, this function returns immediately and the sound is played as a background process. This function always returns TRUE. soundFrameRef The sound frame to be played

A sound frame has the following slots: sndFrameType Species the format of this sound frame. Currently, Newton sound frames always have the symbol 'simpleSound in this slot; future Newton devices may store other values here. A frame of class 'samples containing the binary sound data. The sound data must have been sampled at 11Khz or 22KHz. A oating-point value specifying the rate at which the sample data is to be played back Currently, the value of this slot is always k8bit, indicating 8-bit samples. Currently, the value of this slot is always kNone, indicating no compression. PlaySoundSync PlaySoundSync(soundFrameRef) Plays a sound dened by the specied sound frame (see PlaySound). The sound is played synchronously; that is, the Newton stops everything it's doing, plays the sound, and then this function returns. This function always returns TRUE. soundFrameRef The sound frame to be played

samples

samplingRate dataType compressionType

10-12

Function Reference

CHAPTER

10

Working With Sound

A sound frame has the following slots: sndFrameType Species the format of this sound frame. Currently, Newton sound frames always have the symbol 'simpleSound in this slot; future Newton devices may store other values here. A frame of class 'samples containing the binary sound data. The sound data must have been sampled at 11Khz or 22KHz. A oating-point value specifying the rate at which the sample data is to be played back Currently, the value of this slot is always k8bit, indicating 8-bit samples. Currently, the value of this slot is always kNone, indicating no compression. SetVolume SetVolume() Sets the volume for sounds. You should specify an integer from zero to 4, where zero means off and 4 is the highest volume level. The default level is 4. This function always returns NIL. volume The level at which sound is to be played

samples

samplingRate dataType compressionType

Methods
The functions listed in this section are methods of the root view; hence, to invoke one of these functions youll want to send the message to the root view by prexing the method call with GetRoot():

Function Reference

10-13

CHAPTER

10

Working With Sound

For example, to use the Dial function, you would write code that looks like the following example. GetRoot():Dial(555-1212, modem) :Dial Dial(numberString,where) Dials the specied telephone number through the speaker or modem. This function always returns TRUE. numberString A string specifying the number to dial. The string can also include the following special characters: the letters A through D and the characters, * and # generate special tones when dialing; the dash (-) character inserts a delay of 50 milliseconds when dialing; and the comma (,) character inserts a delay of 500 msecs when dialing. A symbol, either 'speaker or 'modem, specifying whether to dial through the speaker or modem, respectively.

where

10-14

Function Reference

CHAPTER

11

The Intelligent Assistant

The Intelligent Assistant (IA) is a system service that attempts to complete actions for the user according to deductions it makes about the task that the user is currently performing. The Assistant is always instantly available to the user, yet remains non-intrusive. It can be thought of as an alternate interface to Newton that allows the user to invoke services uidly, according to current context. The Assistant knows how to complete several built-in tasks; they are Scheduling (adding meetings), Finding, Reminding (adding Todo items), Mailing, Faxing, Printing, Calling, and getting time information from the WorldClock. This chapter describes how you can add IA support to your application. It discusses the capabilities and limitations of the Assistant, summarizes the IA architecture, and dissects a typical code example. The chapter concludes with a summary list of steps one must take to implement IA support in a Newton application.

11-1

CHAPTER

11

The Intelligent Assistant

Human Interface to the Assistant


When the user taps the Assist button, the Assistant attempts to complete a task specied by the user. If the Assistant does not have sufcient information to complete an action, it attempts to ll in the missing information according to deductions it makes using the current context. If necessary, the Assistant prompts the user to clarify ambiguities by choosing items from the Assist pop-up menu or by writing one of several synonyms that the Assistant understands. For example, the Assistant invokes the Find task if the user writes any of these phrases: nd, nd it, locate, or locate it.

Intelligent Assistance vs. Online Help


This section describes concepts central to the design of various help systems and discusses these concepts in the context of services provided by the Assistant. Simply stated, this section attempts to describe what the Assistant is and what it is not:
n

The Assistant provides context-sensitive online help and active navigation of the Newton user interface. IA is not AI (articial intelligence).

A rudimentary online help system provides information in response to a user queryan example of this kind of system would be the online help provided by the UNIX system in the form of manpages, or various other online programmers references like the 411 or THINK Reference tools used by Macintosh programmers. These systems respond to a query but are not, strictly speaking, context-sensitive; that is, they make no inferences about the information to be retrieved. These help systems are also intrusive; that is, they intrude upon the user s primary task by requiring that the user or the development environment change context. Most of them require the user to focus attention elsewhere and some of them just stream text into the current insertion point without regard to content that may be displaced by the display of help text. 11-2

Human Interface to the Assistant

CHAPTER

11

The Intelligent Assistant

A better approach that is still somewhat intrusive involves the activation of a different environment (such as a help window, application, desk accessory or even a command line) in which to display information. The online help facility in Newtonwhich is distinct from the Assistantadopts this approach, providing in the Assist drawer a button which the user can tap to obtain various help screens, such as the one shown in Figure 11-1.

Figure 11-1

A typical online help screen in Newton

The Balloon Help feature provided on Macintosh in System 7 is an example of non-intrusive context-sensitive help. When Balloon Help is enabled, the help text displayed to the user changes according to the location of the mouse pointer on the screen; thus it is sensitive, in a rudimentary way, to the users current focus (or context.) The help is non-intrusive because it does not change the users context; that is, the help facility neither alters the user s data nor requires the activation of a dedicated environment such as a special help window. As wonderful as context-sensitive help may be, it is still passive, relying on the user to complete the task after reading the help information. The Newton

Human Interface to the Assistant

11-3

CHAPTER

11

The Intelligent Assistant

Assistant, on the other hand, provides active assistanceit not only invokes the appropriate service for the user (active navigation), it actually attempts to complete the task for the user, if asked to do so. When implemented correctly, this assistance is non-intrusivethat is, the Assistant does not rush off and perform a task unless you tell it to do so. Finally, the assistance provided is context-sensitive: all the user need do to invoke appropriate assistance is tap the Assist button. If it can determine enough information about the users intended task, the Assistant opens the appropriate application (and may even complete the intended task) without any further input from the user. In its present incarnation, the Assistant can only perform tasks that you, the developer, program it to perform; it does not learn in any sense of the word, as an articial intelligence system might. (It will never lock the pod bay doors against your wishes, Dave.) In fact, the Assistant can only recognize verbs that your application explicitly registers with it; thus, at the moment the user cannot tell the phone dialer in Newton to buzz someone, despite the fact that it knows how to phone them, call them, and dial them.

IA From the User s Perspective


Depending on the amount of information the user has provided at the time the Assistant is invoked, a variety of scenarios may be played out. This section describes how the Assistant reacts in various situations. When the user taps the Assist button, Newton passes the current selection to the Assistant, which attempts to determine what the user wants to do. If the user has fully specied the actions Newton is to perform, the Assistant either completes the task or displays an optional task slip before taking further action. A sample task slip is shown in Figure 11-2. The task slip is one means by which the Assistant resolves ambiguityfor example, the user can correct the task slip if the Assistant chooses the wrong Bob from the Names soup, or the user can write Bobs fax number on the slip

11-4

IA From the Users Perspective

CHAPTER

11

The Intelligent Assistant

Figure 11-2

The task slip

if the number was not found. The task slips other main purpose is to provide the user with one last chance to conrm or dismiss execution of the task before the Assistant actually takes action. As you might have guessed, not every situation in which the Assistant is invoked proceeds directly to the execution of the task! For example, many tasks require prerequisite information, such as a fax number; the Assistant has enough intelligence to nd this number if it is present, and to query the user if the number is unavailable. If there is more than one Bob in the phone book, the Assistant makes a useful initial guess about which Bob is the intended recipient of the fax, and provide a means for the user to change the recipient if that initial guess is incorrect. The next section explores the means by which the Assistant queries the user for further information when the task is not fully specied.

Get My Drift, Newt?


If the Assistant cannot fully determine the user s intentionsfor example, if the user tapped Assist without having selected anything on the Newton notepad, or the Assistant was unable to recognize the selectionNewton displays the Please dialog box. Figure 11-3 shows the Please dialog box as it would appear if the user had selected the phrase fax bob on the Newton notepad before tapping Assist. Note in the gure that each word in the phrase returned from the handwriting recognizer has been capitalized.

IA From the Users Perspective

11-5

CHAPTER

11

The Intelligent Assistant

Figure 11-3

The Please dialog box

If the user taps Assist without having selected anything on the Newton notepad, the Please dialog box appears with no text present on the label entry input line; the user can then write text here, which is recognized and returned to the label entry input line as Roman text. After the handwriting recognizer converts the user input to a text string, the Assistant parses this string, separating the words it recognizes from those it does not. For now, let us assume that the Assistant recognizes the word Fax as an action to perform and recognizes the word Bob as the entity towards which that action is directed. However, if the selected phrase is Call for Bob at work, the Assistant has a slightly different problem: while the words call, Bob, and work are probably all dealt with easily enough, the words for and at are really of no direct use to the Assistant. If the user is to enjoy natural interaction with Newton, rather than being limited to terse commands such as Call Bob Apple, the Assistant must also be able to separate noise words from words that it actually recognizes. Rather than becoming confused every time it parses a word it does not understand, the Assistant simply places all words that are not meaningful to it in the category of noise words, and ignores them. The services provided by the Assistant are independent of the ordering of words in the phrase for example, the user input phrase Bob fax provides the same assistance as the phrase Fax Bob. This syntax-independent architecture makes it easier to localize IA support in Newton applications for international audiences. The next section explains in detail how the Assistant works, and how you can add intelligent assistance to your application.

11-6

IA From the Users Perspective

CHAPTER

11

The Intelligent Assistant

Programmers Guide to the Assistant


At this point, you have been introduced to most of the salient concepts involved in providing intelligent assistance. This section exposes more of the code-level detail underlying the Assistant, including the frames, templates and mechanisms used to implement intelligent assistance in a Newton application.

Architectural Overview
An application makes a service available through the Assistant by registering a task template that denes the service to the Assistant. A task template species the actions to be performed and includes slots in which to store information required to complete the task (such as a fax number), synonyms for invoking the task (so that the task is invoked whether the user says phone Bob or call Bob), a task slip view to display to the user, and specic instructions (scripts or functions) for executing the task. When your application package is loaded, it calls the NewtonScript function regTaskTemplate() to register your task template with the Assistant; when your package is removed, it calls unRegTaskTemplate() to remove its task template. The main service that a task template denes is called the primary action; executing the primary action may require the completion of several subtasks. For example, if you instruct the Assistant to call Bob, it must nd Bobs phone number, obtain a dial tone, and dial the number. In this example, the primary action might be dened as call_act, and the execution of call_act would require the completion of the subtasks find_number, open_connection, and dial_number. The task template relies upon other templates that dene actions and potential targets of those actions. These templates are called the action template and the target template, respectively. You always need to dene one or more action templates when specifying a new task to the Assistant;

Programmers Guide to the Assistant

11-7

CHAPTER

11

The Intelligent Assistant

however, you may not necessarily need to dene a target template, as the system predenes a number of these for you. The Assistant provides predened target templates for specifying people, places, times, dates, phone numbers, and various numeric values. Thus, the tasks find_number, open_connection, and dial_number from this example might each be dened by a custom action template, while Bob, on the other hand, can be represented by the predened target template who_obj. Each action or target template contains a lexicon, which species a list of words or phrases that the Assistant is to associate with the template. For example, the lexicon for a template dening the act of making a phone call might include the words call, dial, and phone, meaning that this template is used whether the Assistant is asked to call Bob, dial Bob, or phone Bob. When the user requests assistance, the Assistant invokes the NewtonScript function parseUtter(), passing to it the phrase that the user entered on the Newton screen. The parseUtter function attempts to match words and phrases with items in each action or object templates lexicon slot. Each word or phrase matching a lexicon entry causes the Assistant to create a frame using the template that was matched. Frames created from action templates are called action frames; similarly, frames created from target templates are called target frames. At this point, the Assistant has parsed the user input and created a number of data structures, but has not yet determined which task it is trying to complete. The task is selected by matching one of the action frames returned by parseUtter() with the primary action slot in one of the task templates registered with the Assistant. The Assistant then uses the task template that was matched to create a frame (the task frame) in which it stores all of the information dened in the template, as well as all of the frames created by parseUtter(). Note that if the Assistant is unable to match an action template, it tries to determine which task template to use based on the information it does recognize. For example, if the user enters the phrase buzz 555-1234, the Assistant would not recognize the word buzz as an action for which it has a template, but would display the call template based on its recognition of 555-1234 as having the format of a telephone number.

11-8

Programmers Guide to the Assistant

CHAPTER

11

The Intelligent Assistant

Recall that in addition to dening a name for the primary action, the task template species all of the information required to complete it. The task template denes two slots, called signature and preconditions, which are used to specify and store this information. Each of these slots denes an array having elements that correspond to their ordinal counterpart in the other slots array; in other words, the rst element of the signature array is related to the rst element in the preconditions array, the second element in the signature array is related to the second element in the preconditions array, and so on. For each item required to complete the primary action, these parallel arrays dene the name of the slot and the type of object stored in that slot on a per-element basis. For example, the code fragment below denes the signature and preconditions arrays in the built-in task template for faxing. signature: [fax_action, fax_number, who_obj, when_obj], preconditions: ['action, 'number, 'recipient, 'when] For each frame that parseUtter function creates, it looks up the object type in the signature array, notes the index of that element, and creates a slot named for the symbol stored at the corresponding index in the preconditions array. For example, if the Assistant nds Bob in the Names soup it returns a who_obj that represents Bob. Because the who_obj type is stored as the second element in the signature array, the second element of the preconditions array is used to name the slot created to store the Bob object in the task frame. Thus, parseUtter() creates a slot named recipient in which it stores the who_obj representing Bob. As the Assistant continues to parse user data, it creates the appropriate frames and slots. Slots and frames are not created for elements of the signature array that were not matched. As you can see, the parseUtter function really is the heart of the Assistant. Besides parsing the user data, performing lexical matching of words and phrases, creating frames that represent actions and targets, and creating slots in which to store these frames, the parseUtter function returns the parsed information in several other ways. The parseUtter function creates in the task frame the origphrase slot, storing in it the original user input phrase. The origphrase slot stores an

Programmers Guide to the Assistant

11-9

CHAPTER

11

The Intelligent Assistant

array of strings, each element of which is always an individual word from the user input phrase. The parseUtter function also creates the slots phrases and noisewords, each storing an array of strings derived from the original user input phrase. Each element of the array stored in the phrases slot consists of an item that the Assistant was able to match with an action or target template. These entries may be phrases themselves; under certain conditions, for example, the full name of the fax recipient (Bob Dobbs) may be stored as a single element in this array. The noisewords slot contains an array of words or phrases that the Assistant was unable to match. Because the parser breaks unmatched phrases on word delimiters such as spaces, tabs, and return characters, the elements of this array are always single words. Thus far, the Assistant has parsed user input into phrases signifying an action and the target of that action, while ignoring noise words. It uses the parsed information to ll out a task template containing all information necessary to execute the task. After its nished parsing the user data, the Assistant calls your postparse method. The postparse method, which you must dene, is where the Assistant hands control to your application. Your postparse method can ll out a task slip and display it to the user, or perform the task (if parseUtter has returned all required information), or use the slots returned in the task frame to parse for more information.

Structure of the Action Template


The action template denes to the Assistant a frame representing a single action such as call, pay, or remind. The completion of a complex task may require the use of several action templates, each dening a discrete task that is completed as part of the primary task. However, a modular structure such as this is not enforced by the Assistant; it is simply recommended as good programming practice. The Assistant currently maps a single word of user input to a single task template; whether the task represented by that template is structured modularly or monolithically is your decision.

11-10

Programmers Guide to the Assistant

CHAPTER

11

The Intelligent Assistant

The action template also stores a list of words or phrases, called the lexicon, that the Assistant uses to associate this template with words or phrases from user input.

Required Slots
Your action template must dene the slots value, isa, and lexicon. The value Slot The value slot is not used by this version of the Assistant; however, this slot is required for compatibility with future versions of the Assistant. For now, you can use this slot to store a comment string indicating the name of the template. The isa Slot The isa slot identies the object type of the frame created from this template. Templates for user-dened actions must store in this slot a value identifying this template as being an action dened by the user. The predened symbol 'dyna_user_action is acceptable, as would be the symbol for any template that is derived from a template having the value 'dyna_user_action in its isa slot. For example, you can dene a template my_action that is a dyna_user_action and use its symbol in this slot also, as in the following code fragment. my_action := { value: "my action", // comment identifying name of action isa: 'dyna_user_action, // use this class or a subclass lexicon: ["jump", "hop"] // words associated with this action };

Programmers Guide to the Assistant

11-11

CHAPTER

11

The Intelligent Assistant

Based on the denition above, you can derive another action template from my_action, and store the value 'my_action in its isa slot, as in the following example. my_other_action := { value: "my other action", // comment identifying name of action isa: 'my_action, // subclass of 'dyna_user_action lexicon: ["leap", "lunge"] // words associated with this action }; The single quotation mark prex( ') in the symbol is important; it species that the word following it is to be passed as a literal constant rather than interpreted for its current value. The lexicon Slot The lexicon slot stores an array of one or more words or phrases that are to be associated with this action template. Any item in the user input phrase that matches an element in this array is classied as an action, causing the Assistant to create a frame based on this template. The following example shows the lexicon slot from an action template in a checkbook application; this particular action template associates the phrases in its lexicon with the action of opening the checkbook application. Note that case is not signicant; that is, the phrase write check will match even though this phrase is capitalized differently in the lexicon. lexicon: ["Pay", "Paid", "Enter Check", "Write Check", "Wrote Check", "Cashed", "Cashed Check" ],

11-12

Programmers Guide to the Assistant

CHAPTER

11

The Intelligent Assistant

Sample Action Template


The following code fragment is an example of an action template that denes an action called cbPayAction that might be used to implement assistance for a checkbook application. cbPayAction := { value: "Pay Action", // comment identifying name of action isa: 'dyna_user_action, // use this class or a subclass lexicon: ["pay", "paid"] // words associated with this action };

Structure of the Target Template


The target template denes to the Assistant a frame representing the target of an action; targets are generally people, places or things. The target template also stores a list of words or phrases, called the lexicon, that the Assistant uses to associate the template with words or phrases from user input. The Assistant provides the following predened target templates: dyna_user_obj, who_obj, where_obj, what_obj, when_obj, phone_number, parsed_number. You use the dyna_user_obj template to dene new targets to the Assistant.

Required Slots
Your target template must dene the slots value and isa. The value Slot The value slot is not used by this version of the Assistant; however, this slot is required for compatibility with future versions of the Assistant. For now, you can use this slot to store a comment string indicating the name of the template.

Programmers Guide to the Assistant

11-13

CHAPTER

11

The Intelligent Assistant

The isa Slot The isa slot identies the object type of the frame created from this template. Templates for user-dened targets must store in this slot a value identifying this template as being an object dened by the user. The predened symbol 'dyna_user_obj is acceptable, as would be the symbol for any template that is derived from a template having the value 'dyna_user_obj in its isa slot. For example, you can dene a template my_target that is a dyna_user_obj and use its symbol in this slot also, as in the following code fragment. my_target := { value: "my target", // comment identifying name of target isa: 'dyna_user_obj, // use this class or a subclass }; Based on the denition above, you can derive another target template from my_target, and store the value 'my_target in its isa slot, as in the following example. my_other_target := { value: "my other target", // comment identifying name of action isa: 'my_target, // subclass of 'dyna_user_obj }; The single quotation mark prex( ') in the symbol is important; it species that the word following it is to be passed as a literal constant rather than interpreted for its current value.

The lexicon Slot (Optional)


The lexicon slot stores an array of one or more words or phrases that are to be associated with this target template. Any item in the user input phrase that matches an element in this array is classied as a target, causing the

11-14

Programmers Guide to the Assistant

CHAPTER

11

The Intelligent Assistant

Assistant to create a frame based on this template. Note that the lexicon slot is used only to match parsed input with user-dened objects. Because the Assistant does not use this slot when matching user input with predened target templates, the target templates that are predened for you by the Assistant do not contain a lexicon slot. The following example shows the lexicon slot from a typical target template; this particular template associates the phrases in its lexicon with a who_obj created to represent the person Bob Dobbs. Bob, as you can see, has a variety of nicknames. lexicon: ["Bob", "Bob Dobbs", "Robert", "The Bobmeister", "Bob-a-ree-bob", "Bobkat", "The Bobster", "Bob-a-saurus" ],

Sample Target Template


The following code fragment is an example of a target template that denes a target called cbPayee that might be used to implement assistance for a checkbook application. cbPayee := { value: "Who Object",// comment identifying name of target isa: 'dyna_user_obj, // you must use this value! lexicon: ["to", "Bob"]// words associated with this action ;

Structure of the Task Template


Most of the work involved in adding intelligent assistance to your application lies in dening the task template and its related action and object templates. As you know, the task template is used to register a new application service with the Assistant. An application service consists of an

Programmers Guide to the Assistant

11-15

CHAPTER

11

The Intelligent Assistant

action, such as call, pay, or remind, that is generally directed at a target, such as Bob or Apple. An action and its target are dened by an action template and a target template, respectively. The main service that the task template enables the Assistant to provide is called the primary action; executing the primary action may require the completion of several subtasks. While a modular structure is recommended as good programming practice, it is not enforced by the Assistant. In fact, the current version of the Assistant maps a single parsed phrase to a single task template; whether the task represented by that template is structured modularly or monolithically is your decision. For example, the act of telephoning someone can be thought of as a collection of constituent actions that include obtaining the correct phone number, obtaining an open telephone line, actually dialing the phone number, and determining whether the call was completed successfully. In such an example, the act of telephoning might be dened in the task template as the primary action call_act. This primary action would execute subtasks such as get_number, open_phone, dial_number, and determine_success, each of which might be dened by their own action templates. However, if you prefer to create a single huge task template and postparse task, you are free to do so, although, as previously stated, this is not recommended.

Required Slots
All task templates must dene four required slots: isa, primary_act, preconditions, and signature. The isa Slot The isa slot identies the object type of the frame created from this template. Task templates must store only the value 'task_template in this slot. You cannot use the symbol for another template derived from this one instead. The single quotation mark prex( ') is important; it species that the word following it is to be passed as a literal constant rather than interpreted for its current value.

11-16

Programmers Guide to the Assistant

CHAPTER

11

The Intelligent Assistant

The isa slot in your task template should look like the following example. isa: 'task_template, // must use this value only! The primary_act Slot Because the execution of a task may require the completion of several subordinate actions, the task template denes a primary action that invokes all of the subordinate actions necessary to actually complete the task. The Assist drawer represents the primary action as an item in the Let Me pop-up menu by displaying in that menu the rst value in this templates lexicon array. Your task template must store a reference to the primary action template in its primary_act slot. The primary_act slot in a task template for sending FAX messages looks like the following example. primary_act: fax_action, The preconditions Slot Your task template must dene the preconditions slot, which stores an array of symbols specifying the names of slots that the Assistant creates to store information required to complete the task (such as the fax number). preconditions: ['action, 'who, 'what, 'where] The preconditions array must have the same number of elements as the signature array because the Assistant uses these two arrays in parallel. For more details, see the section About the Preconditions and Signature Slots, later in this chapter. The signature Slot Your task template must dene the signature slot, which is a list of all possible frame classes that may be used to create frames stored in the task template. It is an array of one or more action templates followed by zero or more target templates.

Programmers Guide to the Assistant

11-17

CHAPTER

11

The Intelligent Assistant

The signature slot in a task template for sending FAX messages looks like the following example. signature: [fax_act, who_obj,form,where_obj], The signature array must have the same number of elements as the preconditions array because the Assistant uses these two arrays in parallel. For more details, see the section About the Preconditions and Signature Slots, later in this chapter. About the Preconditions and Signature Slots At rst glance, the signature and preconditions slots may seem very much alike. The key difference is that the preconditions slot stores symbols and the signature slot stores template names. After the user input phrase is parsed, individual words or phrases are identied as actions, targets, or noisewords. If an action or target matches a frame class stored in the signature, the appropriate template is used to create a frame, which is then stored in its own slot in the task frame. The slot is named for the symbol stored in the preconditions array at the same index as the element in the signature array matching the frames object type. For example, matching the word Bob in user input with the who_obj that is the second element of the signature array in the example below would cause the Assistant to create a slot named recipient in which to store the frame created from the who_obj template, because both who_obj and 'recipient are the second element in their respective arrays. signature: [fax_action, fax_number, who_obj, when_obj], preconditions: ['action, 'number, 'recipient, 'when] Note that the Assistant creates slots in the return frame only for elements in the signature that result in a match. Using the same example, if the when_obj was not matched, the when slot would not be created in the frame returned by parseUtter().

11-18

Programmers Guide to the Assistant

CHAPTER

11

The Intelligent Assistant

The postparse Slot The postparse slot stores a reference to an action template that is invoked after the Assistant parses the user input. Frequently, the task templates primary action is actually invoked by a postparse methodfor example, if the user asks to fax Bob and Newton cannot do so until the Assistant has retrieved Bobs fax number, the primary action of sending the fax would correctly be invoked after the parseUtter function returns the task frame. Another common use for the postparse method is to display a task slip view that provides the user with an opportunity to conrm, modify or dismiss the primary action before it is executed. A more detailed discussion of the postparse method follows in the section The Postparse Method,later in this chapter.

Optional Slots
Your task template may dene an optional taskslip slot, as well as any other slots that you require. The taskslip Slot The taskslip slot is used to reference views associated with the task template, the most common one being a task slip that displays information about the primary action for conrmation or editing by the user.

Returned Values
The Assistant also creates slots for frames that match any object types stored in the signature array; these slots are named according to the corresponding element in the preconditions array. For more information, see the section About the Preconditions and Signature Slots, earlier in this chapter. After parsing the user input, the Assistant returns values that are stored in the slots raw, phrases, noisewords, and origphrase; the remainder of this section discusses the values returned in these slots, which can be used by your postparse method to obtain further information about the phrase entered by the user.

Programmers Guide to the Assistant

11-19

CHAPTER

11

The Intelligent Assistant

The raw Slot The raw slot is used internally by the Assistant; it stores an array of phrase types and values returned from the parser. Each element of the array is itself a simple array, which lends great exibility to this data structure. This array may sometimes include as one of its elements the original unparsed user input phrase. In its simplest form, the rst and only element in the raw array is a symbol that species the name of the action template or target template that matched the phrase. For example, if the user enters the phrase fax Bob, the beginning of the raw array would look like the following example. raw: [ [fax_action], ... ], In the example above, the rst element in the array is the symbol 'fax_action. This symbol, predefined by the Newton object system, species to a postparse function that the action it is to take is that of sending a fax. You use action templates to dene symbols for your applications own actions. The raw array may also store a frame as an element. Exposing more of the original example below, you can see that the second element of the array is an array of class lex. The lex class denes an array useful for creating dictionary-like collections of tag/value pairs. raw: [ [fax_action], [lex: { isa: 'person}], ...],

The value of the lex array in this example is a framespecically, a target templatedescribing the kind of object the Assistant found when parsing the word Bob. The rst slot in the frame lex contains the symbol 'person, which evaluates to the predefined object template who_obj. The phrases Slot The phrases slot stores a simple array of strings returned by the parser. In the fax Bob example shown previously, each word in the raw phrase is stored as an element in the phrases array after it is tokenized; however, elements of this array can store more than a single word. For example, if the

11-20

Programmers Guide to the Assistant

CHAPTER

11

The Intelligent Assistant

parser searches the Names soup for an object of the type who_obj having the value Bob and nds an object of the specied type that has the name Bob Dobbs, the second element of the phrases array will store the entire string Bob Dobbs. The following example depicts typical phrases and raw arrays that might be returned after parsing the user phrase call Bob. raw: [[fax_action], [lex: { isa: 'person}], ...], phrases: ["Call", "Bob", ...], The noisewords Slot The noisewords slot stores a simple array of strings returned by the parser. These strings are individual words that the parser was unable to match with an action template or a target template. For example, when parsing the phrase Call to Bob, the word to would be stored in the noisewords array if it were not stored in any templates lexicon (resulting in no match). And if there were no entry for Bob in the Names soup, the word Bob would also be stored in this array. The following example depicts the noisewords array that would be returned after parsing the user phrase Call for Bob at Apple, when only the words for and at result in no match. noisewords: The origphrase Slot The origphrase slot stores the original user input phrase as a simple array of strings. Each element of this array is a single word from the user input phrase, and the words are stored in the order in which they appeared in the user input phrase. The origphrase slot that would be returned after parsing the phrase Call for Bob at Apple is depicted in the following example. origphrase:[Call, for, Bob, at, Apple] ["for", "at"],

Programmers Guide to the Assistant

11-21

CHAPTER

11

The Intelligent Assistant

The value Slot The value slot is an optional slot in which the Assistant stores formatted strings such as phone numbers, currency values and dates. The Assistant typically uses the value slot to return the results of a parse conducted using a lexical dictionary. Your postparse method can use the value slot for this purpose as well. An example describing the use of the value slot appears later in this chapter, in the section Parsing for Dollars (and Other Special-Format Objects).

Sample Task Template


The following code fragment is an example of a task template. This template might be used to implement assistance for a checkbook application. checkbook.payTemplate := { value: "Pay Template", // comment identifying this template isa: 'task_template, // you must use this value! primary_act: cbPayAction, // primary action postParse: checkbook.postParseScript, // reference to the postparse task signature: [cbPayAction, cbWho, cbAmount, cbWhen], // required object types preconditions: ['action, 'name, 'amount, 'when], // slotnames for storing signature objects score: nil // you must define this slot for Assistants use };

11-22

Programmers Guide to the Assistant

CHAPTER

11

The Intelligent Assistant

The Postparse Method


After the Assistant has stored all of the objects that were created when matching object types specied in the signature array of the task template, it invokes the postparse method. The postparse method commonly acts as a dispatching method that invokes the subtasks comprising the primary actionone such subtask might be the display of a task slip view to the user. The postparse method can also perform additional parsing (surprise!) to retrieve information that the Assistant was unable to nd on its own. For example, if the user input phrase is Call to Bob and the word Bob does not match any entries in the Names soup, the target of the action call is still unknown to the Assistant. However, because the word to appears in the call action templates lexicon, the postparse method can nd the word that appears after to in the original phrase and use it as the target of the action. Because this word, Bob, does not currently match an existing entry in the soup, the postparse method uses this information to ll out a task slip rather than to actually call Bob. After the user supplies the information missing from the task slip, the postparse method takes care of actually performing the primary action specied in the task frame.
IMPORTANT

Once your postparse method is invoked, it is in complete control of Newton. This means that your postparse method must include any code necessary to complete the primary action, such as that required to display a task slip, validate input, and handle errors. s

A Sample Postparse Method


The following code fragment is an example of a postparse method that tests for the existence of the value slot and accesses its content.

Programmers Guide to the Assistant

11-23

CHAPTER

11

The Intelligent Assistant

postParse: func() begin local index, thePhraseType, thePhraseText; for index := 0 to Length(raw)-1 do begin if ClassOf(raw[index]) = 'Array then begin thePhraseType := raw[index][0]; thePhraseText := phrases[index]; end; else if ClassOf(raw[index]) = 'lex then begin thePhraseType := raw[index][0].isa; if hasSlot(raw[index][0], 'value) then thePhraseText := raw[index][0].value; else thePhraseText := phrases[index]; end; // Display phrase text in the routing slip for this task. end; end;

A Parsing Example
When the user enters Call for Apple at work into the Assist drawer, the Assistant parses this phrase and nds the appropriate task template. The Assistant then continues parsing for the rest of the objects in the signature. Finally, the task templates postparse method is called to give it a chance to parse the objects or perform any other required activities, such as verifying the completeness of the information or displaying a task slip to the user. At

11-24

Programmers Guide to the Assistant

CHAPTER

11

The Intelligent Assistant

the time that the postparse method is called, the task template will have some new slots dened by the Assistant. These slots are: raw:[ [call_act], [company], [work_phone]], phrases: ["Call", "Apple", "work"], noisewords: ["for", "at"], origphrase: ["Call", "for", "Apple", "at", "work"], The code example immediately following illustrates the entire task frame (including new slots and their values) returned by the Assistant. {isa: {}, primary_act: {isa: {value: "action"}, lexicon: [["call", "phone", "ring", "dial"]]}, signature: [{isa: {value: "action"}, lexicon: [["call", "phone", "ring", "dial"]]}, {isa: {}}, {isa: {isa: {}}}, {isa: {isa: {}}, lexicon: ["phone number"]}], preconditions: [action, who, places, phone_number], taskslip: callslip, postparse: <CodeBlock, 0 args #2DF881>, score: NIL, parse: [frames: [frames: {isa: {value: "action"}, lexicon: [["call", "phone", "ring",

Programmers Guide to the Assistant

11-25

CHAPTER

11

The Intelligent Assistant

"dial"]]}], [frames: {isa: {isa: {isa: {}}}}], [frames: {isa: {isa: {isa: {}}, lexicon: ["phone number"]}, lexicon: [["work", "work phone"]]}]], input: [classes: {isa: {value: "action"}, lexicon: [["call", "phone", "ring", "dial"]]}, {isa: {isa: {isa: {}}}}, {isa: {isa: {isa: {}}, lexicon: ["phone number"]}, lexicon: [["work", "work phone"]]}], raw: [[call_act], [company], [work_phone]], phrases: ["Call", "Apple", "work"], noisewords: ["for", "at"], origphrase: ["Call", "for", "Apple", "at", "work"] action: [frames: [call_act]], places: [frames: [company]], phone_number: [frames: [work_phone]]}

Parsing for Dollars (and Other Special-Format Objects)


In all of the examples shown thus far, the Assistant stored the type of the phrase in the raw array and stored the phrase itself in the phrase array. Some objects, however, cannot be parsed for correctly without the use of a lexical

11-26

Programmers Guide to the Assistant

CHAPTER

11

The Intelligent Assistant

dictionary describing their format. These objects include formatted numbers such as phone numbers, currency values, dates, and times. When the Assistant uses a lexical dictionary to parse an object, it stores the parsed phrase as a single string in the value slot. For example, if the user had entered the phrase Call Bob at 343-4594 the Assistant would store the phone number in the value slot, as shown in the following example. raw: [[call_act] [lex:{isa: phone_number_obj, lexicon: ["phone number"]}, value: "343-4594"}] ], Note that the value slot is only created when the Assistant parses a special-format string.

Registering and Unregistering the Task Template


To make a new service available through the Assistant, you register its task template by calling the regTaskTemplate() function when your application package is loaded. When the task template is registered successfully, the value returned by regTaskTemplate is a reference to the instantiation of the template in RAM. If regTaskTemplate returns a NIL value, the attempt to register the template was unsuccessful. Assign the value returned by this function to a local variable, as shown in the following example; youll need it later, when you unregister the task template. result := regTaskTemplate(my_template); To remove the instance of your task template from RAM, call unRegTaskTemplate(result)when your package is unloaded.

Registering and Unregistering the Task Template

11-27

CHAPTER

11

The Intelligent Assistant

Thats it! The Assistant will invoke the primary action dened in your task template whenever it sees any of the words specied in the lexicon of the action template that denes the primary action.

Resolving Verb Conicts


Previous sections of this chapter discuss the resolution of ambiguities arising from an incomplete match of user input. For example, matching the word call without matching the word Bob in the user input phrase Call Bob results in the activation of the task template having call in its lexicon; the postparse task for this template must then display a task slip to query the user for additional information required to complete the task, such as Bobs phone number. Another situation requiring the Assistant to resolve ambiguity occurs when a verb matches more than one action template. Imagine that two games, Chess and Checkers, are currently loaded in the Extras drawer. If both games specify the word play in their action templates lexicon, the Assistant cannot open the correct application by simply matching this verb; the correct game to open must be determined by some other means. For example, the code fragment below shows the template for an action, play_act, that might conceivably be dened by both games. play_act := { value: "play action", isa: 'dyna_user_action, lexicon: [ "play" ] }; The task templates for each of these games might look like the following example. Note that both templates dene play_act as the primary action.

11-28

Resolving Verb Conicts

CHAPTER

11

The Intelligent Assistant

chessTemplate := { value: "Test Template", isa: 'task_template, primary_act: play_act, preconditions: ['generic_action,'action, 'game], signature: ['dyna_user_action, play_act, chess_obj], postparse: func() begin print("we made it, chess!"); end, score: NIL}, checkersTemplate := { value: "Test Template", isa: 'task_template, primary_act: play_act, preconditions: ['generic_action, 'action, 'game], signature: ['dyna_user_action, play_act, wacko_obj], postparse: func() begin print("we made it, wacko!"); end, score: NIL},

A Strategy for Resolving Verb Conicts


If you specify the 'dyna_user_action symbol as the rst element of your task templates signature slot, any target (noun) that distinguishes the template from another enables the Assistant to select the correct template. For example, the two target templates in the following code fragment represent the games Chess and Checkers, respectively. chess_obj := { value: "chess obj", isa: 'dyna_user_obj, lexicon: [ "chess" ] };

Resolving Verb Conicts

11-29

CHAPTER

11

The Intelligent Assistant

checkers_obj := {

value: "checkers obj", isa: 'dyna_user_obj, lexicon: [ "checkers" ] };

Note that the lexicons in these templates DO NOT match; this information allows the Assistant to resolve the ambiguity.

Adding Assistance to Your Application


Adding IA support to your application consists of dening the task template, adding code to register and unregister your task template with the Assistant, and writing any other custom procedures, such as a postparse method, that you need to execute in order to complete the task. You must also dene any custom action and target templates that your task template uses. It is recommended that you begin by dening the action and target templates required to complete the primary action. After doing so, you will have a better idea of the tasks your postparse method will need to handle. After dening the necessary templates and writing a suitable postparse method, you will nd the denition of the task template itself to be almost trivial.

Summary: Extending the Intelligent Assistant


You need to take the following steps to make a new service available through the Assistant.
n

Dene a task template for the service. In doing so, you may need to dene one or more custom action templates or object (target) templates. Create a postparse method. Register and unregister your task template with the Assistant at the appropriate times.

n n

11-30

Adding Assistance to Your Application

CHAPTER

12

Additional System Services

This chapter shows you how your application can take advantage of some of the other system services that Newton provides. Topics include:
n n n n n

Using the Find service to retrieve data Using the File service to store data Providing the capability to undo and redo user actions Using the Notication service to display messages to the user Using the system idle loop to perform periodic operations

Supporting these system services requires that your application provide data structures and routines described in this chapter. Each service may be supported independently of the others; for example, you can support Find without supporting Undo.

Find
The Find service searches one or all applications in the system for occurrences of a string that begins with a phrase specied by the user. Thus, nding the string smith would return the items smith and smithers, but not blacksmith. Figure 12-1 depicts the Find dialog box.

Find

12-1

CHAPTER

12

Additional System Services

Figure 12-1

The Find dialog box

Tapping the Find button causes the system to search only the frontmost application for the string; this operation is called a local nd. Tapping the All button causes the system to search all applications that are represented in an array called FindApps; this operation is called a global nd. The applications in FindApps need not be open; the system opens the application necessary to display an item when the user taps the item in the Find overview. The Find service also provides the capability to search for dates, rather than text. The user can choose items from a popup menu to qualify the search with a date stamp, requesting only data that has been time-stamped before or after a specied date. This menu is shown in Figure 12-2.

Figure 12-2

Specifying text or date searches

When the search is completed, the Find service displays an overview list of items found that matched the search criteria. Figure 12-3 depicts the Find overview as it might appear after searching all applications for the word Boston.

12-2

Find

CHAPTER

12

Additional System Services

Figure 12-3

The Find overview

Various external characteristics would seem to dene a particular Find operation as different from others: whether the search is global or local, and whether the search is for text or dates. From the programmers perspective, however, these different kinds of nd operations actually share many similarities. The programmer can consider a text nd and a date nd to be nearly identical, the only difference being the kind of test an item must pass to be included in the result of the search. And a global nd is simply a series of local nd operations initiated by the systemwhen the user taps the All button, the system executes a local nd in each application registered in the system-supplied FindApps array.

Find

12-3

CHAPTER

12

Additional System Services

In fact, the most important construct affecting a Find operation is not the scope of the search or the kind of data to be gathered. It is the manner in which your application stores data; specically, whether or not the data is stored in soups. Later in this chapter, the section Choosing a Finder Protodescribes how the data storage model used by your application directly inuences the manner in which you support Find operations. Once you have dened the frame that your application returns to the system Find service, your application need only supply two or three methods to support local Finds. Supporting global nds requires only a small amount of additional work. Because the different kinds of Find operations are so closely related, youll nd that supporting any one of them results in having added a good portion of the code required to support the others. Hence, the remainder of the Find section focuses rst on local text nds, introducing date nds as a special case, and then moves on to the topic of global nds.

Supporting Find In Your Application


To add Find capabilities to your application, you must implement a method that can search your applications data and return a frame containing the result of the search. This search method is always named either Find or DateFind; these methods must implement text and date searches, respectively. The frame returned by the search method is called the result frame. The system supplies a global function, StandardFind, that you can use to implement your applications Find method for soup-based text data. You cannot use StandardFind unless your result frame is based on the soupFinder proto. If you choose to support DateFind, you need to supply a DateFind method that can return from your application data those items meeting comparison criteria specied by the user. If your result frame is based on the soupFinder proto, you can use the system-supplied timeStamp slot to implement your date comparison function; otherwise, your application data needs to store its own time stamp information for use in implementing this comparison.

12-4

Find

CHAPTER

12

Additional System Services

The result frames _proto slot must reference one of the systemsupplied protos soupFinder or ROM_compatibleFinder. If you use the soupFinder proto, you need to supply a FindSoupExcerpt method that provides text strings used to identify items in the Find overview; if you use ROM_compatibleFinder, you need to handle some additional messages sent by the system. Later in this chapter, the section Choosing a Finder Proto discusses the characteristics of these protos. You must also supply a ShowFoundItems method that displays an individual item from the result frame; this method is invoked when the user taps on the item in the Find overview. The next section describes how these methods and protos work together to provide the Find service.

Programmers Overview of Find


When the user taps the Find button, the system invokes your applications search method, which scans your applications data and returns a frame containing the results of the search. The content of the frame returned by your applications search method varies according to the nder proto on which it is based; these protos are discussed later in this section. While the search is in progress, the system displays progress messages at the top of the Find dialog box; these messages use a string that you supply which species the name of your application. When the search method returns, the system displays to the user a list of items that were found. The strings identifying these items are extracted from result frames based on the soupFinder proto by a FindSoupExcerpt method that you supply. If you are using the ROM_compatibleFinder proto, you need to extract this information from your application data by other means, described later in this chapter. When the user taps on an element in the list, your applications ShowFoundItems method is invoked to display the item.

Find

12-5

CHAPTER

12

Additional System Services

Date Finds The only signicant difference between a date nd and a text nd is that a different search method is used to locate the items that are returned. Normally, the system sends the Find message to your application when the user taps the Find or All button in the Find dialog box. However, if the user chooses the dates before or dates after item from the popup menu in the Find dialog box, the system sends the DateFind message to your application when the user taps Find or All. Your DateFind method compares items in application data against a specied date string (rather than a text string.) Otherwise, text nds and date nds are essentially the same operation. Global Finds When the user taps the All button in the Find dialog box, the system sends the Find or DateFind message to each application registered in the system-supplied FindApps array. Thus, in terms of the messages sent, global nds are very similar to local nds; however, there are some differences in these operations that your application needs to address. The most important consideration is that your application may not be open when the system invokes its search method as part of a global nd. Therefore, you need to make sure the application soup is available by calling GetUnionSoup from within the body of your search method before actually searching for data. Another consideration is that the value of the scope parameter passed to your search method changes according to the scope of the search. The signicance of this value is completely implementation-specic; that is, you can choose to ignore it or modify your applications actions based on whether the value of this parameter is 'localFind or 'globalFind. Each application receiving the message conducts its own local search and appends its result frame to the results array. The structure of your result frame is based on the nder proto you use to create it; the choice of one nder proto over another is largely dictated by the format in which your application stores its data.

12-6

Find

CHAPTER

12

Additional System Services

Choosing a Finder Proto


The system supplies two nder protos, soupFinder and ROM_CompatibleFinder. Because the system supplies methods for querying soups and manipulating the results of the query, it is strongly recommended that you store your applications data in soups and use the soupFinder proto to support Find. Storing application data in soups allows you to conduct fast, reliable searches by querying the soup for cursors. In addition, youll be able to use the soup-manipulation methods supplied by the system. However, if your application does not store data as soup entries, you can use the ROM_compatibleFinder proto to support Find. Although ROM_compatibleFinder provides most of the services that soupFinder does, it does not respond to messages sent by the system when the user les, deletes, or moves items in the Find overview. If you use ROM_compatibleFinder, you will need to support these messages yourself. For more information, see the section Filing, later in this chapter. If you prefer not to use either of these protos, you can implement your own nder proto as described in the section Writing Your Own Finder Proto, later in this chapter. The nder proto is used to construct the result frame returned by your search method. The next several sections describe the interface and implementation of the search methods Find and DateFind.

Search Method Interfaces


As you know, your application conducts searches in response to Find and DateFind messages that it receives from the system. You must supply a search method for each message that your application supports. The system supplies a global function, StandardFind, that you can use to implement your applications Find method for soup-based text data. If you want to support date nds, you must implement your applications DateFind method yourself. This section describes the application program interface to the Find service.

Find

12-7

CHAPTER

12

Additional System Services

Interface to the Find Method


The system expects your applications Find method to look like the following example. Find: func(what, results, scope, statusContext ) begin . . . end The return value of this method is ignored; the results of the search are returned in the results parameter. what results contains the user-specied string for which Find is to search your applications data. an array of slots passed to your Find method by the system; your Find method appends a slot, myResult, to this array. The exact content of the myResult slot depends on the kind of nder proto used to create the frame returned by your search method; your search method stores this frame in myResult. If you used the soupFinder proto, the frame contains a cursor used to iterate over a list of entries returned by your search methods query on the application data soup. If you used the ROM_CompatibleFinder proto, the frame contains an array of found items. If a global nd is in progress, the results array may contain slots created by other applications search methods. indicates whether the search is local or global, allowing you to handle these two cases differently if you prefer. The value of this argument is always one of the symbols 'localFind or 'globalFind. a frame to which you send the message SetStatus. The SetStatus function accepts as its sole argument a string to display to the user while the search is in progress.

scope

statusContext

12-8

Find

CHAPTER

12

Additional System Services

Interface to the DateFind Method


As mentioned earlier, a typical DateFind method is very similar to its text-nding counterpart. The system expects your applications DateFind method to look like the following example. DateFind: func( findTime , filter , results, scope, statusContext ) begin...end ndTime species the date selected by the user. The date is represented as an integer that is the number of minutes passed since midnight, January 1, 1904. species whether the user chose to nd items before or after the date specied by the value of the findTime parameter. The value of the argument to the filter parameter is always one of the symbols 'dateBefore or 'dateAfter.

lter

The remaining parameters to the DateFind methodresults, scope, and statusContext are used in exactly the same way as their counterparts in the Find method used for text searches. For descriptions of these parameters, see the section Search Method Interfaces,earlier in this chapter.

Implementing Search Methods


Because the implementation of a search method is for the most part application-specic, it is difcult to provide detailed instructions for completing this task; however, some general requirements apply to all search methods. This section describes these requirements and advises you of potential problems your applications Find or DateFind method may need to handle. Your search method needs to be able to search for data in internal RAM as well as in RAM or ROM on a PCMCIA card. Useful system-supplied functions like GetUnionSoup make it easier to solve this problem for soup-based data. The GetUnionSoup function allows you to treat multiple soups as a single soup, regardless of physical location.

Find

12-9

CHAPTER

12

Additional System Services

As your search method proceeds through the application data, it must test each item against user-specied criteria and collect items meeting the test criteria in a frame called the result frame. The exact content of this frame is described later in this chapter, in the section Returning the Results of the Search. Your search method also needs to report status to the user while the search is in progress. This is discussed in the section Reporting Progress to the User, later in this chapter. When the search is completed, the search method must append the result frame to the system-supplied results array. This task is described in detail in the sections Returning the Results of the Search and Storing The Result Frame, later in this chapter. The next section describes a system-supplied method that most applications can use to search for text in soup-based application data.

The StandardFind Function


The root view of the system supplies a method, StandardFind, that uses the soupFinder proto to implement a search for strings beginning with user-specied text. The interface to StandardFind looks like this: StandardFind (what, soupName, results , statusContext, indexPath ); The what, results, and statusContext parameters are exactly the same as those described previously for the Find method. soupName a string that is the name of your applications data soup. StandardFind uses this name to call GetUnionSoup for you. the index path used in the query that this function makes against your applications soup data. Pass nil for this value if you dont want to sort the entries in the cursor on this value. For more information, see the section Queries and Cursors, in Chapter 7, Data Storage and Retrieval.

indexPath

12-10

Find

CHAPTER

12

Additional System Services

To ensure that you send the StandardFind message to the correct view, prex the call with a colon (:), as in the following example. :StandardFind (what, soupName, results , statusContext, indexPath );
IMPORTANT

Do not call self:StandardFind, or GetRoot():StandardFind, as you cannot be absolutely certain that the context of this call will always evaluate to the root view. s

Creating the title Slot


The StandardFind method requires a string containing your applications name to be available in a text slot called title. You need to create this slot in the view referenced by the owner slot of the result frame returned by your search method. Commonly, the owner slot references the applications base view and the title slot is created in this view. Using the StandardFind Function to Implement Text Finds To use StandardFind to implement text searches, you simply call it in the body of your applications Find method, as illustrated in the following code example. // MyApplication.Find : // this code resides in a slot named Find // in your apps base view func(what, results, scope, statusView) begin // make sure the soup exists local mySoup // kMySoupName is a constant containing a string that // is the name of your apps data soup if (mySoup:=GetUnionSoup(kMySoupName)) // look for all entry text beginnning with what :StandardFind(what, mySoupName, results, statusView, nil); end;

Find

12-11

CHAPTER

12

Additional System Services

You can support Find and DateFind independently of one another; for example, you can choose to implement only the DateFind method if your application does not require the ability to nd text strings in its data. The next section provides suggestions for implementing your applications DateFind method.

Tips for Implementing the DateFind Method


Date-based searches have a lot in common with their text-based counterparts; in fact the only signicant difference between these two operations is the search criteria. Rather than matching a text string, your DateFind method implements a comparison function that tests items against the specied time and accepts or rejects them according to the criteria specied by the value of the filter parameter. You can simplify the implementation of date-based searches by timestamping your applications data when it is stored. If you store application data as frames that store the time they were created or modied in a time stamp slot, your DateFind method can simply test the value of this slot and accumulate in an array those items meeting the search criteria. Soup entries contain the system-supplied slot timeStamp, which you can use for this purpose.

Returning the Results of the Search


As you know, the search method must return a frame containing the results of the search. The frame returned by your applications DateFind method is exactly the same as that returned by the Find method used for text searches.The exact content of the result frame is determined by kind of nder proto used to create it, not the kind of information stored in it. This section describes result frames you can construct using the systemsupplied nder protos, as well as the methods your application must supply to support them. The methods your application must supply also vary according to the kind of proto used to create the result frame. Both systemsupplied protos, however, make use of a title slot that you need to create in your applications base view.

12-12

Find

CHAPTER

12

Additional System Services

Creating the title Slot


Both system-supplied protos expect a string containing your applications name to be available in a text slot called title. You need to create this slot in the view referenced by the owner slot of the result frame returned by your search method. Commonly, the owner slot references the applications base view and the title slot is created in this view.

Using the soupFinder proto


If your application stores its data in soups, you need to base your result frame on the soupFinder proto. Your result frame needs to contain the following slots: _proto owner cursor title Must have the value GetRoot().soupFinder; Set to something that can receive the ShowFoundItem message (usually your applications base view). The cursor returned by your search methods query A text string that is your applications name as it appears in the Find overview. You can omit this slot if the frame specied by owner has a title slot. Species whether the search is for text or date. The value of this slot is always one of the symbols 'text, 'dateBefore or 'dateAfter. Species the text to be matched or the date to be compared.

findType

findWords

The view specied by the owner slot must implement a FindSoupExcerpt method that extracts the name of a specied item from the result frame your search method constructs. The system displays the string returned by this method to identify the item in the Find overview. Figure 12-4 depicts the strings from the title slot and the FindSoupExcerpt method as they are used in a typical Find overview.

Find

12-13

CHAPTER

12

Additional System Services

Figure 12-4

Identifying strings in the Find overview

text from title slot

text returned by FindSoupExcerpt

Example Result Frame The following example shows a typical result frame based on the soupFinder proto. myResult := // for Find (text-based) {_proto:GetRoot().soupFinder, // must use this value owner:self, // view that gets the ShowFoundItems message, // usually your apps base view cursor:myCursor, // cursor that iterates over entries returned // by search methods query // findType is a symbol:

12-14

Find

CHAPTER

12

Additional System Services

// either 'text,'dateBefore or 'dateAfter findType:'text // indicates that this is a text find findWords:[search string] // array of words to match }; The slots in the frame returned by a date nd are the same as those in the return frame for a text nd; the only difference lies in the values stored in the findWords slot. For a date find, this slot contains an integer representing a date against which items are compared; in the case of a text nd, this slot contains the text string to be matched. The following code example depicts the result frame returned by a date nd. myResult := // for DateFind {_proto:GetRoot().soupFinder, // must use this value owner:self, // view that gets the ShowFoundItems message, // usually your apps base view cursor:myCursor, // cursor that iterates over entries returned // by search methods query // findType is a symbol: // either 'text, 'dateBefore or 'dateAfter findType:'dateAfter // collect items after the specified date findTime:value // date to compare, as an integer }; The FindSoupExcerpt Method If you use the soupFinder proto to construct your search methods result frame, your application needs to supply a FindSoupExcerpt method which extracts the name of an item from the result frame and returns it to the system as a string. The string this method returns is displayed in the Find overview.

Find

12-15

CHAPTER

12

Additional System Services

When you create your result frame you may want to tuck away some extra info in the frame for your FindSoupExcerpt method to use, such as a slot specifying whether the search was a text search or a date search so you can build a more appropriate title. For example, when displaying items in the overview from a date nd, you may want to include the date associated with each individual item. Your applications FindSoupExcerpt method should look like the example below. FindSoupExcerpt(entry,resultFrame); entry resultFrame the soup entry whose title is needed the frame your application added to the results array

This method returns a string that the system displays in the Find overview. The following example shows the implementation of a typical FindSoupExcerpt method. You need to define this method in a slot named FindSoupExcerpt in the view specified by the owner slot in the result frame that your search method returns. // myApplication.FindSoupExcerpt: func(entry, resultFrame) begin // if this isnt a date find, pass message to parent view if resultFrame.findType = 'dateBefore or resultFrame.findType = 'dateAfter or then begin return entry.nameString; end else return GetRoot():FindSoupExcerpt(entry, resultFrame); end

12-16

Find

CHAPTER

12

Additional System Services

Using the ROM_compatibleFinder Proto


If your application does not store its data in soups, you need to base your result frame on the ROM_CompatibleFinder proto. Your result frame needs to contain the following slots: _proto owner title Must be set to ROM_compatibleFinder The view that receives the ShowFoundItems message; usually your applications base view A string that is your application's name. When the user requests a global nd, the system displays this string in the overview of matches found in each application. You can omit this slot if the frame referenced by owner has a title slot. An array of found items returned by your Find method. Each element of the array is a frame; the structure of this frame is described immediately following, in the section Elements of the items Array. species whether the search is for text or date. The value of this slot is always one of the symbols 'text, 'dateBefore or 'dateAfter. species the text to be matched or the date to be compared.

items

findType

findWords

Elements of the items Array The frame returned by your search method contains a slot named items, which stores an array of frames. Each of the elements in this array is a frame storing an individual item that matched the search criteria. Each element in the array of found items is a frame containing these slots: _proto Use of this optional slot is just a suggestion, and is not enforced by the system in any way. It is strongly suggested that you reference the actual data frame that the search method found through a _proto slot rather than use the application data directly. Global searches 12-17

Find

CHAPTER

12

Additional System Services

destructively alter the items frame; referencing the application data frame through the _proto slot ensures that the original data remains intact. title the name of the application associated this item. If the frame referenced by _proto (or its owner) has a title slot, you can omit this slot. Your result frame can contain any additional slots you require to store application-specic information; these slots are ignored by Find. For example, you might store date strings in an additional slot when performing a date nd; you can then display these strings in the Find overview to provide additional information about the items that were found.

slotName

IMPORTANT

Global searches destructively alter the items frame. Because your applications Find method (the same one used for local searches) is called by the system when the user requests a global search, it is recommended that each element of your items array use a _proto slot to reference the data found in the search, rather than accessing the data directly. s Your items frame should look like the following code sample, which depicts the frame returned by a search that found two items. foundItems := // the search result [{ // data item returned by your search _proto:<actual data item found> // item displayed in the Find overview title:"First", // create as many slots as you need to store // application-specific information slotName: "some more data"}, {_proto:<actual data item found> title: "Second", slotName: "some more data"}];

12-18

Find

CHAPTER

12

Additional System Services

Sample Result Frame The following example shows a typical result frame based on the ROM_compatibleFinder proto. myResult := {_proto: GetRoot.ROM_compatibleFinder, // must use this value owner: self, // view that receives the ShowFoundItems message, // usually your applications base view title: "My Application", // string displayed in Find overview, // usually inherited from owner items: foundItems}; // array of items this search found After constructing the result frame, your search method needs to append it to the system-supplied results array, as described in the next section.

Storing The Result Frame


Your search method must store its result frame in the system-supplied results array. Each element in this array is a slot that contains a frame; the frame contains an array of items found in the search. You need to use the global function AddArraySlot to append to the results array a slot containing your result frame. The interface to AddArraySlot looks like this: AddArraySlot(array , value) AddArraySlot appends a slot to the specied array. array value the array to which this function appends a new slot. the name of the slot that this function creates in the specied array.

Find

12-19

CHAPTER

12

Additional System Services

The following example shows a line of code that would be placed at the end of your applications Find method to store the results of the search. In this code fragment, the results parameter contains the array that was originally passed to the Find method, and the myResult parameter is the frame containing the items found in the search. This call to AddArraySlot places the frame containing the results of the search at the end of the results array, in a slot named myResult. AddArraySlot(results, myResult);

Reporting Progress to the User


Recall that the argument to the statusContext parameter is a frame to which you send the message SetStatus. The SetStatus function accepts as its sole argument a string to display to the user while the search is in progress. Figure 12-5 depicts a typical status message from the Find service.
Figure 12-5 Typical progress message

The following code fragment shows how to use the statusContext parameter to display a progress message to the user. if statusContext then statusContext:SetStatus("Searching in applicationName"); The applicationName replaceable in this example would be replaced with the name of your application, obtained from the title slot in your result frame or its owner. The phrase Searching in applicationName is suggested because it is consistent with the status message that the built-in Newton applications display while a Find operation is in progress.

12-20

Find

CHAPTER

12

Additional System Services

If you want to experiment with SetStatus in the Inspector to produce the dialog box shown in Figure 12-5, you can use the following values: findDrawer findText findStatus the view that appears when the user taps the icon for the built-in Find application. the string for which Find searches the frame to which your application sends the SetStatus message

First, youll need to open the Find dialog box by executing the following line in the Inspector: GetRoot().findDrawer:Open; To set the value of findText to the string needles execute this line in the Inspector: SetValue(GetRoot().findDrawer.findInput.entryLine,'text,needles); The change to findText is reected on the screen because SetValue updates the findDrawer view for you. Execute the following line in the Inspector to pass as the argument to SetStatus the string Searching haystack for needles. GetRoot().findDrawer:SetStatus(Searching haystack for needles.) Note also that unless you happen to have an application called haystack available, tapping the Find button wont do anything meaningful. Tapping the All button will search all applications in FindApps for strings beginning with needles. We have now discussed all of the components of a typical search method. The next section provides code examples for several different kinds of search methods.

Find

12-21

CHAPTER

12

Additional System Services

Sample Search Methods


The sample code immediately following shows the implementation of several typical search methods. These examples dont contain code that actually searches application data, because the implementation of such a search would be application-specic; however, the examples do show how to use the system-supplied protos to search for text and dates.

Finding Text With soupFinder


It is strongly suggested that you use the StandardFind method to implement your Find method if possible; the following code example illustrates kinds of tasks this method performs for you. The example uses the soupFinder proto to search for text in soup-based application data. // MyApplication.Find : func(what, results, scope, begin // called by the Newton // this routine MUST be local ourResult; // for

statusView) when the user chooses Find named Find internal use

// tell the user what were doing // name of this app is MyApplication if statusView then statusView:SetStatus("Searching in MyApplication..."); // application may be closed, // so we need to create our soup GetUnionSoup(soupName); // string is name of your apps soup // look for all entries with text containing what // mySoup is this apps soup -- see DateFind example cursor := Query(mySoup, {type: 'text, text: what});

12-22

Find

CHAPTER

12

Additional System Services

// append our result frame to the system-supplied results array if cursor:Entry() then begin ourResult := { _proto: GetRoot().soupFinder, owner: self, title:"My Application", findType: 'text, findWords: [what], cursor: cursor, }; AddArraySlot(results, ourResult); end; // its unnecessary to return ourResult separately // but you can do so if you want to use it elsewhere return ourResult; end;

Finding Text With ROM_CompatibleFinder


The following example shows how to use the ROM_CompatibleFinder proto to search for text in non-soup-based application data. // MyAppplication.Find: func(what, results, scope, statusContext) begin local result ; local foundItems ; // set the message in the user interface Find view if statusContext then statusContext:SetStatus("Searching in ApplicationName");

Find

12-23

CHAPTER

12

Additional System Services

// Set up an array of found items. // This is where your app actually searches for items // matching some specified criteria and constructs // an array of the items that were found. // data frame returned by your search foundItems := // _proto slot is optional [{_proto:<actual data item found> // item string displayed in Find overview title:"First", // create as many slots as you need // to store application-specific data slotName: "some more data"}, {_proto:<actual data item found> title: "Second", slotName: "some more data"}]; // store found items in my own results frame myResult := {_proto: GetRoot().ROM_compatibleFinder, // non-soup data owner: self, // view that receives ShowFoundItem message title: "My Application", // omit if owner has title slot items: foundItems}; // array of found items // append my result frame to the // array originally passed to my Find method AddArraySlot(results, myResult); end;

12-24

Find

CHAPTER

12

Additional System Services

DateFind Method Using soupFinder


The sample code immediately following shows the implementation of a typical DateFind method using the soupFinder proto. // MyApplication.DateFind : func(findTime, findType, results, scope, findContext) begin // local vars for internal use local myEndTestFn ; local cursor ; local ourResult; local myEntry; local querySpec; // tell the user what were doing // name of this app is MyApplication findContext:SetStatus("Searching MyApplication"); // get the soup // name of this apps soup is MyApplication mySoup := GetUnionSoup("MyApplication"); // findType is either 'dateBefore or 'dateAfter // customize this querySpec according to kind of search querySpec := { type: 'index, // indexPath could be any time slot/path // entries sorted on 'timeStamp have a // system-supplied timeStamp slot indexpath: 'timeStamp, };

Find

12-25

CHAPTER

12

Additional System Services

// build the querySpec if findType = 'dateBefore then begin // because entries are sorted on timeStamp, // we start at first entry and were done when // we find a date that is later than findTime querySpec.startKey := 0; DateTest := func(item) item.timeStamp < findTime; // we dont need an end test for 'dateAfter searches // so we only build this part of cursor for a 'dateBefore search querySpec.endTest := func(item) item.timeStamp >= findTime; end; else begin // in a dateAfter search we start at findTime // we dont need endTest because cursor stops // when it has seen all remaining entries querySpec.startKey := findTime; DateTest := func(item) item.timeStamp > findTime; end; // fill in the valid test according to kind of search querySpec.validTest := DateTest; // get the cursor, sorted on timeStamp slot cursor := Query( mySoup, querySpec );

12-26

Find

CHAPTER

12

Additional System Services

// now set up the items frame and add it to the results array if cursor:Entry() then begin ourResult := { _proto: soupFinder, owner: self, title: "My Application", findType: findType, findWords: findTime, cursor: cursor }; AddArraySlot(results, ourResult); end; // returns slot added to array or nil if "if" is false // its unnecessary to return ourResult separately // but you can do so if you want to use it elsewhere return ourResult; end;

ShowFoundItem Method
When your search method completes, the system displays the results of the search in an overview list on the Newton screen. For global nds, each application in which items were found is identied by a heading, and the items that were found are listed under the heading. When the user taps scroll buttons to scroll through this list of found items, the system keeps track of the users place in the array of found items. When the user taps on an item in the overview, the view specied in the owner slot of the results framenormally, your application's base view is sent a ShowFoundItem message. In the template for the owner view, you must dene a ShowFoundItem method which locates the item in your applications data and displays it, performing any scrolling or highlighting that is appropriate.

Find

12-27

CHAPTER

12

Additional System Services

Figure 12-6

The ShowFoundItem method displays an item from the overview

The ShowFoundItem method used for displaying the results of a date nd is similar to that used for a text ndin fact, the very same method can often be used to display the results of either kind of search. As with search methods, the interface to ShowFoundItem varies according to the nder proto on which your result frame is based. The next two sections describe ShowFoundItem methods for both of the system-supplied finder protos. ShowFoundItem Method for soupFinder Proto If youve based your result frame on the soupFinder proto, the ShowFoundItem method is passed two argumentsthe soup entry that the user tapped in the Find overview, and the frame that your application added to the results array. The system expects your applications ShowFoundItem method to look like the following example. ShowFoundItem: func(myEntry, myCursor) begin . . . end

12-28

Find

CHAPTER

12

Additional System Services

In the body of this method, you need to do whatever is necessary to display the soup entry myEntry from the cursor myCursor. Typically youll send a Close message to the overview and open the appropriate view to display myEntry. The following code fragment shows the implementation of a typical ShowFoundItem method. // myApplication.ShowFoundItem: func(entry, cursor) begin // close my overview if its open if currentView = myOverview then begin myOverView:Close(); myDisplayView:Open(); // open view that displays the entry end; // scroll, highlight, etc. as necessary // to display the entry myDisplayView:DisplayEntry(entry, cursor); end ShowFoundItems Method for ROM_compatibleFinder If youve based your result frame on the ROM_CompatibleFinder proto, the ShowFoundItem method is passed a single argument, one of the elements of the items array. The system expects your applications ShowFoundItem method to look like the following example. ShowFoundItem: func(item) begin . . . end The item parameter species the frame from the foundItems array that stores the item selected by the user. For more information about the foundItems array, see the section Returning the Results of the Search, earlier in this chapter.

Find

12-29

CHAPTER

12

Additional System Services

Handling Messages From the Find Overview


When the user les, deletes, or moves items in the overview of found items, your application is notied via the BroadcastSoupChange mechanism. The BroadcastSoupChange(soupNameString) method sends a soupChanged message to all applications registered in the soupNotify array as using or owning that soup. SoupChanged(soupNameString) is a method that your application must supply to do whatever is necessary to cope with a change to the specied soup. For more information about the BroadcastSoupChange and SoupChanged methods, see the Soups section of Chapter 7, Data Storage and Retrieval.

Supporting Global Finds


Support of global nds requires that you take the additional step of adding your applications unique symbol to the FindApps array provided by the system. When your application is removed, it needs to remove its symbol from this array. This section describes how to register your application for global nds, and how to unregister it when the application is removed.

Creating an Application Identier Symbol


Your application is represented to the system by a symbol that you dene. In an effort to encourage the peaceful coexistence of applications created by different developers, the PIE Developer Technical Support group at Apple has published guidelines for the creation of application symbols, package names, soup names and other system-wide symbols. For details, see Appendix C, Newton Signature Guidelines.

12-30

Supporting Global Finds

CHAPTER

12

Additional System Services

This section briey describes how to use NTK to create an appSymbol slot that contains your application identier symbol. For more information, see Newton Toolkit Users Guide.

Storing Your Application Symbol in the AppSymbol Slot


In the base template of your application, you must dene a slot, appSymbol, that stores your applications symbol. To create an application symbol, you need to dene it as a compile-time constant in your applications Project Data le and then reference that constant through an evaluate slot in your applications base view. Take the following steps in NTK to dene in your applications base view an application symbol slot that references the '|foo:PIEDTS| symbol. 1. Place the following line of code in your applications Project Data le: constant kAppSymbol := '|foo:PIEDTS|; 2. In your applications base view, create a new slot of type evaluate. 3. Name the new slot appSymbol by using the Rename Slot item in the Special menu. 4. Set the value of the appSymbol slot to kAppSymbol by double-clicking the slot name, typing appSymbol in the slot editor window, and clicking the Apply Changes (checkmark) icon in the lower left corner of the browser window. For information on creating a slot and assigning a value to it, see Newton Toolkit Users Guide.

Registering Your Application for Global Finds


When the user requests a global search, the system sends a Find message to every application represented in the system-supplied FindApps array. To make your application available for global searches, you must append its unique symbolic identier to this array. (Your application can still perform local nds if its symbol is not in this array.)

Supporting Global Finds

12-31

CHAPTER

12

Additional System Services

You can use the global function AddArraySlot to append your application identier to the FindApps array. The interface to the AddArraySlot function looks like this: AddArraySlot (array,value); This function appends the element value to the specied array. For more information, see the discussion of the AddArraySlot function in the section Array Functions, in Chapter 17, Utility Functions. To register your application symbol with the Find service, you need to place in your applications InstallScript method a line of code similar to the one in the following example. This code fragment uses AddArraySlot to append the symbol '|foo:PIEDTS| to the FindApps array. Remember to place a single quotation mark in front of your symbol name so that the symbol, rather than its value, is passed to AddArraySlot. AddArraySlot (FindApps,'|foo:PIEDTS|);

Unregistering Your Application


When your application is removedfor example, when the PCMCIA card on which it resides is removedyou need to unregister its symbol with the Find system service by removing the symbol from the FindApps array. You can use the SetRemove function to do this; the interface to SetRemove looks like this: SetRemove (array, value); This function removes the element specied in value from the array specied in array. For more information, see the discussion of the SetRemove function in the section Array Functions, in Chapter 17, Utility Functions. To remove your applications symbol from the FindApps array when your application package is removed, place in your RemoveScript method a line of code similar to the one in the following example. SetRemove (FindApps,'|foo:PIEDTS|);

12-32

Supporting Global Finds

CHAPTER

12

Additional System Services

Registration Unnecessary for Local Finds


You need not register your applications symbol in the FindApps array to support local nds. Apart from registering, global and local nd support uses the same mechanism, which relies on the Find and ShowFoundItems methods that your application supplies.

Writing Your Own Finder Proto


Most applications do not need a custom nder proto; however, this section discusses methods and slots that may be useful when creating a custom nder proto or specializing one of the existing nder protos. Keep in mind that the implementation of your custom nder proto is entirely up to you. Depending on your design goals, you may use all or none of the slots and methods mentioned here.
Note

The information in this section is incomplete at this time. Updated information will be posted on the PIETalk bulletin board on AppleLink as it becomes available. u

Modifying Existing Finder Protos


The slots in your custom nder proto are of course entirely dened by your nder implementation; however, the following suggested slots may be useful. _proto currentItem the system-supplied nder proto on which your custom proto is based. As the user scrolls through the list of found items displayed in the Find overview, the system uses this slot to store an index to the currently-selected item.

Writing Your Own Finder Proto

12-33

CHAPTER

12

Additional System Services

Methods for Custom Finder Protos


These suggested methods mirror existing behavior in the system-supplied Find service; once again, these are only suggestions, as the implementation of your Find support is entirely dependent upon your design goals. ReSync ReSync: func () begin end This method resets the current item to the rst item in the array of found items.If your proto is based on soupFinder, this method should reset the cursor as well. Call this method when disposing of the Find overview or when the user changes items in the Find overview, making it necessary to update and redisplay the overviewfor example, moving or deleting an item. You can also use this method to recover from errors encountered when the attempt to display an item fails, such as when advancing the cursor to an item returns nil or the 'deleted symbol. ShowFoundItem ShowFoundItem: func(entry, cursor) begin end // for _proto:soupFinder ShowFoundItem: func(item) begin end // for _proto:ROM_CompatibleFinder This method displays an item when the user taps on it in the Find overview. To do so, this method may need to open a view appropriate for displaying the item, set the cursor or currentItem slot to the reference the item, and perform any scrolling or highlighting that is appropriate. This method may call the ShowFoundItem method of the view specied in the owner slot. Note that the arguments to this method change according to the soupFinder proto used to implement the result frame. For more information, see the section ShowFoundItem Method, earlier in this chapter.

12-34

Writing Your Own Finder Proto

CHAPTER

12

Additional System Services

entry cursor item ShowOrdinalItem

The soup entry for the item on which the user tapped in the FInd overview The cursor returned by your search methods query The item on which the user tapped in the FInd overview

ShowOrdinalItem: func (ordinal) begin end This method shows an entry from the cursor specied by ordinal value; it can be used to scroll items in the Find overview. For example, to scroll to the next item in the overview, you could increment or decrement the currentItem index appropriately, call the appropriate cursor function to set the current item to the new index, and then redisplay the overview. ordinal One of the symbols 'first, 'prev, or 'next, that is used to call the appropriate cursor function to retrieve the specied entry.

For more information on the cursor methods Move, GoTo, Next, Prev, and Reset, see the Queries and Cursors section in Chapter 7, Data Storage and Retrieval. AddFoundItems AddFoundItems: func (foundItem , offset, maxCount) begin end This method builds the result frame that is returned by your search method. How you obtain the data stored in this frame depends on the type of Finder you have; that is, soupFinder protos get their data from a cursor that is returned in response to a query, ROM_compatibleFinder protos build an array of found items in their items slot, and your custom nder proto may take yet another approach.

Writing Your Own Finder Proto

12-35

CHAPTER

12

Additional System Services

foundItem

A frame containing the items found. It should have the following slots: { // typical foundItem frame // we suggest you dont access //data directly _proto: <someApplicationDataItem>, // your custom finder proto finder: someFinderProto, // index of this item itemIndex:n // string identifying this item // in Find overview title:"the item name"

} offset maxCount The number of preexisting items to skip over before adding the new one Maximum number of items that may be added to the result frame

Handling Messages From the Find Overview


The messages described in this section are sent to your application when the user taps buttons in the Find overview. The soupFinder proto supports these messages for you, manipulating soup entries returned by the cursor. The ROM_compatibleFinder proto does nothing in response to these messages.

FileAs
FileAs: func (labels) begin end This method les all of the Find overview items in the folder specied by the labels parameter.

12-36

Writing Your Own Finder Proto

CHAPTER

12

Additional System Services

labels

The folder in which to le the found items.

For information on methods and data structures you can use to implement this method, see the Filing section, later in this chapter.

MoveTo
MoveTo: func (toStore) begin end This method moves all of the items in the Find overview to the store specied by the toStore parameter. toStore The store to which the found items are to be moved.

For information on methods and data structures you can use to implement this method, see the Soupssection of Chapter 7, Data Storage and Retrieval.

Delete
Delete: func () begin end This method deletes all of the items in the Find overview from your applications data. For information on methods and data structures you can use to implement this method, see the Soupssection of Chapter 7, Data Storage and Retrieval.

Filing
The File mechanism in Newton allows your application to tag soup entries with labels used to store, retrieve and display the data by category. The labels used to tag entries are represented as folders in the user interface; however, no true hierarchical ling existsthe tagged entries still reside in the soup. To store the currently-displayed item, the user taps on a le folder button that displays a list of categories in which to le the item. When the user

Filing

12-37

CHAPTER

12

Additional System Services

chooses a category from the list, the system sets the value of the data frames labels slot and notifies your application that filing has changed. Your application performs the appropriate application-specic tasks and redraws the current view, providing to the user the illusion that the item has been placed in a folder. The user retrieves items by choosing from a popup list the category of previously-led items to be displayed in an overview view. When the user taps on an item in the overview, the system retrieves and displays the selected entry. The default categories provided by the system for ling and display of data are None (Unled), Business, Important, Miscellaneous, and Personal; the user can edit these default labels as well as add up to eight more.

Programmers Overview of Filing


Most of the user interface to the Newton ling mechanism is supplied for you by the protoFilingButton and protoFolderTab protos. In addition to displaying views with which the user can interact to store and retrieve data, these protos send messages to your application when the user les an item (filingChanged), changes the display of data items ( filterChanged), or edits the list of ling categories (folderChanged). This section discusses these protos and the messages they send to your application.

The protoFilingButton View and the lingChanged Message


The protoFilingButton proto displays on the screen a button that looks like a le folder and is found on the right side of any divider line in the notes screen, or in the lower-right corner of the card le. This button should be placed in the lower-right corner of your application window. When the user taps the button, Newton displays a dialog box containing a list of categories under which the user can choose to le the currentlyselected item. Figure 12-7 depicts the protoFilingButton view and the dialog box that is presented when the user taps this button.

12-38

Filing

CHAPTER

12

Additional System Services

Figure 12-7

User interface to Filing service

When the user taps one of the categories in the dialog box, the system stores the symbol representing that category in the labels slot of the frame storing the current entry and sends a filingChanged message to your application. Your applications filingChanged function must display the items that match the current lter.

The protoFolderTab View and the lterChanged Message


The protoFolderTab view displays on the screen a view that looks like the tab on a le folder. When the user taps the title on the tab, this proto displays a popup list of ling categories. A checkmark appears next to the currently-selected ling category in this list; the user can tap an item in the list to select a new category to be displayed. 12-39

Filing

CHAPTER

12

Additional System Services

When the user taps a ling category in the popup list, Newton sends the filterChanged message to your application and collapses the list, displaying the currently-selected ling category on the le folder tab. Your applications filterChanged method must display the data led under the newly-selected category. Figure 12-8 shows a protoFolderTab view as it appears to the user when the popup list of ling categories is displayed; the previous illustration, Figure 12-7, shows the protoFolderTab view as it appears when the list is collapsed.

Figure 12-8

Selecting a ling category in the protoFolderTab popup list

12-40

Filing

CHAPTER

12

Additional System Services

The folderChanged Message


The user can also edit the list of categories under which items may be led. Because the Newton user interface depicts these ling categories as folders, the message sent to your application when a ling category is changed is called folderChanged. Your folderChanged method must update the appropriate data frames with the new name. The implementation of the folderChanged method is discussed in detail in the following section, Adding Filing Support to Your Application.

Adding Filing Support to Your Application


You need to take the following steps to implement ling support in your application. This section discusses these tasks in detail:
n

Implement the filingChanged, filterChanged and folderChanged methods. You can use the system-supplied DefaultFolderChanged global function to implement your applications folderChanged method. Dene a labels slot in your applications data frames. This slot is for use by the system. Add views based on protoFilingButton and protoFolderTab to your applications base view. Dene the slots appAll, appObject, labelsFilter, target, and targetView in your applications base view.

Required Slots
You need to dene the slots appAll, appObject, labelsFilter, target, and targetView in your applications base view. You also need to dene a slot called labels in your applications data frames.This section discusses each of these slots in detail.

Filing

12-41

CHAPTER

12

Additional System Services

The appAll slot The appAll slot stores a string that is displayed as the last item in the protoFolderTab popup menu; this item allows the user to display all of your applications data frames. The string stored in this slot must be of the form All Items where Items is the plural for the application-specic items to be led, such as expense reports, cards, notes, and so on. For example, if the user taps the protoFolderTab view in the built in Notes application, the last item in the popup list is All Notes, as shown in Figure 12-8. The following code fragment a typical appAll slot. appAll: "All Notes" The appObject slot The appObject slot stores an array of two strings. The rst element of the array species the singular case of your applications data items and the second element species the plural case, as shown in the following example code fragment. appObject: ["note", "Notes"] The rst element is used in the protoFilingButton dialog box displayed when the user les an item. For example, the protoFilingButton dialog box shown in Figure 12-7 displays the string File this note in. The second element is used in the protoFolderTab view to indicate to the user the currently-selected ling category. For example, the protoFolderTab view depicted in Figure 12-7 displays the string Unled notes.

12-42

Filing

CHAPTER

12

Additional System Services

The labelsFilter slot The labelsFilter slot stores a value indicating the current ling category selected from the protoFolderTab popup list. This slot can store either a symbol or the value NIL. If the value stored in this slot is NIL, your filterChanged method must display unfiled items. If a symbol is stored in this slot, your filterChanged method must display the kind of items represented by that symbol. The system-supplied symbol '_all indicates that your filterChanged method is to display all of your applications soup entries. The value of the labelsFilter slot is set by the system. The targetView slot The targetView slot species the view to which ling messages are sent. The value of this slot is almost always your applications base view. You need to set the value of this slot in your InstallPackage script, using code similar to the following example. InstallPackage: func() begin // your application-specific code goes here self.targetView := self; end The target slot The target slot contains the soup entry with which the user is working, such as the current card, note, or caffeine record to be led. If there is no active item, this slot must have the value NIL. Your application must update the value of the target slot every time the user views a new item. Because the selection of a new item is an applicationspecic detail, it is difcult to recommend a means of updating this slot that will be appropriate for every application; however, updating this slot in the viewClickScript of the active view is frequently an acceptable solution.

Filing

12-43

CHAPTER

12

Additional System Services

The labels slot Each frame in which your application stores an entry must contain a labels slot. When the user les the entry, the system stores the symbol representing the ling category in this slot. Storing this symbolic value in the labels slot is really the only ling that is donethe entry still resides in the soup, but your filingChanged method provides for the user the illusion that the data has been put somewhere else. This slot can store either a symbol or the value NIL. If the value stored in this slot is NIL, your filingChanged method must treat the item as unled. If a symbol is stored in this slot, your filingChanged method must test the value of this slot to determine whether the entry should be displayed and then redraw the display appropriately. The value of the labels slot is set by the system when the user chooses a ling category from the protoFilingButton popup list.

Required Methods
In your applications base view, you need to create slots named for the methods filingChanged, filterChanged and folderChanged, and implement these methods as described in this section. The lingChanged Method When the user chooses a ling category from the protoFilingButton popup list, the system updates the current entrys labels slot and sends the filingChanged message to your applications base view. Your applications filingChanged function must redraw the current display appropriately. For example, if your application is displaying an overview list of unled items when it receives this message, your filingChanged function needs to redraw the list without the newly-led item in it, providing to the user the illusion that the item has been stored elsewhere. Your filingChanged method must also handle the case in which the user re-les an item in the category under which it already resides. In this case, the appropriate response is to do nothing; unnecessarily redrawing views that have not changed makes the screen appear to icker or ash.

12-44

Filing

CHAPTER

12

Additional System Services

There are no arguments to the filingChanged method; because the system updates the current entrys labels slot when the user chooses a new ling category, you can determine the current ling category by examining the value of this slot. Dont just assume that the current value of a data frames labels slot is valid without testing it; the system may have sent the filingChanged message because the user deleted that filing category! The following code example shows the implementation of a typical filingChanged method. filingChanged: func() begin /* this is where your application updates soup information for the current target, NOTE that the target is a frame, not a cursor. You must also maintain the cursor somewhere as well */ if self.labelsFilter and (target.labels <> self.labelsFilter) then // dont forget to flush the cache or you may lose // value of target.labels in a reset or card pull EntryChange(target); // now redo the kids or something because the new // category is not the same as the current filter end; The lterChanged Method When the user changes the current lter category in the protoFolderTab view, the system calls your applications filterChanged method. This method must display the items that match the current lter. The following code example shows the implementation of a typical filterChanged method. The sample filterChanged method defines

Filing

12-45

CHAPTER

12

Additional System Services

a query function, called qfunc, which tests the labels slot of an entry against the current ling category stored in the applications labelsFilter slot. The qfunc function is used to query the soup for the entries that match the current ling category. filterChanged: func() begin local newfilter := self.labelsFilter ; local qFunc ; // // // // // if setup a query function for the items in the soup of data items. need to compare the labels slot of the item with the new filter unless '_all is the filter. In that case, all items are valid newFilter <> '_all then qfunc := func(item) item.labels = newFilter ; else qfunc := func(item) true ; // use the query function to access the soup myQuery := Query(mySoup, {type: 'index, validTest: qFunc}); end; The folderChanged Method When the user adds, renames or deletes a name in the list of ling categories, the system sends a folderChanged message to the owning application once for each soup registered in the soupNotify array; that is, if your application has registered more than one soup in this array, it will receive multiple folderChanged messages.

12-46

Filing

CHAPTER

12

Additional System Services

You must supply a folderChanged method that updates the labels slot of any of your applications data frames that are affected by the name change. You can use the system-supplied global function DefaultFolderChanged to implement your folderChanged method. The system expects your applications folderChanged method to look like the following example. folderChanged(soupName,oldFolder,newFolder) The soupName parameter contains a string that species the name of the soup associated with the ling category that was renamed or deleted. The oldFolder parameter contains a symbol that species the folder (label) that was changed. The newFolder parameter contains a symbol specifying the new name of the folder that was changed. The value of this parameter is NIL for a folder that has been deleted. The following code example shows the implementation of a typical folderChanged method. The DefaultFolderChanged function performs all the tasks shown in this example; unless you need to take application-specic action, you can implement your applications folderChanged method by simply calling the DefaultFolderChanged function. folderChanged: func (soupName,oldFolder,newFolder) begin // no changes to existing folders if only adding new one if oldFolder = nil then return; // nothing to do if soup doesn't exist (yet) if not GetStores()[0]:HasSoup(soupName) then return; // update folder labels for all entries in the soup // querySpec is implementation-specific

Filing

12-47

CHAPTER

12

Additional System Services

local myEntry, cursor := Query(GetUnionSoup(soupName),); loop begin myEntry := cursor:Entry(); if myEntry = nil then break; if myEntry.labels = oldFolder and not EntryStore(myEntry):IsReadOnly() then begin myEntry.labels := newFolder; EntryChanged(myEntry); end; // if end; // loop // tell the app to recalc the visible items :SoupChanged(nil); // tell the filter bar to update (in case filter was renamed) if self.filterBar then filterBar:UpdateFilter(oldFolder, newFolder); end;// fn Because the details of the query spec depend on how your applications data is organized, this example intentionally leaves it out. Youll generally use the GetUnionSoup function to collect all of the relevant soups, though. The UpdateFilter method is supplied by the protoFolderTab system prototype; it updates the text on the folder tab if the user has renamed the ling category. You may also need to propagate label changes elsewhere in your application; for example, in cached soup data.

Adding the Filing Button


Your application must display a ling button in its base view. This is the folder-like button that the user taps to display the ling dialog, as shown in Figure 12-7.

12-48

Filing

CHAPTER

12

Additional System Services

Take the following steps to add the ling button to your applications base view.
n

In NTK, sketch the ling button in your applications base view using the protoFilingButton proto and declare it to the applications base view. In the ling buttons viewSetupFormScript or viewSetupDoneScript method, set appropriate values for its viewBounds slot. If you dont set the view bounds, you'll get an error when opening the view that contains the ling button. The following example is taken from the built-in Names application in the Newton MessagePad; it uses the global function RelBounds to place the button inside of another view to produce a border around the ling button. viewBounds:RelBounds( -23, 2, 17, 13),

Supply the ling buttons buttonClickScript method. Your buttonClickScript method needs to call the inherited buttonClickScript method after its performed the appropriate application-specic tasks. buttonClickScript: func() if :EntryCool(target, true) then inherited:buttonClickScript();

Adding the Folder Tab View


Your application must display a folder tab in its base view. This is the view that displays the currently selected ling category, as shown in Figure 12-7. This view is based on the protoFolderTab system proto. Adding the folder tab view to your application is easy. In NTK, sketch the folder tab in at the top of your applications base view using the protoFolderTab proto and declare it to the applications base view.

Filing

12-49

CHAPTER

12

Additional System Services

Filing Methods
The system-supplied methods described here may be used to implement ling. DefaultFolderChanged DefaulFolderChanged(soupName, oldFolder, newFolder) Updates the specied folder label for all entries in the specied soup and reects the change in the folder tab view if the current ling category is the one that has changed. soupName oldFolder newFolder A string that species the name of the soup associated with the ling category that was renamed or deleted. A symbol that species the folder (label) that was changed. A symbol specifying the new name of the folder that was changed. The value of this parameter is NIL for a folder that has been deleted.

UpdateFilter UpdateFilter(oldFolder, newFolder) Updates the text on the folder tab if the user has renamed the current ling category. oldFolder newFolder A symbol that species the folder (label) that was changed. A symbol specifying the new name of the folder that was changed. The value of this parameter is NIL for a folder that has been deleted.

12-50

Filing

CHAPTER

12

Additional System Services

Undo
The global function AddUndoAction provides a mechanism for implementing Undo capabilities in your Newton application. AddUndoAction AddUndoAction(methodName, parameters ) The AddUndoAction function registers with the system a method to be called whenever the user taps the Undo button. methodName A symbol (it must have a single quote) that is the name of the method to be called when the user taps Undo. This method must always return TRUE. An array of parameters to be passed to this method.

parameters

Here's how you would use this function to provide undo capability in a view. Say you have a view that uses cards and you have a particular method, DeleteCard, that is called when you need to delete a card. Within the DeleteCard method, you call the AddUndoAction function, passing the name of a different method that will add the card, passing the card that was deleted as a parameter to the method. Your call to AddUndoAction would look like this: DeleteCard: func(theCard) begin . . . // statements that delete a card . . . AddUndoAction ('AddCard, [theCard]) end,

Undo

12-51

CHAPTER

12

Additional System Services

You also need to supply the AddCard method, like this: AddCard: func(theCard) begin . . . // statements that add a card . . . end,

Notication
This section describes how to take advantage of the system notication facility. The view method Notify provides the capability to display an alert view, as illustrated in Figure 12-9. The last four alert messages are saved by the system, and the user can scroll through them by tapping on the universal scroll arrows while the alert view is open. Also, the user can tap on the circled i to display the date and time of the message.

Figure 12-9

Notify alert

12-52

Notication

CHAPTER

12

Additional System Services

Notify view:Notify(level, headerStr, messageStr ) Uses the system notication facility to display a message or otherwise notify the user. level Species the notication level to use and can be one of the following constants: kNotifyLog The notice is only entered into the notication log; the user is not alerted. kNotifyMessage The user is alerted by a blinking notice icon that a message is pending. Tapping the icon causes pending messages to be displayed in an alert view. kNotifyAlert The notice is immediately displayed to the user in an alert view and the system beep is played. kNotifyQAlert The notice is immediately displayed to the user in an alert view. headerStr A string that is displayed as a header on the notice. Usually this is the name of your application or a major component of it. A string that is the message to the user.

messageStr

Notication

12-53

CHAPTER

12

Additional System Services

Idling
This section describes how to install an idler for your application. An idler is a system service that sends your view a viewIdleScript message periodically. SetupIdle view:SetupIdle(milliseconds ) Installs or changes an idle routine for the specied view. (An idle routine calls the view's viewIdleScript method periodically.) The SetupIdle method always returns NIL. milliseconds The number of milliseconds to wait before calling the viewIdleScript method for the rst time. After the rst time, the views viewIdleScript method returns an integer which is the delay until this method is next called.

You can call the SetupIdle method at any time to reset the idle time immediately. To remove the idle routine from the view, call this method again with an idleTime of zero. You can also remove the idler by returning NIL from your viewIdleScript.
Note

When you install an idler for a view, the time when the viewIdleScript message will next be sent is not guaranteed to be the exact interval you specify. This is because the idler may be delayed if a method is executing when the interval expires. The viewIdleScript message cannot be sent until an executing method returns. Do not install idlers that use extremely short intervals (less than 100 milliseconds). u

12-54

Idling

CHAPTER

13

Routing

In the Newton interface, the term routing has acquired a rather broad denition. Originally intended to collectively describe communication functions like printing, faxing, and mailing, it has come to include just about any action performed on an object.

Overview
Access to the routing functions is provided by the Action button. When the user taps on this button, a pop-up list of available functions is displayed, as shown in Figure 11-1. Certain functionsduplicate and delete, for instancerequire no additional information from the user, and are performed as soon as the user selects the item from the pop-up list.

Overview

13-1

CHAPTER

13

Routing

Figure 13-1

Action button

Other functionsprint, fax, beam, and mailrequire additional information before they can be performed. When the user selects one of these items from the list, a routing slip for that operation is presented. Figure 11-2 shows the various different types of routing slips. For each activity, the routing slip solicits whatever information is needed to accomplish the task: type of printer, fax number, mail address, and so forth. When a user has provided the necessary information, they tap another button to dispatch the task: Print, Fax, Mail, or Beam. The item then goes into the Out Box, located in the Extras drawer. The Out Box contains a list of all the items waiting to be sent, organized by category. Beaming is performed immediately. The Out Box opens and a progress message is displayed as the item is sent.

13-2

Overview

CHAPTER

13

Routing

Figure 13-2

Routing Slips

Printing, faxing, and mail are deferred until the user opens the Out Box and sends items explicitly. The user can send all items in a category by tapping on Connect and choosing the category. Or they can send a single item by tapping rst on it, and then on the Send button in the Conrm dialog.
Note

If the Newton is connected to a fax/modem, the system can send the entry immediately. u

Overview

13-3

CHAPTER

13

Routing

Figure 13-3

Out Box

Figure 13-4

In Box

13-4

Overview

CHAPTER

13

Routing

The user can cancel an operation-in-progress by tapping the Stop button in the status bar. When an item has been sent, the Out Box closes. At the other end, reception of data is handled by the In Box. The user opens the In Box and taps on the Receive button to accept data sent by either beaming or mail.

Adding Routing to Your Application


To add routing to your application, you need to do the following things:
n

Add the protoActionButton from the NTK palette to your application. This proto provides the envelope icon. Dene certain slots in the base view of your application. For printing and faxing, you will also add certain slots to the root view. Create a routing frame and add it to the system global routing. The routing frame species which routing functions your application will support, and causes these functions to appear in the Action button picker.

Dening Your Base View Slots


You need to dene the following slots in the base view of your application.

appSymbol
The appSymbol slot contains the symbol that uniquely identies your application. For details on this symbol, see Using the Newton Toolkit.

target
The target slot contains the data to be sent. Any frame can be sent as long as it is not too largethis depends on the amount of RAM availableand does not contain references to ROM. Soup entries are ne because any _proto slots are removed when you put a frame in a soup. Views cannot be sent because of their prototypes.

Adding Routing to Your Application

13-5

CHAPTER

13

Routing

How you maintain the target slot is up to you. You may want to keep track of the soup entry with which the user is working, such as the current card, note, or record. For certain routing functions, you may want to set up the target data at the time of routing, instead of maintaining it in the target slot as you go along. In this case, you can provide a setUpTarget method (described later in this section) and provide your target data there.

targetView
This slot species the view to which routing messages are sent. The value of this slot is almost always your applications base view. Should you wish to set this view at the time of routing, you can do it in the setUpTarget method.

setupTarget
setupTarget(slip) This method is optional. Youll implement this method if you want to set up your target data at the time of routing. You might, for example, want to set up an array of items to print.
IMPORTANT

The setupTarget method is not called for duplicate, delete, and card transfer; for these routing functions, you must use the target slot. s The setupTarget method is sent one argument: the routing slip for the selected routing function. Your method sets the target and targetView slots of this slip. Heres an example: SetupTarget: func(slip) begin slip.target := :GetMyCurrentTarget(); slip.targetView := self; end

13-6

Adding Routing to Your Application

CHAPTER

13

Routing

setupRoutingSlip
setupRoutingSlip(fields) This method is called to give you a chance to change or add information before the routing actually happens. The fields argument is the frame that actually goes into the Out Box. You must implement this method to change the text descriptionthat appears in the Out Box entry for the routed item (for example, Notepad, Fri 1/1/ 11:00 am). The fields frame contains a slot, called title, that you can set to the string you want to appear. For example: func(fields) begin fields.title := "SampleApp," && DateNTime(Time()); end

Creating a Routing Frame


The routing frame is where you specify which routing functions you want. This frame is typically a slot dened in your base view. You need an entry for each routing function desired. Heres an example routing frame that would produce an Action button with two functions, print and delete. myRoutingFrame = { print: { title: "Print Record", routeForm: 'printSlip, formats: [kFormatSymbol]

}, divider1: }, delete: }, };

nil, { title: "Delete", routeScript: 'deleteRecordScript

Adding Routing to Your Application

13-7

CHAPTER

13

Routing

As you can see from this example, there are three types of picker items:
n

For routing functions that go through the Out BoxPrint, Fax, Beam, and Mailyou must dene a routeForm slot with the name of the routing slip for that function. Print, Fax, and Mail must also have a formats slot that species how the data should be formatted. For routing functions that do not go through the Out BoxDelete, Duplicate, and Card Transfer you must provide a routeScript method that performs the activity. These routing functions do not need the routeForm or formats slots. For a handy dividing line, you can dene a slot with a name of your choosing and a value of nil.

The slots used in constructing routing frame entries are here described in detail.

title
This slot is required for all routing functions. It contains the text you want to display for this Action picker item: for instance, Print Record. There are two user interface guidelines you should probably follow in this regard: 1. Place the items in the same order as the built-in applications, like the Notepad. 2. In the very rst item, add a descriptive object describing the data to be routed; Record for example. With the rest of the items, a simple verb will sufce. (Card transfer is an exception; it requires a modier like From or To.)

routeForm
For printing, faxing, beaming, and mail, you must dene this slot and pass one of the following pre-dened symbols: 'printSlip 'faxSlip 'zapSlip (for beaming) 'mailSlip

13-8

Adding Routing to Your Application

CHAPTER

13

Routing

You dont need this slot for deleting, duplicating, or card transfer.

routeScript
For deleting, duplicating, and card transfer, this slot contains the symbol of a method that actually performs the activity.

formats
For printing, faxing, and mail, the formats slots must contain an array of one or more symbols referencing formats (that you must create). For instance: formats := [kFormatSymbol]; These symbols are used to build the Format picker in the routing slips for these functions. For a detailed discussion of how to create formats, see the section Printing, Faxing, and Mail later in this chapter.

Adding Your Routing Frame


You need to add your routing frame to the system global routing; you could put this code in your InstallScript. When you close your application, you should then remove your routing frame in your RemoveScript. For example: const kAppSymbol := '|myApp:SAMPLE|'; InstallScript := func(partFrame) begin local myApp := partFrame.theForm ; routing.(kAppSymbol) := myApp.myRoutingFrame ; end; RemoveScript := func(partFrame) begin RemoveSlot(routing, kAppSymbol); end;

Adding Routing to Your Application

13-9

CHAPTER

13

Routing

Deleting
To support deleting, you need a routing frame entry like this: delete: { title: Delete, routeScript: 'myDeleteScript}, You must write the method that deletes the data, and put its symbol in the routeScript slot. This method is passed the target and target view as arguments. It should send the Delete message to the target view. The Delete message has the syntax Delete(method,args ) where method is the symbol of the method to call to delete the actual data, and args is an array of arguments to pass to that method. For example: myDeleteScript: func(target, targetView) begin targetView:Delete('deleteTheData,[target,targetView]); end The Delete message causes the crumple animation to be displayed. You must also then implement the method, in the target view, that deletes the actual data; deleteTheData, for example: deleteTheData: func(entry, entryView) begin EntryRemoveFromSoup(entry); entryView:drawFromSoup(); end

13-10

Deleting

CHAPTER

13

Routing

Duplicating
To support duplicating, you need a routing frame entry like this: duplicate: { title: Duplicate, routeScript: 'myDuplicateScript}, You must write the method that duplicates the data, and provide its name in the routeScript slot. This method is passed the target and target view as arguments. In general, this method will put a new entry, that is a duplicate of the current entry, into the soup. For example: myDuplicateScript: func(target, targetView) begin // make a copy of the target local newItem := myCopyScript(target); // update the view targetView:drawFromSoup(); end You might also want to add a new view for the new data item and set it as the current view.

Duplicating

13-11

CHAPTER

13

Routing

Beaming
To support sending data by beaming, you need a routing frame entry like this: zap: { title: "Beam", routeForm: 'zapSlip}, Beaming is different from the other routing functions because you also need to consider the reception of the routed data on another Newton. There are two possible scenarios: either the beam is intended for reception by your application (running on the other Newton), or the beam is intended for reception by some other application. When the user taps Put Away on a message in the In Box, the system looks at the appSymbol slot thats part of the routed item, and sends a putAway message to that application. If you want your application to receive beams, you need to implement a putAway method in the base view.

PutAway
PutAway(item) The item argument is a frame. One slot in this frame, called body, contains the data that was sent. Your putAway method might store this data in a soup; for example: putAway: func(item) begin local newEntry; newEntry := item.body;

13-12

Beaming

CHAPTER

13

Routing

// ensure that filing folder exists on this Newton // or nil it out if it doesnt CheckThatFolderExists(newEntry); local s := myAppSoup; if NOT s then s := RegisterCardSoup(kSoupName, kSoupIndices, kAppSymbol, kAppObject); // add the frame to the soup s:AddToDefaultStore(newEntry); // inform apps that the soup has changed BroadcastSoupChange(kSoupName); end;
IMPORTANT

The PutAway method can be called when your application is closed. You therefore can not rely on anything that you set up in methods like viewSetupFormScript being there. This warning applies to messages that are sent from your putAway method as well. A good example is the BroadCastSoupChange call made in the previous example. It will cause the soupChanged method in your application to be called, but your application may not be open. Make sure you check if your application is open with something like: if self.viewCObject then ...
s

The other option is that you may want your application to send a beam to a different application. Doing this is tricky. First, youll need to set the appSymbol slot, using the SetupRoutingSlip method, to the symbol of the application whose PutAway method you want called. Second, youll need to understand what kind of frame the receiving application expects and be sure to send your data in that format.

Beaming

13-13

CHAPTER

13

Routing

In general, its a good idea to open a view showing the data that was put away; this gives the user a chance to do something with the received data and gives added conrmation that the data was, in fact, put away.
Note

The PutAway method does not return an error. You should probably use the Try and Throw functions to handle exceptions that are encountered. (See The NewtonScript Programming Language for details.) u

Card Transfer
To support transfers to and from cards, you need a routing frame entry like this: card: ROM_cardaction; The ROM_cardaction method moves the data to and from the card for you and sends a BroadcastSoupChange message.
IMPORTANT

For card transfer, your target must be a soup entry.

Printing, Faxing, and Mail


To support printing, faxing, and mail, you need routing frame entries like these: print: { title: Print Record, routeForm: 'printSlip, formats: [kFormatSymbol]} fax: { title: Fax, routeForm: 'faxSlip, formats: [kFormatSymbol]}

13-14

Printing, Faxing, and Mail

CHAPTER

13

Routing

mail: { title: Mail, routeForm: mailSlip, formats: [kFormatSymbol]} Each of these routing frame entries includes a formats slot. This slot contains one or more symbols that reference formats you must dene. There are four steps to creating, installing, and referencing a format:
n

In your NTK project, create a format using the New Print Format menu item in the File menu. In the base view of your application, dene a format frame that references your format. In your InstallScript, add your format to the root view . In the formats slot of your routing frame, reference your installed format frame.

n n

Creating a Format
A format is basically a special kind of layout. Whereas you create a layout to lay out views on the screen, you create a format to lay out views on a routing mediuma printed or faxed page, or the text of a mail message. To create a format, choose New Print Format from the NTK File menu. (The name of this menu item is understood to include formats for faxing and mail as well.) For the base view of your format, choose protoPrintFormat from the palette. This proto automatically adjusts itself to the output device. As you add child views, you can use their viewJustify slot to ensure that they use the full page. You can also determine the size, in pixels, of the output page by sending a LocalBox message to the view that uses protoPrintFormat as its proto.
Note

Printing in landscape mode is currently not supported.

Printing, Faxing, and Mail

13-15

CHAPTER

13

Routing

Accessing Your Target Data


Formats are attached to the root view and cannot access the target slot of your application. They can, however, access the fields frame that goes into the Out Box. You can implement the SetupRoutingSlip method (described in Dening Your Base View Slots earlier in this chapter) to add a slot to the fields frame and copy your target into it. For example: func(fields) begin fields.myData := Clone(target); fields.title := title && DateNTime(Time()); end
IMPORTANT

Be sure not to put view references or references to ROM in this frame. Its best to keep the information you store in fields small; for instance, a key that can be used for a soup query. s Needless to say, printing and faxing require your application to be present. PrintNextPageScript PrintNextPageScript() Your format must dene a printNextPageScript method. (A slot for this method is automatically provided by protoPrintFormat.) This method is called after each page is sent to see if there are additional pages. If there are no additional pages, printNextPageScript should return nil. If there are more pages, this method needs to set up the page (perhaps by calling :RedoChildren) and return true. Heres an example of a printNextPageScript method: func() begin // always print 2 pages // fields.pageNumber is the current page

13-16

Printing, Faxing, and Mail

CHAPTER

13

Routing

if fields.pageNumber < 3 then begin :RedoChildren() ; true ; end else nil ; end

Format Issues
Your formats viewDrawScript method may be called many times for a single page. If your viewDrawScript changes a cursor to point to other entries, it should copy the cursor (that is, use cursor:Clone) before changing it. If it uses variables to keep track of things like width, height, or other counters, it should reset those variables on each call.
Note

Only the viewDrawScript may be called multiple times. The viewSetupFormScript and viewSetupDoneScript methods are called only once per page. u Printing and faxing use a banding method to render the page to the output device. There are several things you need to consider in this regard. You do not have access to the coordinates of the current band, so if youre drawing your entire page, things can be very slow. (Time is a factor with faxing; if theres no activity for ve seconds or so, the connection can break.) Its a good idea, whenever possible, to break your page up into multiple views. The system only renders the views in the current band. Your format must initialize itself quickly. If you need to do a substantial amount of initialization, do it in the viewSetupFormScript of the protoPrintFormat, since this method is called before a fax connection is established. Also, its better to cache your data in your setupRoutingSlip method instead of making lots of soup queries in your format.

Printing, Faxing, and Mail

13-17

CHAPTER

13

Routing

Dening a Format Frame


In the base view of your application, you need to dene a format frame that species assorted bits of information, including a reference to your format. A format frame can contain the following slots. myFormatFrame := { title: Print Record, auxForm: nil, textScript: 'myTextScript, attachment: true, _proto: ROM_coverPageFormat, mainFormat: printFormat_myFormat }; A format frame must contain at least a title slot and a mainFormat slot. title This slot contains the text that will be shown in the Format picker of the routing slip. To see where the title slot is used, go to the Notepad, click on the Action button and pick Print Note. Youll get the print routing slip with two pickers. The second picker is the Format picker; the entries in this picker are generated from the title slot. auxForm The auxForm slot denes a layout for a slip that will be used to gather additional information. To see an example of an auxForm in action, pick Print Note from the Notepad and then pick the Memo format. The auxiliary slip that solicits further information is an auxForm layout. For more details, refer to the sample code on this topic published by the PIE Developer Technical Support (DTS) group.

13-18

Printing, Faxing, and Mail

CHAPTER

13

Routing

TextScript TextScript(fields, target) You can implement this function to return a text-only representation of the target data, to be used as the body of a mail message. Heres an example: func(fields, target) begin local text := ""; text := "Check #" & NumberStr(target.ckNumber); text := text & "\n" "To:" && target.ckPayee; text := text & "\n" & "For:"; text := text & :localizedMoney(target.ckAmount); end This example returns a string something like this: Check #4 To: Ned the Wonder Llama For: $1,000,000.00 You cannot use this method to send graphics or other types of frame data. You can, however, set the attachment slot to true and the target frame will be attached to the mail message. attachment Set this slot to true to attach the target frame to a mail message. _proto For faxing, you can set this slot to ROM_coverPageFormat; this prototype gives you the standard fax cover page automatically.

Printing, Faxing, and Mail

13-19

CHAPTER

13

Routing

mainFormat The mainFormat slot contains a reference to the format you created with the New Print Format menu item. Your reference should have the form printFormat_fileName, where fileName is the name you gave to your format le when you saved it.

Adding Your Format Frame to the Root View


After dening a format frame, you need to add it to the root view in your InstallScript. For example: constant kAppSymbol := constant kFormatSymbol := '|myApp:SAMPLE| ; '|sampleFormat:myApp:SAMPLE|;

InstallScript := func(partFrame) begin local myApp := partFrame.theForm; routing.(kAppSymbol) := myApp.myRoutingFrame; GetRoot().(kFormatSymbol) := BuildContext(myApp.myFormatFrame); end; RemoveScript := func(partFrame) begin RemoveSlot(routing, kAppSymbol); RemoveSlot(GetRoot(), kFormatSymbol); end; The symbol you dene in your InstallScript (kFormatSymbol, in the above example) is the symbol that you need to put in the formats slot of your routing frame entries.

13-20

Printing, Faxing, and Mail

CHAPTER

13

Routing

Multiple Formats
You can dene multiple formats. Each format must have its own format frame that references the format in the mainFormat slot. You can specify a default format by placing the format symbol in a slot called lastFormat in the base view of your application. Note, however, that the system will update the value of this slot if the user selects a different format. You may want to check and set the value of the lastFormat slot from the context of your application, perhaps along with maintaining your target. You cannot set this slot from the SetupRoutingSlip method, as the system has already accessed the slot at this point.
IMPORTANT

Mail uses a different slot, called lastMailFormat, so youll need to maintain this slot separately if you implement mail. s

Printing, Faxing, and Mail

13-21

CHAPTER

14

Communications

This chapter describes how to develop communication tools for Newton.

Introduction
The Newton provides a number of built-in communication services. These services are available to any developer who wants to use or build upon them. They include:
n n n

synchronous and asynchronous serial connection modem connection (MNP/v42 and Class1-T30/T4) point-to-point infrared (IR) communication (Sharp 9600 and Apple IR enhanced protocols) AppleTalk ADSP protocol

Introduction

14-1

CHAPTER

14

Communications

Endpoints
The basis of the communications architecture is the notion of an endpoint. An endpoint is the interface between the user and an underlying transport service. A single prototypeprotoEndpointprovides a standard interface to all communication servicesserial, modem, IR (or beaming), and AppleTalk protocols, as well as third-party communication products. This proto provides methods for
n n n n

communicating with the underlying service setting options opening and closing connections sending and receiving data

The instantiated endpoint frame encapsulates and maintains the details of the specic connection at hand, how to handle input, and so on. It includes methods to be run under certain circumstances, such as when input is available. And it includes a specication of the type of transport service being used. In the current implementation, there can be only one endpoint open at a time. You cant have two endpoints using the serial port at once, nor can there be two different ports in use at the same time. For instance, if someone is sending data through the serial port, you cant transfer data through the IR port.

Options
The specics of the session at hand, including the type of communications service being used, a specication of the destination, and communications parameters such as baud rate, parity, and so forth, are set by supplying

14-2

Endpoints

CHAPTER

14

Communications

option frames in the configOptions slot of the endpoint. An option frame can contain the following slots: label type opCode The option identier. The type of option, which can be 'service, 'option, or 'address. How the service should handle the option request. Values are: opSetRequired means that if the service is unable to honor the request (a baud rate of 1.2 million, for instance), the request must fail. Note that other options in the array are processed even though one or more may fail. opSetNegotiate means that the service can substitute a reasonable value if the requested value is unacceptable opGetDefault returns the default settings. opGetCurrent returns the current settings. A result code, set on return from the GetOptions method. (This slot is ignored if used as an argument.) Details of the option.

result data

Specifying the Service


You specify the communication service by providing a 'service option. Every endpoint must have one 'service option. The following 'service label constants are provided:
Constant Value Service

kCMSAsyncSerial kCMSMNPID kCMSModemID kCMSSlowIR kCMSAppleTalkID

"aser" "mnps" "mods" "slir" "atlk"

asynchronous serial serial with MNP modem IR AppleTalk

Endpoints

14-3

CHAPTER

14

Communications

To create an asynchronous serial endpoint, for instance, you would do as follows: mySerialEndpoint := { _proto:protoEndpoint, configOptions: [ { label: kCMSAsyncSerial, type: 'service, opCode: opSetRequired }, ], }; Note that the value opSetRequired is specied for the opCode slot; this value says that if the requested service is not available, the request should fail. Youll always use opSetRequired when specifying the 'service option. After specifying the 'service option, you then need to set the relevant 'option and 'address options, which depend on the service youre using. Lets look at the different services individually.

Serial Endpoints
Serial endpoints can involve a range of communication parameters: baud rate, ow control, DTR control, and so on. Heres an example of an asynchronous, 9600bps, 8-bit, no-parity serial endpoint, with XON/XOFF ow control: mySerialEndpoint := { _proto:protoEndpoint, configOptions: [ { label: kCMSAsyncSerial, type: 'service, opCode: opSetRequired },

14-4

Endpoints

CHAPTER

14

Communications

{ label: type: opCode: data:

kCMOSerialIOParms, 'option, opSetNegotiate, { bps: k9600bps, dataBits: k8DataBits, stopBits: k1StopBits, parity: kNoParity } }, kCMOInputFlowControlParms, 'option, opSetNegotiate, { xonChar: unicodeDC1, xoffChar: unicodeDC3, useSoftFlowControl: true, useHardFlowControl: nil } }, kCMOOutputFlowControlParms, 'option, opSetNegotiate, { xonChar: unicodeDC1, xoffChar: unicodeDC3, useSoftFlowControl: true, useHardFlowControl: nil } },

{ label: type: opCode: data:

{ label: type: opCode: data:

], }; Note that all three 'option specications use an opCode of opSetNegotiate, which means that if the requested values (9600bps, for instance) are not available, a reasonable substitute will be accepted.

Endpoints

14-5

CHAPTER

14

Communications

The serial 'option labels are as follows:


Label Value

kCMOSerialIOParms kCMOInputFlowControlParms kCMOOutputFlowControlParms

"siop " "iflc" "oflc "

General Input/Output Parameters


The kCMOSerialIOParms option species the basic input/output parameters. In the bps slot, you can use the following constants to specify the interface speed:
Constant Value

kExternalClock k300bps k600bps k1200bps k2400bps k4800bps k7200bps k9600bps k12000bps k14400bps k19200bps k38400bps k57600bps k115200bps k230400bps

1 300 600 1200 2400 4800 7200 9600 12000 14400 19200 38400 57600 115200 230400

14-6

Endpoints

CHAPTER

14

Communications

In the dataBits slot, you can use the following constants:


Constant Value (# of Data Bits)

k5DataBits k6DataBits k7DataBits k8DataBits

5 6 7 8

In the stopBits slot, you can use the following constants:


Constant Value (# of Stop Bits)

k1StopBits k1pt5StopBits k2StopBits

0 1 2

In the parity slot, you can use the following constants:


Constant Value

kNoParity kOddParity kEvenParity

0 1 2

Flow Control
The kCMOInputFlowControlParms and kCMOOutputFlowControlParms options have the same format. They let you specify XON and XOFF characters, as well as software and hardware ow control.

Endpoints

14-7

CHAPTER

14

Communications

You can use the following constants for default ow control:


Constant Value

kDefaultXOnChar kDefaultXOffChar

$\u0011 $\u0013

The following constants are useful for specifying unicode characters:


Constant Value

unicodeNUL unicodeSOH unicodeSTX unicodeETX unicodeEOT unicodeENQ unicodeACK unicodeBEL unicodeBS unicodeHT unicodeLF unicodeVT unicodeFF unicodeCR unicodeSO unicodeSI unicodeDLE unicodeDC1 unicodeDC2 unicodeDC3 unicodeDC4 unicodeNAK

$\u0000 $\u0001 $\u0002 $\u0003 $\u0004 $\u0005 $\u0006 $\u0007 $\u0008 $\u0009 $\u000A $\u000B $\u000C $\u000D $\u000E $\u000F $\u0010 $\u0011 $\u0012 $\u0013 $\u0014 $\u0015

14-8

Endpoints

CHAPTER

14

Communications

Constant

Value

unicodeSYN unicodeETB unicodeCAN unicodeEM unicodeSUB unicodeESC unicodeFS unicodeGS unicodeRS unicodeUS

$\u0016 $\u0017 $\u0018 $\u0019 $\u001A $\u001B $\u001C $\u001D $\u001E $\u001F

Modem Endpoints
Heres an example of a modem endpoint, without MNP compression: protoModemEndpoint := { _proto:protoEndpoint, configOptions: [ { label: kCMSModemID, type: 'service, opCode: opSetRequired }, { label: type: opCode: data: { label: type: opCode: data: kCMOModemECType, 'option, opSetRequired, kModemECProtocolNone}, kCMOMNPAllocate, 'option, opSetRequired, kMNPDontAllocate},

Endpoints

14-9

CHAPTER

14

Communications

{ label: type: opCode: data: ], };

kCMOMNPCompression, 'option, opSetRequired, kMNPCompressionNone},

The list of modem 'option labels is as follows:


Label Value Meaning

kCMOModemECType kCMOMNPAllocate kCMOMNPCompression kCMOModemDialing

"mecp" "mnpa" "mnpc" "mdo "

error control type use MNP compression type of MNP compression dialing preferences

Modem Error Control


The kCMOModemECType option species the type of error control to use; possible data slot values are as follows:
Constant Value Meaning

kModemECProtocolNone kModemECProtocolMNP kModemECProtocolExternal

0x00000001 0x00000002 0x00000008

no error control use internal MNP (class 4) use external modems built-in error control

You can specify either kModemECProtocolMNP or kModemECProtocolExternal but not both. If you want the endpoint created even if the requested error control is unavailable, you must also specify kModemECProtocolNone; for instance: {label: type: opCode: data: kCMOModemECType, 'option, opSetRequired, kModemECProtocolMNP + kModemECProtocolNone},

14-10

Endpoints

CHAPTER

14

Communications

MNP Allocation
The kCMOMNPAllocate option species whether you want a buffer allocated for MNP compression; possible data slot values are as follows:
Constant Meaning

kMNPDoAllocate kMNPDontAllocate

allocate buffer do not allocate buffer

MNP Compression Type


The kCMOMNPCompression option species which MNP compression to use; possible data slot values are as follows:
Constant Value Meaning

kMNPCompressionNone kMNPCompressionMNP5 kMNPCompressionV42bis

0x00000001 0x00000002 0x00000008

connect with no compression connect with MNP 5 compression connect with V42bis compression

If you specied kMNPDontAllocate for the kCMOMNPAllocate option (described previously), you must specify kMNPCompressionNone for the compression type. If you specied kMNPDoAllocate, you need to specify either kMNPCompressionMNP5 or kMNPCompressionV42bis. There is a fall-back mechanism whereby if you request MNP V42bis compression and it isnt available, the modem tool will try MNP5 compression. If MNP5 compression is unavailable, the endpoint will be created without MNP compression.

Endpoints

14-11

CHAPTER

14

Communications

Modem Dialing Preferences


You specify modem dialing preferences using the kCMOModemDialing option. Three of the dialing preferences can be specied by the user; the rest of the preferences have default values, as shown here.
Slot name Default value

speakeron detectdialtone detectbusy dtmftonedialing manualdial speakervolume waitforcarrier waitbeforeblinddial commadelay ringtoanswerafter

true user preference true user preference nil user preference 55 seconds 3 seconds (used only when detectdialtone is false) 1 second 2 seconds (used only when modem endpoint is listening for connection)

You may override any of the default values. For the three user-specied preferences, you can fetch the values from the System soup, or from the userconfiguration global. The following example sets the three user preference values and overrides the default values for the speakeron and waitforcarrier slots: myModemDialOption := { type : 'option, label : kCMOModemDialing, opCode : opSetRequired, data : { speakeron: nil, detectdialtone: true, dtmftonedialing: true,

14-12

Endpoints

CHAPTER

14

Communications

speakervolume: waitforcarrier: } };

kSpeakerVolumeMedium, 60,

You can use the following constants to set the value of the speakervolume slot:
Constant Value

kSpeakerVolumeLow kSpeakerVolumeMedium kSpeakerVolumeHigh

"1" "2" "3"

Address Option
Youll also need to supply a phone number as an 'address option; for instance: addressOption := { type : 'address, label : kCMARouteLabel, opCode : opSetRequired, data : { addressType:: kPhoneNumber, addressData:: "9,555-1212" } };

Serial Endpoints With MNP Compression


You can also create a serial endpoint with MNP compression. To do this, you need the basic serial options, as well as three MNP options. Two of the MNP options, kCMOMNPAllocate and kCMOMNPCompression, are described under Modem Endpoints earlier in this chapter.

Endpoints

14-13

CHAPTER

14

Communications

A third MNP option, kCMOMNPDataRate, species the rate for data transfers. You can use the same constants provided for setting the bps slot in serial endpoints:
Constant Value

k300bps k600bps k1200bps k2400bps k4800bps k7200bps k9600bps k12000bps k14400bps k19200bps k38400bps k57600bps k115200bps k230400bps

300 600 1200 2400 4800 7200 9600 12000 14400 19200 38400 57600 115200 230400

Heres an example: mySerialMNPEndpoint := { _proto:protoEndpoint, configOptions: [ { label: kCMSMNPID, type: 'service, opCode: opSetRequired },

14-14

Endpoints

CHAPTER

14

Communications

{ label: type: opCode: data:

kCMOSerialIOParms, 'option, opSetNegotiate, { bps: k9600bps, dataBits: k8DataBits, stopBits: k1StopBits, parity: kNoParity } }, kCMOMNPAllocate, 'option, opSetRequired, kMNPDoAllocate}, kCMOMNPCompression, 'option, opSetRequired, kMNPCompressionV42bis}, kCMOMNPDataRate, 'option, opSetRequired, k9600bps},

{ label: type: opCode: data: { label: type: opCode: data: { label: type: opCode: data: ], };

IR Endpoints
Newton uses a compatible extension of the protocol used in Sharp Corporations IZ/IQ 9000 series of electronic organizers. Support for other IrDA standards is currently under consideration. The current Newton IR implementation is a half-duplex, asymmetric transport, which means that you cannot send and receive data at the same time.

Endpoints

14-15

CHAPTER

14

Communications

To create an IR endpoint: myIREndpoint := { _proto:protoEndpoint, recvFlags: kFrame, configOptions: [ { label: kCMSSlowIR, type: 'service, opCode: opSetRequired }, ], };
IMPORTANT

Note that an IR endpoint must have a recvFlags slot, set to kFrame, in addition to the usual configOptions frame. s

AppleTalk ADSP Endpoints


Heres an example of how to create an AppleTalk ADSP endpoint: myADSPEndpoint := { _proto:protoEndpoint, configOptions: [ { label: kCMSAppleTalkID, type: 'service, opCode: opSetRequired }, { label: type: opCode: data: kCMSAppleTalkID, 'option, opSetRequired, kCMOAppleTalkADSP },

14-16

Endpoints

CHAPTER

14

Communications

{ label: type: opCode: data: ], };

kCMOEndpointName, 'option, opSetRequired, kADSPEndpoint },

Address Option
Youll also need to supply an 'address option, giving an AppleTalk Name Binding Protocol (NBP) address. For example: addressOption := { type : 'address, label : kCMARouteLabel, opCode : opSetRequired, data : { addressType:: kNamedAppleTalkAddress, addressData:: "PrinterName:Laserwriter@Zone" } };
Note

For information on both the AppleTalk ADSP and NBP protocols, consult Inside Appletalk. u Due to power constraints, it is not possible for the Newton to register an NBP name on the network (so that other devices could locate it). Future machines may provide NBP registration and listening capabilities. A number of functions are provided for obtaining the addresses of other devices on the network; these functions are covered in AppleTalk Functions below.

Endpoints

14-17

CHAPTER

14

Communications

Instantiating the Endpoint


After youve dened your endpoint and supplied the necessary options in the configOptions slot, you then need to instantiate the endpoint. Instantiate endpoint :Instantiate(endpoint, options ) Instantiates an endpoint. endpoint options For example: myEndpoint:Instantiate(myEndpoint, nil); You can, if you prefer, pass your options to Instantiate, rather than putting them in the configOptions slot. If you do pass options to Instantiate, however, you must pass all of them. In other words, you cant specify some options in configOptions and then pass (or change) additional options in Instantiate. If another endpoint is already open, on any port, Instantiate returns the error 8007 and an exception like this: Exception |evt.ex.msg|: "new TEndpoint failed" A reference to the endpoint youve dened. Optional. A complete set of endpoint options.

Establishing a Connection
Establishing a connection has two parts: one party initiates the connection and the other accepts it. To initiate a connection, call Connect. To wait for and accept a connection request, call Listen. To cancel a pending Connect or Listen, call Abort.

14-18

Endpoints

CHAPTER

14

Communications

Note

Putting your Connect or Listen call inside of the AddDeferredAction function will make it easier to abort the connection process. u Listen is supported for modem, IR, and MNP serial endpoints. With IR communication, when one Newton is calling Connect, the other Newton must be calling Listen. Connect endpoint :Connect(address, options) Initiates a connection. address An 'address option. You can specify the 'address option here instead of in the configOptions slot, if you prefer. Currently not used; specify nil.

options

Heres an example of creating an 'address option and calling Connect: myAddress := { type : 'address, label : kCMARouteLabel, opCode : opSetRequired, data : { addressType:: kPhoneNumber, addressData:: "555-1212" } AddDeferredAction(func() ep:Connect(myAddress, nil)) You should be sure to check for any error code returned; it can help you narrow down any problems. (See the appendix Errors for a complete list of error values.) With an IR endpoint, if nothing happens and you receive a time-out with a 38001 error, it means that the other side is probably not calling Listen.

Endpoints

14-19

CHAPTER

14

Communications

Listen endpoint :Listen(options) Waits for a connection request and, based on the specied option criteria, accepts it. To cancel Listen, call Abort. options Currently not used; specify nil.

Sending Data
Two methods are provided for sending data: Output and OutputFrame. To send strings, integers, arrays, or binary frames, use Output.
n

Strings are automatically converted from Unicode to ASCII. (You may substitute a different translation table by putting a reference to the table in the endpoint.encoding slot; the default value is kMacRomanEncoding.) Integers or arrays of integers are treated as unsigned byte values (0..255). Binary frames other than strings are sent without conversion. With arrays, each element of the array is sent in turn, allowing an arbitrary sequence of bytes to be sent. Character array elements are not converted, however.

n n n

To send a frame, keeping the structure intact and without any conversion, use OutputFrame. The OutputFrame method takes any type of data immediates, binary objects, arrays, or frames. It attens the data and sends it as a stream of bytes (preceded by an unsigned long count). If youre making consecutive output calls, its a good idea to clear the pipes after three or four calls by calling FlushOutput. Output endpoint :Output(data, flags) Outputs the value data .

14-20

Endpoints

CHAPTER

14

Communications

data

If data is a character, that character is sent. If data is a string, that string is sent. If data is a number, a single byte with the bottom eight bits of the number is sent. If data is an array, each element of the array is sent in turn. (Note that this allows an arbitrary sequence of bytes to be sent, independent of any issues involving Unicode.) These constants are provided for transport-level protocols which may use them. (These ags can also be used in the recvFlags slot of the endpoint.)

flags

For example: endpoint:Output("llama", nil); endpoint:Output(unicodeCR, nil); endpoint:Output("2832531", nil); endpoint:Output("99\n", nil); endpoint:Output(endpoint:SendMessage(), nil); The following constants are provided for setting the flags parameter:
Constant Value Meaning

kMore kFrame kExp

0x00000001 0x00000002 0x00000004

set end-of-message use framing for preserving end-of-message expedited data

The kMore ag is used to preserve the end-of-message (EOM) ag for transport-level protocols that support it. This ag is of no use with serial and modem connections; specify nil instead. When sending data using an IR endpoint, specify kFrame + kMore if additional output is to come. When youre nished with your transmission, simply specify kFrame. For instance: endpoint:Output("sometext", kFrame + kMore); endpoint:Output(unicodeCR, kFrame);

Endpoints

14-21

CHAPTER

14

Communications

OutputFrame endpoint :OutputFrame(data, flags) Outputs data as a attened frame. data flags A frame. These constants are provided for transport-level protocols which may use them. (These ags can also be used in the recvFlags slot of the endpoint.) See the discussion (immediately preceding) of the Output method for details.

FlushOutput endpoint :FlushOutput() Ensures that all output is sent across the channel. Its a good idea to call FlushOutput after each Output or OutputFrame call. Error 8007 is an indication that you need to be calling FlushOutput.

Receiving Data
To receive data, you need to provide an input specication. An input spec, as it is called, denes an input block, and can have the following slots: byteCount A byte count. (If specied, do not also specify a termination character, as the termination character will take precedence.) A termination character. Optional. Analogous to a buffer size, this slot species how many bytes to hold. The oldest characters are discarded after this limit is reached. A method to be called when a block has been received.

endCharacter discardAfter

inputScript

14-22

Endpoints

CHAPTER

14

Communications

A format in which to return data. You can specify 'string to return a character string, converting ASCII into Unicode as required. 'raw to return a raw byte stream. These bytes are not converted into Unicode. 'frame to unflatten and return a frame that was sent using OutputFrame. The byteCount, endCharacter, and discardAfter slots are ignored. 'array to return an array of integers, each corresponding to one byte of input. This format is the default format. partialScript Optional. Called periodically (based on the value in the PartialFrequency slot), this method is returned the data received until that point. partialFrequency Optional. The frequency , in milliseconds, at which the PartialScript should be run. inputForm
IMPORTANT

The important thing to understand about input (and output) is that the endpoint does not mark and recognize different types of data. You need to implement some sort of protocol mechanism to negotiate data formats. s After dening your input spec, you set it in action by calling SetInputSpec. Heres an example that asks for character input up to and including a carriage return, with a maximum of 200 bytes: receiveText: { inputForm: 'string, endCharacter: unicodeCR, endCharacter: 200, }, ep:SetInputSpec(receiveText);

Endpoints

14-23

CHAPTER

14

Communications

Most times, youll want to wait until the input spec conditions are met: a termination character is received or a byte count is reached. At this point, your inputScript is called with the received block passed to it. Your inputScript should have the following format: myInputScript(endpoint , data) myEndpoint data A reference to the endpoint youve dened. The received data, formatted as specied by inputForm.

You can also force termination of an input spec by calling Input.


Note

There is currently no way to receive an end-of-message (EOM) indication via an input spec. Future versions of the communications interface will support automatic EOM termination of input specs. u After youve set your rst input spec, there are two ways of setting subsequent input specs. You can call SetInputSpec again, or you can put your next input spec into a slot in the endpoint called nextInputSpec. Heres an example that requests characters up to and including a carriage return and then requests a frame: receiveText: { inputForm: 'string, endCharacter: unicodeCR, discardAfter: 200, InputScript: func(endpoint, s) begin ep.nextInputSpec := endpoint.receiveFrame; ep:HandleText(s); end, },

14-24

Endpoints

CHAPTER

14

Communications

receiveFrame: { inputForm: 'frame, InputScript: func(endpoint, f) begin ep.nextInputSpec := nil; ep:HandleFrame(f); end, }, To ush all bytes in the input channel (in the current and all subsequent blocks), call FlushInput.
IMPORTANT

With IR endpoints, you should not have an active input spec while also trying to send output. s SetInputSpec endpoint :SetInputSpec(inputSpec) Sets the specied input specication. inputSpec Input endpoint :Input() Forces the current input spec to be terminated. Input reads the input buffer, up to the number of bytes specied in discardAfter, formats the data as specied by inputForm, and returns the data. You can use Input as a way of moving on when nothing is happening. Note, however, that Input does not call the InputScript of the terminated input spec. The identier of the input spec to be used.

Endpoints

14-25

CHAPTER

14

Communications

FlushInput endpoint :FlushInput() Discards all bytes in the input channel.

Receiving Partial Input


You can ask that partial inputless than an input blockbe passed back to a script you provide in the PartialScript slot of your input spec. You also need to dene a PartialFrequency slot and specify the frequency , in milliseconds, at which the PartialScript should be run. Note that this value sets the minimum time between invocations of PartialScript; there are no assurances, however, about the maximum time between invocations. Also, the script is run only if new data has arrived since the last invocation. You can also ask for all input received since the last time your PartialScript was called by calling Partial. The data returned to PartialScript or Partial is not removed from the buffer. To discard all bytes in the current input block up to the end of the last invocation of PartialScript or Partial, call FlushPartial.
IMPORTANT

The PartialScript function does not terminate the input spec, and does not work while receiving binary or attened frames. s Partial endpoint :Partial() Returns a frame containing the bytes that have arrived since the last time your PartialScript was called. Partial formats the data as specied by inputForm, and returns the data. Partial leaves the data in the input buffer (unlike Input, which removes it). To clear the data, call FlushPartial.

14-26

Endpoints

CHAPTER

14

Communications

FlushPartial endpoint :FlushPartial() Causes all bytes in the current input block, up to the end of the last partial read operation, to be discarded.

Creating a State Machine


You can combine input specications to create state machines that implement CCL (Connection Control Language) facilities. Your InputScript methods can use string-parsing functions to test for state transition conditions. Based on these tests, actions can be performed by the scripts, and new input specications can be used to proceed a new state. For example, the following input spec takes input up to and including the character E. It compares the last three characters with the string AGE to identify the MESSAGE prompt. waitForMESSAGE: { inputForm: 'string, endCharacter: $E, discardAfter: 200, InputScript: func(endpoint, s) begin if (StrPos(s, "AGE", 0)) then begin ep:SetInputSpec(endpoint.waitForSEND); ep:Output(endpoint:SendMessage(), kMore); ep:FlushOutput(); end end, },

Endpoints

14-27

CHAPTER

14

Communications

If the search string is found, the InputScript sends the message and then species the next input specwaitForSend which looks for the SEND: prompt. waitForSEND: { inputForm: 'string, endCharacter: $:, discardAfter: 200, InputScript: func(endpoint, s) begin if(StrPos(s, "SEND:", 0)) then begin ep:SetInputSpec(endpoint.waitForLastFUNCTION); ep:Output("Y\n", nil); ep:FlushOutput(); end end, }, Its also possible to create a parent-child hierarchy of input specs. For example, you could dene a parent input spec that waits for connection, a child that waits for a login name prompt, a grandchild that waits for a password prompt, and so on. Creating a hierarchy of input specs can help organize your exception handling. You can dene a general purpose exception handler at the parent levelconnection broken, for instancealong with handlers for specic conditions like incorrect password.

14-28

Endpoints

CHAPTER

14

Communications

Checking the Endpoint State


You can use the State method to determine the state of the endpoint. State endpoint :State() Returns the state of an endpoint. Possible values are:
Constant Value Meaning

kUninit kUnbnd kIdle kOutCon kInCon kDataXfer kOutRel kInRel kInFlux


IMPORTANT

0 1 2 3 4 5 6 7 8

uninitialized unbound idle outgoing connection pending incoming connection pending data transfer outgoing release pending incoming release pending state is changing

The presence of a connection will not prevent the system from going to sleep. If the system does go to sleep, the connection dies. The SCC hardware is powered off, and will be reinitialized when the system wakes up. Your endpoint frame is intact, but youll need to either call Connect again or dispose of the endpoint with Dispose. You can prevent the Newton from going to sleep during a critical communication transaction by overriding the poweroffScript message; see the chapter Handling System Messages for details. s

Endpoints

14-29

CHAPTER

14

Communications

Changing or Adding Options


Youll want to set most options in the configOptions slot of the endpoint. If you want to change or set certain options after the endpoint has been instantiated, use the SetOptions method. You can determine the current or default values of one or more options by calling GetOptions. SetOptions endpoint :SetOptions(options) Sets the specied options. options
IMPORTANT

One or more options.

The SetOptions method works only with certain options. For now, its best to set your options in the configOptions slot before calling Instantiate. s GetOptions endpoint :GetOptions(options) Returns the specied options. options One or more options.

You specify the options in the options parameter just as if you were setting them, except that you pass either opGetCurrent or opGetDefault in the opCode slot of each option. For example: myOptions: [ { label: kCMOSerialIOParms, type: 'option, opCode: opGetCurrent,

14-30

Endpoints

CHAPTER

14

Communications

data:

{ bps: dataBits: stopBits: parity:

k9600bps, k8DataBits, k1StopBits, kNoParity } },

{ label: type: opCode: data:

kCMOInputFlowControlParms, 'option, opGetCurrent, { xonChar: unicodeDC1, xoffChar: unicodeDC3, useSoftFlowControl: true, useHardFlowControl: nil } },

], }; myendpoint:GetOptions(myOptions) On return, the result slot of each option contains one of the following values:
Constant Value Meaning

opSuccess opFailure opPartSuccess

0 1 2

operation completed successfully operation failed option was set, but with a different value than requested (returned only when opSetNegotiate opcode was used) set attempted on a read-only option option not supported specied opCode was invalid option not found one or more requested options are missing

opReadOnly opNotSupported opBadOpCode opNotFound opTruncated

3 4 5 6 7

Endpoints

14-31

CHAPTER

14

Communications

Handling Exceptions
Most of the endpoint functions return nil for success, or an integer for failure. The integer is generally an error code. You can also provide an exceptionHandler method in your endpoint frame. ExceptionHandler endpoint :ExceptionHandler(error) If provided, this method is called whenever an exception is thrown, when an output fails, or when an in-progress input spec encounters an error. error A frame with a name slot thats passed a string with the exception name, usually |evt.ex.comm|, and a data slot thats passed the integer error code.

If no exceptionHandler method is specied, the exception is passed up the handler chain. Exceptions that are not caught are turned into user-level alerts. (See the Exception Handling chapter of The NewtonScript Programming Language for more information.)

Closing a Connection
If you want to abort a data transfer, call Abort. Before calling Abort, however, there are two things you must do. You must set endpoint.nextInputSpec to nil and then call SetInputSpec(nil), in that order.. Here is an example: BailOut : func() begin ep.nextInputSpec := nil; // no more input ep:SetInputSpec(nil); // kill current inputSpec ep:Abort(); end; If you want to close down the connection, you need to call Disconnect and Dispose, in that order. If you have just called Abort, you need to wait a

14-32

Endpoints

CHAPTER

14

Communications

little bit, so you should pass these two methods to the AddDelayedAction function. For example, BailOut : func() begin ep.nextInputSpec := nil; ep:SetInputSpec(nil); ep:Abort(); AddDelayedAction(func() begin ep:Disconnect(); ep:Dispose(); end, [],1000); end; To close a connection gracefully, waiting for pending transmissions to complete, call Release. You must still call Dispose to deallocate the underlying endpoint structures. Abort endpoint :Abort() Aborts any pending I/O. If you are disposing of the endpoint, you must rst set endpoint.nextInputSpec to nil and then call SetInputSpec(nil), in that order. You can also simply call Abort to cancel a pending Connect or Listen call.
Note

Youll need to add an exception handler to your endpoint to ignore the user cancelled exception caused by the Abort call. u Disconnect endpoint :Disconnect() Closes a connection.

Endpoints

14-33

CHAPTER

14

Communications

Release endpoint :Release() Closes a connection after waiting for all pending transmissions to complete. Dispose endpoint :Dispose() Deallocates the underlying endpoint structures.

AppleTalk Functions
A number of functions are provided for obtaining the addresses of other devices on the network.

Opening and Closing the AppleTalk Drivers


In order to access zone information, you need to rst open the AppleTalk drivers with OpenAppleTalk. When youre done, be sure to close the drivers with CloseAppleTalk. OpenAppleTalk OpenAppleTalk() Opens the AppleTalk drivers, returning zero if successful. If you get the error 12014, perhaps the drivers are already open. CloseAppleTalk CloseAppleTalk() Closes the AppleTalk drivers, returning zero if successful. If you get the error 10067, perhaps the drivers were never opened.

14-34

Endpoints

CHAPTER

14

Communications

Obtaining Zone Information


The Newton system has several functions for obtaining zone information. HaveZones HaveZones() Returns true if a connection exists and zones are available. Returns nil if there is no connection. GetMyZone GetMyZone() Returns the name of the current AppleTalk zone. GetZoneList GetZoneList() Returns an array containing strings of all the existing zones. GetNames GetNames(fromWhat) Returns a string or an array of names based on the fromWhat parameter. fromWhat A network address in the form name:type@zone.

If fromWhat is a string, GetNames returns a string; if fromWhat is an array, GetNames returns an array of names. Heres an example: userconfiguration.currentPrinter.printerName #4415501 "Idiot Savante:LaserWriter@RD1/ NewHaven-LocalTalk" GetNames(userconfiguration.currentPrinter.printerName) #4417791 "Idiot Savante"

Endpoints

14-35

CHAPTER

14

Communications

GetZoneFromName GetZoneFromName(fromWhat) Returns the zone name as a string based on the fromWhat parameter fromWhat For example: GetZoneFromName(userconfiguration.currentPrinter. printerName) #44184A9 "RD1/NewHaven-LocalTalk" NBPStartLookup NBPStartLookup(entity) Begins a lookup of network entities, as specied by the entity parameter. Returns zero if the lookup is successful; otherwise the error 12013 is returned. entity Species the type of entity to search for and the zones in which to search. A network address in the form name:type@zone.

For example, to look for LaserWriters in the current zone: NBPStartLookup("=:LaserWriter@*") NBPLookupCount NBPLookupCount() Returns the number of entities the currently running NBP lookup has found. NBPLookupCount() #20 8

14-36

Endpoints

CHAPTER

14

Communications

NBPGetLookupNames NBPGetLookupNames() Returns an array of names found by NBPLookup. NBPGetLookupNames() #44091D1 ["Lab Rat", "Idiot Savante", "No Berts", "Bones", "Shane's Very Own", "Shogun Tokugawa", "calvin's homework", "Wupatki"] NBPStopLookup NBPStopLookup() Terminates a lookup, returning zero if successful, or 10067 if not.

NetChooser Function
The Newton system implements a NetChooser, similar in function to the Macintosh Chooser, as part of the root view. You can use the function GetRoot().NetChooser:OpenNetChooser to display a list of entities from which the user can make a selection. NetChooser:OpenNetChooser NetChooser:OpenNetChooser(zone, lookupName , startSelection, who , connText, headerText, lookforText ) Displays the chooser view. zone lookupName startSelection who The pre-dened AppleTalk zone; specify nil for the current zone. The name of the entity to be looked up. The name of an entity to be selected as default. The name of the context that will do the notication; self specifies the current context.

Endpoints

14-37

CHAPTER

14

Communications

connText headerText lookforText

The string to be placed in the button that will select the service. The string to be placed in the title string, and also in possible notications. A string that informs the user what the chooser is trying to nd. The lookforText is appended to the string Looking for. This string is displayed while the list is being assembled, or when the user chooses Change Zone.

Heres an example: GetRoot().NetChooser:openNetChooser(nil,"=:LaserWriter@", nil, self, "Use printer, sir", "Printer", "printers"); This example will open the NetChooser view and use the lookforText string while the search is in progress.

Figure 14-1

14-38

Endpoints

CHAPTER

14

Communications

When the search has been completed, the NetChooser lls in the available choices.

Figure 14-2

To obtain the user s selection, you need to provide a method called NetworkChooserDone. This method should have the following format: myChooser:NetworkChooserDone(currentSelection, currentZone) currentSelection currentZone Heres an example: ChooserSample := { // open our network connection openNetworkScript: func() Returns the selected entity Returns the currently selected AppleTalk zone.

Endpoints

14-39

CHAPTER

14

Communications

begin GetRoot().NetChooser:openNetChooser(nil,"=:LaserWriter@", nil, self, "Use printer, sir", "Printer", "printers"); end, // called when the user selects an item networkChooserDone: func(currentSelection, currentZone) begin Print("Current Selection =" && currentSelection); Print("Current Zone =" && currentZone); end }; ChooserSample:OpenNetworkScript() #1A TRUE // select the network entity, close the Chooser "Current Selection = Idiot Savante" "Current Zone = RD1/NewHaven-LocalTalk"

Summary of Methods and Functions


This section contains a summary of the methods and functions described in this chapter. Instantiating the Endpoint endpoint : Instantiate( endpoint, options ) Establishing a Connection endpoint : Connect( address, options ) endpoint : Listen( options) Sending Data endpoint : Output( data, ags ) endpoint : OutputFrame( data, ags ) endpoint : FlushOutput()

14-40

Summary of Methods and Functions

CHAPTER

14

Communications

Receiving Data endpoint : SetInputSpec( inputSpec) endpoint : Input() endpoint : FlushInput() endpoint : Partial() endpoint :FlushPartial() Checking the Endpoint State endpoint : State() Changing and Adding Options endpoint : SetOptions( options) endpoint : GetOptions( options) Handling Exceptions endpoint : ExceptionHandler( error) Closing a Connection endpoint : Abort() endpoint : Disconnect() endpoint : Release() endpoint : Dispose() AppleTalk Functions OpenAppleTalk() CloseAppleTalk() HaveZones() GetMyZone() GetZoneList() GetNames(fromWhat) GetZoneFromName(fromWhat) NBPStartLookup(entity) NBPLookupCount() NBPGetLookupNames() NBPStopLookup() NetChooser Function NetChooser:OpenNetChooser( zone, lookupName , startSelection, who , connText, headerText, lookforText )

Summary of Methods and Functions

14-41

CHAPTER

15

Localizing Newton Applications

At the time of this books printing, available Newton devices support ROMs based on the English, German and Japanese languages. This chapter discusses how to support multiple languages and how to make use of localespecic user preferences to customize your applications handling of numbers, dates and times. This chapter also discusses how locale settings affect the set of dictionaries used by the system for handwriting recognition. The recognition section in this chapter presumes that you already have a basic understanding of handwriting recognition issues; if you have not done so already, you should read Chapter 6, Written Input and Recognition.

The International Frame


The settings in the Locale panel specify the set of conventions the Newton object system uses to interpret user input and display information. The user can specify values for the country, keyboard type, and paper size in this panel, which is shown in Figure 15-1.

The International Frame

15-1

CHAPTER

15

Localizing Newton Applications

Figure 15-1

The Locale settings in Preferences

The Country popup menu species the current locale bundle, which is a frame used to tailor the systems responses to match the conventions of a specied location. The values in this frame specify a variety of items, such as the set of dictionaries used for handwriting recognition, locally-popular formats for displaying currency values, and labels for commonplace entities. For example, the set of dictionaries used for handwriting recognition in the U.S. locale has an entry for the word color, while the corresponding entry in the set of dictionaries used for the United Kingdom locale is spelled colour. The Keyboard popup menu species the kind of keyboard to be used when displaying the oating keyboard to the user, as well as the mapping of buttons (keys) on the oating keyboard to appropriate key codes; this information is stored in the international frame. The Paper Size menu sets the default page format used for printing and faxing; this value is stored in the current locale bundle. When the user sets a locale, the system chooses the current locale bundle from an array of predened frames stored in the locales slot of the international frame. This frame is stored in the global variable international. Although you are welcome to look at the international frame in the Inspector, dont attempt to set its slots directly. The content of this frame is for internal use by the system only and is subject to change without notice. Besides, the truly interesting slots are in the currentLocaleBundle slot, which you can get and set using the global functions GetLocale and SetLocale, respectively. Subsequent sections in this chapter describe how to get and set values in the current locale bundle.

15-2

The International Frame

CHAPTER

15

Localizing Newton Applications

How Locale Affects Recognition


As the user changes settings in the Locale panel, the set of dictionaries used for word recognition also changes. In addition to changing the set of enumerated dictionaries used for recognition, changing locales changes the set of lexical dictionaries used to specify formats for dates, times and numbers. Because the dictionaries vary in size, the amount of RAM used for system dictionaries varies as the set of dictionaries in use changes; however, this variation does not change the amount of RAM available to your application. For more information about dictionary-based recognition, see the Using Dictionaries section of Chapter 6, Written Input and Recognition.

Examining the Current Locale Bundle


The global function GetLocale returns the current locale bundle frame. It is recommended that you use the GetLocale function rather than accessing this frame directly. The rest of this section describes the slots in the current locale bundle and provides examples of their values for various locales.

Recognition Slots in the Current Locale Bundle


This section describes slots in the current locale bundle that are used by the recognition system. Enumerated Dictionaries This section describes slots storing arrays of enumerated dictionaries in the current locale bundle. wordsDictionary The main dictionary used for word recognition. recogCitiesDictionary The system-supplied enumerated dictionary listing names of cities in the current locale. recogCompaniesDictionary The system-supplied enumerated dictionary listing names of companies in the current locale.

The International Frame

15-3

CHAPTER

15

Localizing Newton Applications

recogStatesDictionary The system-supplied enumerated dictionary listing names of states and provinces in the current locale. recogStatesAbbrevsDictionary The system-supplied enumerated dictionary listing common abbreviations for names of states or provinces in the current locale. Lexical Dictionaries This section describes slots storing lexical dictionaries in the current locale bundle that are used for stroke recognition. recogTimeDictionary The lexical dictionary used for recognizing time substrings commonly encountered in the current locale; a substring is an element of the complete string. recogPhoneDictionary The lexical dictionary used for recognizing phone number substrings commonly encountered in the current locale; a substring is an element of the complete string. recogDateDictionary The lexical dictionary used for recognizing date substrings commonly encountered in the current locale; a substring is an element of the complete string. recogNumberDictionary The lexical dictionary used for recognizing number substrings commonly encountered in the current locale; a substring is an element of the complete string.

String Slots in the Current Locale Bundle


This section describes slots in the current locale bundle that are used to display locale-specic strings. The strings stored in these slots vary according to the locale.

15-4

The International Frame

CHAPTER

15

Localizing Newton Applications

Your application can reference these slots directly to use the strings stored here as labels for text or elds in your application. You should never set the values of these slots directly except in your own custom locale bundle. postalCodeLabel A string used to label postal codes. For example, the built-in Names application uses this slot to display the string "Zip Code" in the U.S. locale and the string "Post Code" in the Australia locale. An array of strings used to label items ordinally; for example, "First", "Second" and so on. An array of short strings used to label items ordinally; for example, "1st", "2nd" and so on. The string used to label distances. For example, this value is "miles" in the U.S. locale and "kilometers" in the Canada locale.

longOrdinals shortOrdinals distanceLabel

distanceMeasure The unit of measure used for distances. For example, this value is miles in the U.S. locale and kilometers in the Canada locale. This value is used by the built-in World Clock application to display the distance between two cities in a format appropriate to the user s locale; your application can use it also. distanceLabelShort The short version of the string used to label distances. For example, this value is "km" as opposed to the corresponding distanceLabelLong value of "kilometers". title The string that identies this locale bundle; useful mainly for debugging purposes. regionLabel The string used to label regions. For example, this value is "State" in the U.S. locale and "Province" in the Canada locale. cityLabel The string used to label cities. For example, this value is "City" in the U.S. locale and "Town" in the United Kingdom locale.

The International Frame

15-5

CHAPTER

15

Localizing Newton Applications

Date Strings These slots contain strings used by the system in the graphical representation of various date values. The strings stored in these slots vary according to the locale. Rather than using these values directly, you generally would use the appropriate dateTimeStrSpec to format the output of functions that return date information. However, your application can reference these slots directly to use the strings stored here as labels for text or elds in your application. You should never set the values of these slots directly except in your own custom locale bundle. longDateFormat The frame containing strings for the graphical representation of the elements of the long (verbose) date format.This frame contains the slots listed immediately following. versionNumber For internal use only. longDofWeek An array of strings representing full-text names of the days of the week; for example, "Sunday", "Monday", "Tuesday" and so on. abbrDofWeek An array of strings representing abbreviated names of the days of the week; for example, "Sun", "Mon", "Tue" and so on. terseDofWeek An array of strings representing shorter abbreviations of names of days than are specied in the abbrDofWeek slot; for example, "Su", "Mo", "Tu" and so on. shortDofWeek An array of strings representing single-letter abbreviations of names of the days of the week; for example, "S", "M", "T" and so on.

15-6

The International Frame

CHAPTER

15

Localizing Newton Applications

longMonth An array of strings representing full-text names of the months of the year; for example, "January", "February", "March" and so on. abbrMonth An array of strings representing abbreviated names of the months of the year; for example, "Jan", "Feb", "Mar" and so on. longDateOrder A dateTimeStrSpec value describing the order in which the elements of a long date are to appear; for example, month/ day/year ("January 31, 1994") as opposed to day/month/year ( "31 January 1994"). dayLeadingZ For internal use only. longDateDelim An array of strings used to represent the character separating the elements in the graphical representation of a long date string; for example, the string ", " (comma-space) used in the long date string "January 31, 1994". The system automatically selects a delimiter from this array according to the relative positions of the string elements to be separated. The 0th array element precedes the date string; the rst element species the delimiter to be placed between the rst and second elements in the date string; the second element in the array species the delimiter used to separate the second and third elements in the date string; and so on.

The International Frame

15-7

CHAPTER

15

Localizing Newton Applications

shortDateFormat The frame containing strings for the graphical representation of the elements of all date strings other than those in the longDateFormat format.This frame contains the slots listed immediately following. versionNumber For internal use only. shortDateOrder A dateTimeStrSpec value describing the order in which the elements of a short date are to appear; for example, day/ month/year ( "31/1/94") as opposed to month/day/year ( "1/31/94"). shortDateDelim An array of strings used to represent the character separating the elements in the graphical representation of a short date string; for example, the string "/" (forward slash) used in the short date string "1/31/94". The system automatically selects a delimiter from this array according to the relative positions of the string elements to be separated. The 0th array element precedes the date string; the rst element species the delimiter to be placed between the rst and second elements in the date string; the second element in the array species the delimiter used to separate the second and third elements in the date string; and so on. dayLeadingZ A value of kLeadZero species that a leading zero is to be prexed to representations of single-digit day values in short dates; for example, the 0 in 11/01/94. A value of kNoLeadZero species suppresses the use of the leading zero prex.

15-8

The International Frame

CHAPTER

15

Localizing Newton Applications

monthLeadingZ A value of kLeadZero species that a leading zero is to be prexed to representations of single-digit month values in short dates; for example, the 0 in 01/11/94. A value of kNoLeadZero suppresses the use of the leading zero prex. yearLeadingZ A value of kLeadZero species that a leading zero is to be prexed to representations of single-digit year values in short dates; for example, the 0 in 12/12/04. A value of kNoLeadZero suppresses the use of the leading zero prex. Time Strings These slots contain strings used by the system in the graphical representation of various time values. The strings stored in these slots vary according to the locale. Rather than using these values directly, you generally would use the appropriate dateTimeStrSpec to format the output of functions that return time information. You should never set the values of these slots directly except in your own custom locale bundle. timeFormat The frame containing strings for the graphical representation of the elements of time formats. This frame contains the slots listed immediately following. versionNumber For internal use only timeSepStr1 The string used to represent the character separating the rst and second elements in the graphical representation of a time

The International Frame

15-9

CHAPTER

15

Localizing Newton Applications

string; for example, the string "." (period) used in the time string "23.59:59". timeSepStr2 The string used to represent the character separating the second and third elements in the graphical representation of a time string; for example, the string ":" (colon) used in the time string "23.59:59". morningStr The string used to annotate times from midnight to just before noon for a 12hour clock cycle; for example, the string " am" (space-am) used in the time string 8:00 am. eveningStr The string used to annotate times from noon to just before midnight for a 12-hour clock cycle; for example, the string " pm" (space-pm) used in the time string 8:00 pm. suffixStr The string used as a sufx for graphical representations of times for a 24-hour clock cycle. This slot is not currently used by the MessagePad; however, it might contain, for example, the string " GMT" to indicate the use of Greenwich Mean Time. hourLeadingZ A value of kLeadZero species that a leading zero is to be prexed to representations of single-digit hour values. A value of kNoLeadZero suppresses the use of the leading zero prex. minuteLeadingZ A value of kLeadZero species that a zero is to be prexed to representations of single-digit minute values. A value of

15-10

The International Frame

CHAPTER

15

Localizing Newton Applications

kNoLeadZero suppresses the use of the leading zero prex. secondLeadingZ A value of kLeadZero species that a zero is to be prexed to representations of single-digit second values. A value of kNoLeadZero suppresses the use of the leading zero prex. timeCycle A value of kCycle12 species the use of a twelve-hour clock cycle; the value kCycle24 specifies the use of a 24-hour clock cycle. midNightForm The value kUseHour0 species the representation of midnight as the numeric string "00:00".The value kUseHour12 species the representation of midnight as the numeric string "12:00". The value kUseHour24 specifies the representation of midnight as the numeric string "24:00". noonForm The only valid value is kUseHour12, which species the representation of noon as the numeric string "12:00" Numeric Strings These slots contain strings used by the system in the graphical representation of various numeric values. The strings stored in these slots vary according to the locale. Rather than using these values directly, use the appropriate dateTimeStrSpec to format the output of functions that return numeric data. You should never set the values of these slots directly except in your own custom locale bundle.

The International Frame

15-11

CHAPTER

15

Localizing Newton Applications

numberformat

The frame containing strings for the graphical representation of the elements of numeric formats. This frame contains the slots listed immediately following. versionNumber For internal use only decimalpoint The string used to represent the decimal character in the graphical representation of a numeric string; for example, the string "." (period) used in the currency string "$123.45". groupSepStr The string used to represent the character separating the groupings of numbers in the graphical representation of a numeric string; for example, the string "," (comma) used in the numeric string "1,234". groupWidth The number of characters in each grouping of numeric characters separated by the groupSepStr character; for example, the string "123,456,789" is separated in groups of three. minusPrefix The string used as a prex for graphical representations of negative numbers; for example, the minus sign ( -) in the string "-123". minusSuffix The string used as a sufx for graphical representations of negative numbers; for example, the minus sign ( -) in the string "123-".

15-12

The International Frame

CHAPTER

15

Localizing Newton Applications

currencyPrefix The string used as a prex for graphical representations of currency values; for example, the dollar sign ($) in the string "$123". currencySuffix The string used as a sufx for graphical representations of currency values; for example, the dollar sign ($) in the string "123$", as used for the locale Canada (French locale). decimalLeadingZ A value of kLeadZero species that a zero is to be prexed to representations of single-digit decimal values; for example, the 0 in the string "$0.12". A value of kNoLeadZero suppresses the use of the leading zero prex.

Other Slots in the Current Locale Bundle


These slots are also contained in the current locale bundle. _proto The locale bundle from which this frame inherits default attributes. Not all locale frames have this slot.

postalCodeNumeric Has the value TRUE if postal code eld accepts numeric input only; for example, in the U.S. locale, postal codes do not include alphabetic characters. versionNumber For internal use wordBreakTable For internal use; the word-selection table used to nd word boundaries when selecting words. lineBreakTable For internal use; the word-selection table used to nd word boundaries when breaking lines of text.

The International Frame

15-13

CHAPTER

15

Localizing Newton Applications

defaultPaperSize Species the default paper size to be used when formatting pages for printing and faxing; valid values are 'eightByEleven and 'a4. keycodeMapping Species the Macintosh-style 'kchr' resource used to map keys on the oating keyboard to appropriate keycodes when the application is compiled by NTK.

Customizing the Current Locale Bundle


When the system starts up, it loads from ROM the locale bundle specied by the user settings in the Locale panel and stores it in the international frames currentLocaleBundle slot. The system caches subsequent user changes that affect the RAM representation of the current locale bundle. Because the current locale settings are actually a combination of the values present in the current locale bundle and the values stored in the cache, you cannot modify the current locale bundle directly. If you do, your changes may take effect temporarily but may be lost if the system is reset or the cache is ushed. In order to change settings in the current locale bundle, you need to replace it with one that replicates the slot values you wish to preserve and changes the values of those slots you need to modify. The best way to do this is to dene in your custom locale bundle a _proto slot that references one of the existing locale bundles. This approach ensures that your custom locale bundle has the full complement of required slots, including those storing the lexical dictionaries used for handwriting recognition, which you cannot create. s WARNING Your custom bundles _proto slot must ultimately reference a system-supplied locale bundle. s

15-14

The International Frame

CHAPTER

15

Localizing Newton Applications

Creating a Custom Locale Bundle


To create your applications custom locale bundle, use the FindLocale function to return from the locales array the frame to be referenced by your custom locale bundles _proto slot. Your custom locale bundle is simply a frame that includes this _proto reference and any additional slots that you wish to dene to override the values of those inherited from the prototype. Your custom locale bundle should look like the code in the following example. usLocaleBundle := :FindLocale("U.S."); myLocaleBundle := { _proto: usLocaleBundle, // add slots to be modified title: "myLocaleBundle:PIEDTS", } The FindLocale function accepts as its argument a string value specifying the name of the locale bundle it is to return. This function returns from the locales array the bundle having this value in its title slot.Your custom locale bundle needs to have a title slot of its own, as well. The string stored in this slot must be unique within the locales array. In the preceding code example the myLocaleBundle frame is based on the U.S. locale bundle. It overrides one slot, the title slot, to create its own name, myLocaleBundle:PIEDTS, but implements no functional changes to the locale. To make changes to the locale bundle, you can add your own slots in place of the comment that says // add slots to be modified. When creating the string for your bundles title slot, you need to take appropriate precautions to avoid name clashes. The problems associated with creating a unique name string for a locale bundle are similar to those you might encounter when creating a name for a soup; for suggestions regarding the creation of unique name strings, see the Naming Soups section in Chapter 7, Data Storage and Retrieval,

The International Frame

15-15

CHAPTER

15

Localizing Newton Applications

Adding the Bundle to the Locales Array


Once you have created your locale bundle, you need to make it available to the system by using the system-supplied AddLocale function to install it in the locales slot. The following code sample shows how to pass the previously created locale bundle myLocaleBundle to this function. :AddLocale(myLocaleBundle);

Setting the New Locale


The SetLocale function searches for a specied bundle in the international frames locales slot and installs that bundle in the international frames currentLocaleBundle slot. This function accepts as its argument a string naming the bundle to be installed. The following code example shows how to use the SetLocale function to install the custom locale frame created in the previous examples in this section; recall that the name of this bundle is "myLocaleBundle:PIEDTS" as stored in its title slot. SetLocale("myLocaleBundle:PIEDTS");

Removing the New Locale Bundle


At an appropriate time, you may need to remove the custom locale bundle you have installed. As with any shared data, what is appropriate is left up to you, the developer, because it can be difcult to determine whether other applications are using your bundle. Even if your own application is the only one using the custom locale bundle, it can be difcult to determine whether to remove it. You wouldnt necessarily want to install it every time the application opened and remove it every time the application closed. Its also problematic to remove your bundle when the application is removedthere is currently no way to tell the difference between removing the application permanently and just ejecting the PCMCIA card on which it resides. Watch for future guidelines from PIE DTS on cleaning up shared data.

15-16

The International Frame

CHAPTER

15

Localizing Newton Applications

For the purposes of discussion, assume that you have determined very clear-cut circumstances under which it is appropriate to remove your custom locale bundle. You can use the system-supplied RemoveLocale function to do so. The RemoveLocale function accepts as its argument a string value specifying the name of the locale bundle it is to remove. The following code sample shows how to pass the title string from the myLocaleBundle frame to this function. :RemoveLocale("myLocaleBundle:PIEDTS");

Summary: Customizing Locale


The following code sample summarizes the points discussed in this section. // get a bundle to proto from usLocaleBundle := :FindLocale("U.S."); // define my custom locale bundle myLocaleBundle := { _proto: usLocaleBundle, // add slots to be modified here title: "myLocaleBundle:PIEDTS", } // add myLocaleBundle to international.locales array :AddLocale(myLocaleBundle); // install myLocaleBundle as the current locale bundle SetLocale("myLocaleBundle:PIEDTS"); // To remove the bundle, pass its title to RemoveLocale :RemoveLocale("myLocaleBundle:PIEDTS");

The International Frame

15-17

CHAPTER

15

Localizing Newton Applications

Localized Output
Your application can make use of locale-specic user preferences to customize your applications handling of numbers, dates and times. In addition to using information available from the current locale bundle, your application can use the utility functions described here to display localized strings representing dates, times and monetary values.

Date and Time Values


The system provides several utility functions that return date and time values as strings formatted according to the format specication passed as one of their arguments. The GetDateStrSpec function is used to create the format specication passed to these functions. A date or time format specication is an array, the elements of which are themselves two-element arrays. The rst element in each two-element array is a constant specifying the item to be displayed and the second element is a constant specifying the format in which that item is displayed. For example, the two-element array [kElementDayOfWeek, kFormatAbbr] specifies that the day in a date string is to be displayed in abbreviated format, such as Wed. On the other hand, the two-element array [kElementDayOfWeek, kFormatLong] species that the day of the week is to be displayed in long format, such as Wednesday. The order in which date elements appear is specied by values stored in the current locale bundle. The longDateOrder slot stores the format specication for the order of all dates except short dates. The format specication for short dates is stored in the current locale bundles shortDateOrder slot. Times always appear in hour/minute/seconds order, although you can use format specications to vary the display of individual elements and delimiters in the time string. The delimiters used to separate the various elements of the date or time string are retrieved from the current locale bundle.

15-18

Localized Output

CHAPTER

15

Localizing Newton Applications

Formatting Date and Time Values


This section describes how to use format specications to specify the manner in which date and time strings are displayed by the functions that accept them. The following code example uses system-supplied constants to build an array of [element, format] pairs specifying the output of a date string. The complete set of constants is listed in the section Date and Time String Specication Constants, later in this chapter. This array is supplied as the argument to the GetDateStrSpec function, which returns the format specication passed to the LongDateStr function. The LongDateStr function formats the current time (returned by the Time function) as specied by the format specication. // at compile time, define my array of // element and format pairs in Project Data myArray:= [ [kElementYear, kFormatNumeric],// year [kElementDay, kFormatNumeric],// day of month [kElementMonth, kFormatLong],// name of month [kElementDayOfWeek, kFormatLong]// day of week ]; // create the formatSpec // this spec returns a string like February 1, 1994theSpec:= GetDateStringSpec(myArray); // later on, at run time... // initialize an evaluate slot with theSpec mySpec := theSpec; // get a value to format theTime:= Time(); // pass the time and the format to LongDateStr LongDateStr(theTime,mySpec);

Localized Output

15-19

CHAPTER

15

Localizing Newton Applications

This example is deliberately verbose for purposes of illustrating how to build a format specication array. For commonly-used format specications, the system denes formats that can be passed directly to the functions that accept format specications. These formats are stored in the global variable ROM_dateTimeStrSpecs; to use one of these values, access the appropriate slot by dereferencing ROM_dateTimeStrSpecs with a dot operator, as in the following example. // a more succinct approach LongDateStr(Time(),ROM_datetimestrspecs.longDateStrSpec); Using these predened format specications also saves you the trouble of having to dene them at compile time and initialize slots with the compile time variables at run time. The format specications available from the ROM_dateTimeStrSpecs global variable are listed in Table 15-1.

Table 15-1 Slot

Format specications in ROM_dateTimeStrSpecs global Note Example of format

longDateStrSpec abbrDateStrSpec yearMonthDayStrSpec yearMonthStrSpec dayStrSpec monthDayStrSpec numericDateStrSpec numericMDStrSpec numericYearStrSpec longMonthStrSpec abbrMonthStrSpec

1 1 1 1 1 1 2 2 1,2 1 1

"Wednesday, July 22, 1992" "Wed, Jul 22,1992" "July 22, 1992" "July 1992" "Wed, Jul 22" "July 22" "7/22/92" "7/22" "1992" "July" "Jul"
continued

15-20

Localized Output

CHAPTER

15

Localizing Newton Applications

Table 15-1 Slot

Format specications in ROM_dateTimeStrSpecs global (continued) Note Example of format

numericDayStrSpec longDayOfWeekStrSpec abbrDayOfWeekStrSpec longTimeStrSpec shortTimeStrSpec shortestTimeStrSpec hourStrSpec minuteStrSpec secondStrSpec

1,2 1 1 3 3 3 3 3 3

"22" "Wednesday" "Wed" "10:40:59 AM" "10:40 AM" "10:40" "10" "40" "59"

1. Argument to LongDateStr function 2. Argument to ShortDateStr function 3. Argument to TimeStr function

The kIncludeEverything Constant If you want to use the default format for time or date strings as specied by the current locale bundle, you can pass the kIncludeEverything constant to the functions LongDateStr, ShortDateStr and TimeStr. Youll get the results summarized inTable 15-2.

Table 15-2 Function

Using the kIncludeEverything constant Format of output

LongDateStr ShortDateStr TimeStr

year, month, day, day of week in locales default format year, month, day in locales default short date format hour, minute, second, AM/PM, and sufx

Localized Output

15-21

CHAPTER

15

Localizing Newton Applications

Formatted Numeric Strings


The FormattedNumberStrfunction converts a oating-point value into a number string that is formatted according to the format specied by its arguments and the values in the current locale bundle that govern the representation of numeric strings. The interface to this function looks like this: FormattedNumberString(number, format ); The number argument is the oating-point value to be converted to a string. The format argument species the notation to be used in the formatted number string. This argument can have the values specied in Table 15-3
Table 15-3 Value Values of format parameter Format Example

%f %e %E %g %G

Decimal notation Exponential notation Exponential notation w/ uppercase E Use shorter of %f or %e Use shorter of %f or %E

"123.456000" "1.234560e+02" "1.234560E+02" n/a n/a

For example, formattedNumberStr(23453, "%f") returns "23,453.000000" as the formatted output string. You can place a decimal point and a numeric value after the % symbol to indicate how many decimal places to display; for example, the value %.2f indicates that the formatted output string is to display two decimal places, as shown in the following code fragment. formattedNumberStr(23453, "%.2f") returns "23,453.00" as the formatted output string.

15-22

Localized Output

CHAPTER

15

Localizing Newton Applications

Miscellaneous Date and Time Functions


The system supplies a number of additional functions that return date and time values from the system clock. These functions do not format their output, but it can be passed to the FormattedNumberStr function to produce a string appropriate for display to the user. For a complete description of these functions, see the Function Reference section at the end of this chapter.

Currency Values
Currency strings reect localized formatting characteristics that distinguish them from other number strings. They typically display a prex or sufx indicating their denomination and may additionally require one indicating whether the amount is negative. Currency strings must also adhere to regional conventions for grouping numbers, for the delimiter used to indicate these groupings, and for the character used to represent the decimal point. These values are stored in a frame in the current locale bundles numberFormat slot; for descriptions of all of the values stored in this slot, see the section Numeric Strings, earlier in this chapter. For example, the currencyPrefix slot stores the value $ for the U.S. locale and for the United Kingdom locale. The currencySuffix slot stores a string that follows a monetary value in some locales; for example, in the locale Canada (French locale) this slot stores the value $.

Formatting Currency Values


You can use the appropriate prexes or sufxes from the numberFormat frame in conjunction with FormattedNumberString function to display currency values. The following code fragment uses the FormattedNumberStr function to convert a floating-point value into a number string that can be displayed as a local currency value.

Localized Output

15-23

CHAPTER

15

Localizing Newton Applications

// this function takes a floating point number and // returns it as a localized currency string GetCurrencyString: func(x) begin getLocale().numberFormat.currencyPrefix & formattedNumberStr(x, "%0.2f") & getLocale().numberFormat.currencySuffix; end; s WARNING The value passed to FormattedNumberString (and therefore to GetCurrencyString) must be a oating-point value. s

Supporting Multiple Languages


To effectively support multiple languages, your application needs to discover the ROM version of the Newton device on which it is running. Merely testing the value of the title slot in the current locale bundle can yield unreliable results if another application has installed a locale bundle in a language other than the one implemented in ROM. Consider, for example, the case in which another application has installed a U.S. locale bundle on a Newton device having a German-language ROM. Your application might be running in English, while all of the messages from the ROM would appear in German. The correct way to discern the systems native language implementation is to use the system-supplied GetLanguageEnvironment function. This function returns a value indicating the native language for which the ROMs on the current Newton device are implemented. This function is described in detail in the Function Referencesection, later in this chapter.

15-24

Supporting Multiple Languages

CHAPTER

15

Localizing Newton Applications

Function Reference
This section describes functions and methods useful for implementing regional customization of application data. Some of the functions described here are used to install or remove a custom locale bundle. Others return information from the ROM and the current locale bundle. This section also describes functions that return date and time values from the system clock some of these functions return a formatted string; others, a system value representing the date or time information. The remaining functions described here are utilities used to regionalize the format of numeric strings. AddLocale :AddLocale(theLocaleBundle) Installs the specied frame in the locales array. theLocaleBundle
Note

The locale bundle to be installed in the locales array

This function may not be dened in ROM it may be supplied by NTK. u Date Date(time) Returns the specied time as a date frame having the slots described in Table 15-4. The formats of individual strings in the date frame are determined by values in the current locale bundle. time The time as returned by the Time function

Function Reference

15-25

CHAPTER

15

Localizing Newton Applications

Table 15-4 Slot name

Date frame slots and values Example value

year month date dayofweek hour minute second DateNTime

1993 1 24 0 (Sunday=0, Saturday=6, and so on) 15 38 52

DateNTime(time) Returns the specied time as a string having the format MM/DD /YYYY HH : MM; for example, 10/23/1993 12:45. The formats used for individual elements and delimiters in the returned string are determined by values in the current locale bundle. time FindLocale :FindLocale(titleString) Returns from the locales array the frame having the specied string in its title slot. Use this function to get a frame to be referenced by your custom locale bundles _proto slot. titleString The name of the locale bundle to be retrieved, as specied by the string in the bundles title slot The time as returned by the Time function

Note

This function may not be dened in ROM it may be supplied by NTK. u

15-26

Function Reference

CHAPTER

15

Localizing Newton Applications

FormattedNumberStr FormattedNumberStr(number, format ) Returns a formatted string representation of a oating-point value according to the format specied by the format argument and the values in the current locale bundle that govern the representation of numeric strings. This function is similar to (but not exactly like) the C function printf(). number format any numeric value, either oating point or integer. species a format string similar to those used with the C programming languages printf function. However, only the values %f, %e, %E, %g and %G produce any effect.

Table 15-5 Value

Values of the format parameter Format Example

%f %e %E %g %G
Note

Decimal notation Exponential notation Exponential notation w/ uppercase E Use shorter of %f or %e Use shorter of %f or %E

"123.456000" "1.234560e+02" "1.234560E+02" n/a n/a

The current version of the FormattedNumberStr function always returns a oating point number, even if you pass an integer for the number argument. This will be xed in a subsequent version of this function. It is NOT sufcient to strip the last character since some countries put the sign of the number at the end. u

Function Reference

15-27

CHAPTER

15

Localizing Newton Applications

Note

You can place a decimal point and a numeric value after the % symbol to indicate how many decimal places to display; for example, the value %.2f indicates that the formatted output string is to display two decimal places. u GetDateStringSpec GetDateStringSpec(formatArray) Returns a date or time format specication which is passed to one of the following built-in functions: LongDateStr, ShortDateStr, or TimeStr. Because the GetDateStrSpec function is available at compile time only, its return value must be stored in a compile time variable used to initialize an evaluate slot at run time. The slot value is then passed to date and time functions requiring the format spec at run time. The order in which elements of a date or time string appear is not specied by the format specication, but by values stored in the current locale bundle. The delimiters used to separate the various elements of the date or time string are also not specied in the format spec, but retrieved from the current locale bundle. formatArray an array of two-element arrays. Each two-element array lists a single date or time element and a corresponding format to be used to display that element. For example: [[kElementMonth,kFormatAbbr], [kElementDay, kFormatNumeric]] The two-element subarrays can appear in any order; the order in which elements of the date or time string appear is dened in the current locale bundle, not by the format spec. See the section Date and Time String Specication Constants, later in this chapter, for a complete listing of the values you can use for the date or time element in each subarray, and an example of each as returned by one of the built-in date or time functions.

15-28

Function Reference

CHAPTER

15

Localizing Newton Applications

Note

This function is available in the Newton Toolkit development environment at compile time only. It is not available at run time. u GetLanguageEnvironment GetLanguageEnvironment() Returns a value indicating the language for which the ROM in the current Newton device is implemented. These values are summarized in Table 15-6.

Table 15-6 Language

ROM language codes Value

English French German Japanese


Note

0 1 2 14

This function may not be dened in ROM it may be supplied by NTK. u GetLocale GetLocale() Returns the frame installed in the currentLocaleBundle slot of the international frame. For more information, see the description of the current locale bundle in the section Examining the Current Locale Bundle, earlier in this chapter.

Function Reference

15-29

CHAPTER

15

Localizing Newton Applications

HourMinute HourMinute(time) Returns the value of the time argument as a string in the format HH :MM; for example, 12:45. The formats used for individual elements and delimiters in the returned string are determined by values in the current locale bundle time LongDateStr LongDateString(time,dateStrSpec) Returns the date as a string in the kLongDateFormat dened for the current locale bundle; for example "Saturday, May 8, 1993". time dateStrSpec The time as returned by the Time function A format specication as returned by the GetDateStringSpec function. See the description of the GetDateStringSpec function for more information on available formatting options. The time as returned by the Time function

RemoveLocale :RemoveLocale(localeBundleTitle) Removes the specied locale bundle from the locales array. localeBundleTitle The name of the locale bundle to be retrieved, as specied by the string in the bundles title slot

SetLocale SetLocale(localeBundleTitle) Searches the locales array for the specied locale bundle and installs that bundle in the international frames currentLocaleBundle slot. localeBundleTitle A string naming the bundle to be installed; this function installs from the locales array the frame having this string in its title slot.

15-30

Function Reference

CHAPTER

15

Localizing Newton Applications

Note

This function may not be dened in ROM it may be supplied by NTK. u SetLocation worldClock:SetLocation(newLocation) Sets the I'm Here location in Time Zones. newLocation A frame specifying a name, latitude, longitude, country, and area code; country and area code are optional.

SetTime SetTime(time) Sets the time of the system clock. This function always returns NIL. time The time to which the system clock is to be set, specied as the number of minutes elapsed since midnight, January 1, 1904

ShortDate ShortDate(time) Returns the date as a string in the format Day MM/DD ; for example, "Fri 12/25". The formats used for individual elements and delimiters in the returned string are determined by values in the current locale bundle. time ShortDateStr ShortDateStr(time,dateStrSpec) Returns the date as a string in the kFormatNumericDate format; for example, "5/8/93". The time as returned by the Time function

Function Reference

15-31

CHAPTER

15

Localizing Newton Applications

time dateStrSpec

The time as returned by the Time function A format specication as returned by the GetDateStringSpec function. See the description of the GetDateStringSpec function for more information on available formatting options.

StringToDate StringToDate(dateString) Parses a string for date or time information and returns the result as the number of minutes passed since midnight, January 1, 1904. The formats used for individual elements and delimiters in the returned string are determined by values in the current locale bundle. dateString The string to be parsed. If the year is omitted from the string, the current year is assumed. The following types of date/time strings can be parsed (the case of letters is not signicant): "12:05 a.m. sun, jan 2, 1992" "jan 2, 1992" "12:05 1/2/92" "1/2/92" "12:05mon,1/2" "1/2" To get a date frame from a string use the following line of code. (For more information about date frames, see the description of the Date function.) Date(StringToDate(dateString)) StringToTime StringToTime(timeString) This function is just like StringToDate, except that it parses a string for time information only, ignoring any date information in the timeString string,

15-32

Function Reference

CHAPTER

15

Localizing Newton Applications

and returns the result as the number of minutes passed since midnight, January 1, 1904. The formats used for individual elements and delimiters in the returned string are determined by values in the current locale bundle. timeString The string to be parsed for time information only; any date information in this string is ignored.

Ticks Ticks() Returns a number of ticks. A tick is one sixtieth of a second. There is no dened starting time for ticks; they are used to measure durations of time. So you would typically call Ticks, do something, or wait, and then call Ticks again and compare the values to see how much time has passed. Time Time() Returns the time in minutes as an integer. This is the number of minutes passed since midnight, January 1, 1904. TimeInSeconds TimeInSeconds() Returns the time in seconds as an integer. This is the number of seconds passed since midnight, January 1, 1993. TimeStr TimeStr(time,timeStrSpec) Returns the specied time as a string in the format HH :MM:SS [AM|PM]; for example, "10:40:59 AM". time timeStrSpec The time as returned by the Time function A format specication as returned by the GetDateStringSpec function. See the description of the GetDateStringSpec function for more information on available formatting options.

Function Reference

15-33

CHAPTER

15

Localizing Newton Applications

TotalMinutes TotalMinutes(dateFrame) Returns the time in minutes since midnight, January 1, 1904, when passed a date frame have the same slots as described in the Date() function. (The dayofweek slot is actually not used.) You must pass in a date frame, or this function returns an error.

Date and Time String Specication Constants


This section contains several tables listing the system-supplied constants available for specifying the elements and formats of date and time strings. The system-supplied constants for specifying the elements of date strings are described in Table 15-7.

Table 15-7 Constant

Elements of date strings Element of string Example values

kElementNothing kElementDayOfWeek kElementDay kElementMonth kElementYear

no element day of the week date month year

displays no value Wednesday, Weds, W 22, 02, 2 July, Jul, J 1992

15-34

Function Reference

CHAPTER

15

Localizing Newton Applications

The system-supplied constants for specifying the elements of time strings are described inTable 15-8.

Table 15-8 Constant

Elements of time strings Element of string Example values

kElementHour kElementMinute kElementSecond kElementAMPM kElementSuffix

hour minute second AM/PM 24-hour clock indicator

12 33 59 AM, PM GMT

The system-supplied constants for specifying the format of date string elements are described inTable 15-9.

Table 15-9 Constant

Formats for date or time string elements Element of string Example of display

kDefault kFormatLong kFormatAbbr kFormatTerse kFormatShort kFormatNumeric

to be documented full-length abbreviated shortened abbreviation single-letter numeral

to be documented Wednesday Wed We W 1994

Function Reference

15-35

CHAPTER

15

Localizing Newton Applications

The system denes constants for several commonly-used format specications. These constants, described inTable 15-10, can be passed as arguments to the GetDateStringSpec function.

Table 15-10 Constant

Constants dening commonly-used format specications Example of display

kFormatLongDate kFormatAbbrDate kFormatNumericDate kFormatNumericYear kFormatLongMonth kFormatAbbrMonth kFormatNumericDay kFormatLongDayOfWeek kFormatAbbrDayOfWeek kFormatLongTime kFormatShortTime kFormatHour kFormatMinute kFormatSecond

"Wednesday, July 22, 1992" "Wed, Jul 22,1992" "7/22/92" "1992" "July" "Jul" "22" "Wednesday" "Wed" "10:40:59 AM" "10:40 AM" "10" "40" "59"

The kIncludeEverything Constant If you want to use the default format for time or date strings as specied by the current locale bundle, you can pass the kIncludeEverything constant to the functions LongDateStr, ShortDateStr and TimeStr. Youll get the results summarized inTable 15-2.

15-36

Function Reference

CHAPTER

15

Localizing Newton Applications

Table 15-11 Function

Using the kIncludeEverything constant Format of output

LongDateStr ShortDateStr TimeStr

year, month, day, day of week in locales default format year, month, day in locales default short date format hour, minute, second, AM/PM, and sufx

Summary of Functions
This section categorizes the date, time, locale and utility functions in this chapter according to task.

Locale Functions
These functions manipulate locale bundles. :AddLocale(theLocaleBundle) :FindLocale(titleString) GetLocale() :RemoveLocale(localeBundleTitle) SetLocale(localeBundleTitle)

Date and Time Functions


These functions return date or time information from the system clock. They are grouped into two categories: those that return formatted strings and those that do not.

Summary of Functions

15-37

CHAPTER

15

Localizing Newton Applications

Formatted Date/Time Functions


These functions return formatted date or time strings. Some of the functions here format the string according to a format specication supplied as one of their arguments; others format the string according to values stored in the current locale bundle. See the descriptions of individual functions for more information. Date(time) DateNTime(time) HourMinute(time) LongDateString(time, dateStrSpec) ShortDate(time) ShortDateStr(time, dateStrSpec) StringToDate(dateString) StringToTime(timeString) TimeStr(time, timeStrSpec)

Miscellaneous Date/Time Functions


These functions get and set system clock values. The date and time values are returned as system clock values, not as strings. SetTime(time) Ticks() Time() TimeInSeconds() TotalMinutes(dateFrame)

Utility Functions
These functions perform tasks related to the presentation of data in regionalized formats. FormattedNumberStr(number, format) GetDateStringSpec(formatArray) GetLanguageEnvironment() worldClock:SetLocation(newLocation) 32

15-38

Summary of Functions

CHAPTER

16

Supporting Newton Connection

Newton Connection is an application that runs on a Macintosh or Windows computer and allows you to backup data and programs from a Newton or load data and programs into a Newton. Newton Connection also allows the user to edit data or enter new data on the personal computer and then download the changed data to the Newton. Newton Connection is called Connection in this chapter. This chapter assumes you are familiar with the basic operation of Connection. See Connection documentation for information on that. All soups on a Newton are automatically saved to the personal computer when the user synchronizes Connection to the Newton. You, as the application developer, do not have to do anything to make that happen, other than placing your applications data in a soup. This soup data is written to a le called a synch le. If the Newton has a PCMCIA card installed at the time of synchronization, an additional synch le is created or updated that contains the soups stored on the card. Most applications have one soup, though some have more.

16-1

CHAPTER

16

Supporting Newton Connection

This chapter describes how to set up a Newton program so that a user can view and manipulate data for the program in Connection, and gives internal information on how Connection handles soup information. A Connection user can save data from the Newton in external les, and can also import data from external les. Parallel third party applications, such as calendars and address books, can use those les to cooperate with Newton. A calendar program running on the personal computer, for example, can collect appointments made on Newton. It can similarly make appointments on the Newton by writing a file that the Connection user can import.
IMPORTANT

You should not use any of the slot, attribute or type names dened by Connection for your own purposes. The results of doing so are unpredictable. You can nd the names dened by Connection in this chapter. s

How Connection Handles Soup Data


A synch le contains copies of all the soups in a single Newton store, including the meta data soup, sometimes called the directory soup. Each soup (other than the meta data soup) belongs to a particular application. Some applications may own several soups. Each sync le corresponds to a store on the Newton. Each soup that a user can read or modify with Connection has an entry in the meta data soup that tells Connection how to handle the data in the soup. Those entries are called meta data entries. A top-level slot within a meta data entry is called an item. Items are values, functions, or arrays of values or functions. Many of the items dene characteristics of the data used or displayed in Connection. An atomic characteristic of a single piece of data, such as its type or size, is called an attribute.

16-2

How Connection Handles Soup Data

CHAPTER

16

Supporting Newton Connection

At the same time that you develop your application, you should develop the meta data entry for the application. The meta data entry is written in NewtonScript. A meta data entry consists of data and functions. When you write the functions, you can use most, but not all, of the functions and operators that are available on the Newton. The available functions and operators are discussed in NewtonScript Functions Available for Use in Meta Data beginning on page 16-61. There are also a few additional functions that can be used only for Connection. Those are described in Newton Connection-Only Functions beginning on page 16-65. On the Macintosh, when a Connection user opens a synch le, or when synchronization nishes, Connection shows the Application Browser window, which you can see in Figure 16-1. The Application Browser shows a list of the Newton applications that have meta data entries in the meta data soup. Each meta data entry can have a slot that tells Connection the name that should be used in the Application Browser.

Figure 16-1

Application Browser

In the Microsoft Windows version of Connection, the user nds standard applications listed in the toolbar or the View menu, while non-standard applications are listed in the View/Extras menu.

How Connection Handles Soup Data

16-3

CHAPTER

16

Supporting Newton Connection

When the user opens one of the applications shown in the Application Browser or the menus, Connection shows a window that contains one row for each entry in the soups controlled by the application. This window is referred to as the Data Browser window, which you can see in Figure 16-2.

Figure 16-2

Data Browser

The meta data entry controls what data is contained in the rows, the order of the cells in each row, and the display of the data. The Data Browser lets the user use a search mechanism to lter which soup entries are displayed. Connection uses information from the meta data entry to test soup entries to determine whether or not the entry passes the search criteria. The user can specify the order of the rows by selecting a column to serve as the sort column. Once again, Connection uses information from the meta data entry to compare soup entries to determine their sort order. When the user opens a row of data from the Data Browser, Connection displays a window that lets the user edit the data in the frame. This window is referred to as a Detail Window. The meta data entry determines the contents of this window and the allowed editing operations.

16-4

How Connection Handles Soup Data

CHAPTER

16

Supporting Newton Connection

Figure 16-3

Detail Window

The user can request the creation of a new entry. The meta data entry can specify the initial contents of this new entry. Connection displays the new entry in a Detail Window, and the user can modify the new entry there. After editing data in a Detail Window, before any changes are actually made to the entry in its soup, the data is validated using functions and other information provided by the meta data entry. Similarly, before data is entered into soups using import operations, Connection can use information provided in the meta data entry to validate the data. When data is exported from or imported to soups, the meta data entry controls what data is exported or imported. Soups contain data frames called entries. These are simply NewtonScript frames and can contain any kind of data that can be stored on the Newton. The Data Browser and Detail Window display frames that contain only strings, which are called text frames. Items in the meta data entry convert entry frames into text frames. Other items convert text frames into data frames that Connection inserts into soups.

How Connection Handles Soup Data

16-5

CHAPTER

16

Supporting Newton Connection

Writing Meta Data to the Meta Data Soup


You should write your meta data entry to the meta data soup when you create your soup. Use the pre-dened constant ROM_MetaSoupName to refer to the meta data soup. The meta data soup only exists on the internal store. It will never exist on a card store, and you should not create one there. (The meta data soup on the internal store always exists.) You should make sure you arent adding over old entries. Here is some sample code that does that: // remove any old soup meta data entry then add the latest // probably should check version slot in meta data entry... local directorySoup := GetStores()[0]:GetSoup(ROM_MetaSoupName); if directorySoup then begin myCursor:=Query(directorySoup,{type:'index, indexPath:'soup, startKey: soupName, endTest: func(entry)NOT(StrEqual(entry.soup, soupName))}); while myCursor:Entry() do begin EntryRemoveFromSoup(myCursor:Entry()); myCursor:Next(); end; directorySoup:Add(Clone(MetaData)); end; You probably should check if the version has changed and, if it hasnt, leave the meta data alone. You should remove your meta data when you delete your soup. (You should not do this in your RemoveScript, however.)

16-6

How Connection Handles Soup Data

CHAPTER

16

Supporting Newton Connection

Meta Data Format


This section describes the syntax and semantics of the Meta Data Format version 2.0. Version 2.0 is a superset of version 1.0 and is used by versions 2.0 or later of Connection. Every soup that you want the user to be able to access through Connection should have a meta data entry in the directory soup. The meta data entry denes how Connection treats the data in the soup. You create a meta data frame and write it to the meta data soup from NewtonScript, usually when you create the applications soup. (See Writing Meta Data to the Meta Data Soup on page 16-6.) Some applications can have more than one soup. In that case, you usually need to have one meta data entry for each soup. One meta data entry is called the main meta data entry; the others are dependent meta data entries. (See ExportFilter beginning on page 16-43 for a way to deal with dependent soups that do not have meta data.) The top-level slots in a meta data frame are referred to as items. Items can be arrays, methods, frames, or individual slots. The sections following describe the items in detail. They are divided into groups of related items:
n

General Items beginning on page 16-13 include items that determine the internal and external names, specify a the version number, and a provide new entry frame. All applications need to specify the names. Moving Data Between Newton Soups and Connection beginning on page 16-15 includes items that convert soup entries into text frames and convert text frames into soup entries. All applications need to provide at least one item for converting text frames into soup entries. You need to provide at least one item that converts text frames into soup entries if you want the user to be able to edit entries or add entries in Connection. Controlling the Connection Windows beginning on page 16-25 includes items that control the Data Browser, Detail Window, and tab creation template window. All applications need to have the item that controls the appearance of the Data Browser. 16-7

Meta Data Format

CHAPTER

16

Supporting Newton Connection

Moving Data to and From External Files beginning on page 16-35 includes items that control moving data between Newton soups and les that can be used by desktop applications. Those les can either be in text format, which includes tab-delimited les, or native format, which is a more complex format that can specify any object that can exist on the Newton. You do not need to provide the items in this section unless you want to do that kind of conversion. Soup-Related Items beginning on page 16-51 includes items that Connection uses when it needs to create soups. That is relatively rare, and you do not have to provide these items unless you think Connection will need to create soups for your application. Multi-Soup Applications beginning on page 16-52 includes items that Connection needs when an application has more than one soup. That is relatively rare. Centralizing Denitions beginning on page 16-54 includes items that you can use to bring denitions used in other items together in one place, either because the denitions are used more than once or for documentation purposes. You do not have to use these items, but most applications do.

Table 16-1 shows all items. In the table:


n

The Slot Name column gives the slot name for the item. Note that case is not signicant. The Required column indicates whether or not the item is required. The Type column gives the NewtonScript data type for the item.

n n

16-8

Meta Data Format

CHAPTER

16

Supporting Newton Connection

Table 16-1 Slot Name

Meta data items Required Type Description

Soup

yes

string

The internal name of the data soup that this meta data entry controls. This name is never displayed to the user. See page 16-13. The name for the application soup that will appear in the Application Browser on the Macintosh or in the menus under Windows. See page 16-14. The developer-supplied version number of this meta data entry. See page 16-14. Used when creating new soup entries. See page 16-14. This method is called to generate a text version of an entry frame for display in a Data Browser window. See page 16-19. This method is called to generate a text version of an entry frame for display in a Detail Window. See page 16-20. This method is called after a user has edited an entry in the Detail Window and prior to the entry being inserted in a soup. See page 16-21.
continued

Name

yes

string

Version

no

integer

NewEntry BrowserExport

no yes 1

frame or method method

EditExport

no2

method

EditImport

no2

method

Meta Data Format

16-9

CHAPTER

16

Supporting Newton Connection

Table 16-1 Slot Name

Meta data items (continued) Required Type Description

Export

no

method

Only used if TabExport or EditExport or BrowserExport methods not present. See page 16-23. Only used if TabImport or EditImport methods not present. See page 16-24. This array is used to control the Data Browser window. See page 16-26. This array is used to control the Detail Window. See page 16-29. Used to specify the default width for the leftmost labels column of a Detail Window. See page 16-31. Used when ltering (searching) within the Data Browser window. See page 16-32. This array is used for controlling text format (sometimes called tab format) export and import. See page 16-34. This method is called to handle a text format export operation. See page 16-36.
continued

Import

no

method

DisplayInfo

yes 3

array of symbols or frames array of symbols or frames integer or method or symbol frame of functions

EditInfo

no

Column0Width

no

CompareScripts

no

ExportInfo

no

array of symbols or frames

TabExport

no

method

16-10

Meta Data Format

CHAPTER

16

Supporting Newton Connection

Table 16-1 Slot Name

Meta data items (continued) Required Type Description

TabImport

no

method

This method is called after Connection has read a text format record to create a frame in the format you use in your soup. See page 16-37. This method is called to convert a soup entry into native format. See page 16-39. This method is after Connection has read a native format entry. See page 16-40. This array is used for controlling Native and translator format export. See page 16-42. Called before exporting to native and text formats. See page 16-43. This method is called prior to inserting an entry in a data soup as a result of native and translator format import operations. See page 16-46. This method is called prior to entering an entry in a data soup for all import operations. See page 16-47. Used when pasting or opening a Data Browser. See page 16-51.
continued

NativeExport

no

method

NativeImport

no

method

NativeExportExceptions

no

array of symbols or frames method

ExportFilter

no

EntryValidation

no

method

ApplyCommands

no

method

DontCreateSoups

no

Boolean

Meta Data Format

16-11

CHAPTER

16

Supporting Newton Connection

Table 16-1 Slot Name

Meta data items (continued) Required Type Description

SoupIndicies

no

array

Used when pasting or opening a Data Browser to create the soup if necessary. See page 16-51. Used when pasting or opening a Data Browser to create the soup if necessary. See page 16-51. The presence of this item identies this as a main meta data entry. This is an array of strings, each string being an internal soup name of a dependent meta data entry. See page 16-53. If present and not nil, identies this meta data as a dependent meta data Entry. The symbol should correspond to the string specied in the soup item of the main meta data entry. See page 16-54. Used to functionally specify attributes. See page 16-54. Each individual frame is a default denition for an element in the displayInfo, editInfo, exportInfo, and/or nativeExportException s arrays. See page 16-55.
continued

SoupInfo

no

frame

Dependents

no4

array of strings

EditWith

no5

symbol

AttributeFunctions DefaultDefinitions

no no

frame of functions frame of frames

16-12

Meta Data Format

CHAPTER

16

Supporting Newton Connection

Table 16-1 Slot Name

Meta data items (continued) Required Type Description

EditTypes

no

frame of frames

This frame of frames is used to describe developerdened data types. Each individual frame denes one developer type. The name of the individual frame is the name of the developer type. See page 16-57.

1. If you do not include BrowserExport, you must include Export, unless this is a dependent meta data entry. Dependent meta data entries do not require either of those items. 2. If EditInfo exists, then either EditExport, BrowserExport, or Export and either EditImport or Import are required, except for in dependent meta data entries. Dependent meta data entries do not require any of those items. 3. DisplayInfo is not required for dependent meta data entries. 4. Dependents is required for main meta data entries that have dependents. 5. EditWith is required for dependent meta data entries.

General Items
The general items deal with:
n n n

The internal and external names The version number Specifying a new entry

Soup
The soup slot is a string that gives the name of the soup within the Newton. For example: soup: "SoupName:PIEDTS", Connection uses this name to nd out what soup this meta data is for; this is the internal name of that soup. In a sense, this could also be considered the name for this meta data entry.

Meta Data Format

16-13

CHAPTER

16

Supporting Newton Connection

Name
The name slot is a string that species the name that Connection displays for this soup. It is the name that appears in the Application Browser and the name that appears in the title bar of the Data Browser. You probably want Connection to give something more like the application name, since the soup name includes your unique registry information. For example, suppose the soup for your application is called "SoupName:PIEDTS", which might not be very meaningful to the user. You can use this slot to specify a more meaningful name in Connection: name: "My Application",

Version
The version slot gives the version number of this meta data frame. If you do not give this slot, the version number defaults to 1. You should change this number when you change the meta data for your application.

NewEntry
The newEntry slot contains either:
n

A frame that has the slots contained in a soup entry. This should be a frame in the format you use in your soup, not a text frame. A method whose return value is a frame that has the slots contained in a soup entry. This method takes one parameter, which is the store of the soup into which the entry will be placed.

When the Connection user uses the New Entry command to make a new entry, Connection calls DeepClone on the frame given in newEntry or, if newEntry is a method, calls the method and calls DeepClone on the result. It then adds that cloned entry to the soup and calls the appropriate export method to get a text frame that can be displayed in the Detail Window.

16-14

Meta Data Format

CHAPTER

16

Supporting Newton Connection

You can give default values or include constants or slot values in the new frame. This is particularly important for values that the user cannot create by editing the new frame in the Detail Window. If you do not include this item, Connection creates an empty frame for a new entry. In any case, Connection displays the new entry in a Detail Window. The format of the Detail Window is controlled by editInfo (see EditInfo beginning on page 16-29).

Moving Data Between Newton Soups and Connection


Connection uses text frames in the Data Browser and Detail Window. In a text frame, each slot that contains data you want to display contains a string. A text frame can have additional slots that contain data that will be used by your meta data functions. For example, you may want to add one that has the name originalFrame and contains a reference to the corresponding soup entry. (This is for your use and is optional. Connection preserves these additional slots whenever possible. These additional slots may not be present if the text frame being imported was tab imported.) The next section, Data Browser and Detail Window Flow of Control, discusses the sequence of events in bringing data to and from Connection. Two methods handle conversion from the soup entry format used in a synch le into text frames:
n

The BrowserExport method converts soup entries into text frames that are displayed in the Data Browser. The EditExport method converts soup entries into text frames that are displayed in the Detail Window.

You often want to use the text frame produced by the BrowserExport method in the Detail Window as well as the Data Browser. EditExport is a separate method in case you want to do something different. Data Browser and Detail Window Flow of Control beginning on page 16-16 discusses this issue.

Meta Data Format

16-15

CHAPTER

16

Supporting Newton Connection

One method handles conversion from text frames to soup entry format:
n

The EditImport method converts a text frame into a frame in the format you use in your soup

Connection uses the Import method if the EditImport method does not exist and the Export method if the BrowserExport or EditExport methods do not exist. In general, though, Import and Export are provided for backward compatibility with version 1.0 of Connection. The next section describes how data gets from a soup into the Data Browser and Detail Window and back again. The meta data items are described following that.

Data Browser and Detail Window Flow of Control


This section provides an overview of what happens when the user displays soup data and then edits the data in a Detail Window. Opening a Data Browser When the user opens a Data Browser showing a particular applications data, Connection does the following for each entry: 1. Calls the BrowserExport item, which is a method, to convert the soup entry into a text frame. If a BrowserExport item does not exist, then the Export item is called. Figure 16-4 illustrates how BrowserExport or Export makes a text frame from a frame in the format you use in your soup. Notice two points about this example: n Information that you want displayed in the Data Browser must be converted to text strings, but the text frame can contain slots that have data other than text. In this case, the Code slot contains an integer. Slots like this are not intended to be displayed. They hold information that is internal to your program. n The contents of the slots can be different. In this case, BrowserExport took the information contained in the Units slot, the symbol 'inches, and used that to add text to the Height slot. Your BrowserExport item can do anything you want to the data.

16-16

Meta Data Format

CHAPTER

16

Supporting Newton Connection

Figure 16-4

BrowserExport Makes a Text Frame

Slot Name

Contents

Name Age Height Units Code

"Asher" 6 6.5 'inches 11123


Entry Frame BrowserExport

Slot Name

Contents

Name Age Height Code

"Asher" "6 years" "6 and a half inches" 11123


T ext Frame

2. Uses the displayInfo item to determine how the text frame should be displayed. Each text frame becomes a row in the Data Browser, with the data in the slots occupying elds in the rows. The displayInfo item is an array, where each element denes the appearance of one eld of each Data Browser row and, thus, one column of the Data Browser. Figure 16-5 illustrates this.
Figure 16-5 Connection Uses DisplayInfo to Display a Field

Slot Name

Contents

Slot Name

Contents

Name Age Height Code


T ext Frame

"Asher" "6 years" "6 and a half inches" 11123

Slot Label
One element from the displayInfo array

"Name" "Pets Name"

Pets Name Asher


In Data Browser

Meta Data Format

16-17

CHAPTER

16

Supporting Newton Connection

Notice that each column that you want to appear in the Data Browser must have an element in the displayInfo array. Each element in the displayInfo array has a Slot value that defines which slot from a text frame appears in that column. In this example, the Code slot would not have an element in the displayInfo array, because the contents of the Code slot is not meant to appear in the Data Browser. Opening a Detail Window When the user double clicks on a row in the Data Browser, or selects a row and issues the appropriate command, Connection opens a Detail Window. 1. Connection needs a text frame for the Detail Window: n If EditExport exists, Connection calls it to get a text frame for the Detail Window. EditExport acts in the same way as BrowserExport, as illustrated in Figure 16-4 on page 16-17. n If EditExport does not exist, Connection uses the text frame used for the Data Browser, unless that has become unavailable because memory has been ushed. If memory was ushed, Connection calls BrowserExport or, if that does not exist, Export, to get a new text frame. Regardless of how Connection got the text frame, it keeps it as long as the Detail Window shows this entry. 2. Connection uses the editInfo item to determine the appearance of the Detail Window. Each element in the editInfo array determines the appearance of the data from one slot in the text frame and, thus, one eld in the Detail Window. This is similar to the way Connection uses the displayInfo item, as illustrated in Figure 16-5 on page 16-17. Updating the Soup Connection updates the soup when, after editing the data, the user does one of the following:
n n n

Closes the Detail Window Clicks the Next, Previous, or New Entry buttons Selects the Data Browser window

16-18

Meta Data Format

CHAPTER

16

Supporting Newton Connection

1. Connection calls EditImport or, if EditImport doesnt exist, calls Import. EditImport is passed the same text frame that was created by EditExport, BrowserExport, or Export. Thus, you can safely store information in the text frame at export time for use at import time. 2. EditImport (or Import) either tells Connection to do nothing, tells Connection to display an error message, or gives Connection a frame to write to the soup. Creating a New Entry When the user clicks on the New Entry button, Connection: 1. Gets a frame from the NewEntry item. That item can be a frame or a method that returns a frame. 2. Calls DeepClone on the frame it got from NewEntry. 3. Writes the new frame to the soup in the synch le. 4. Opens a Detail Window showing the new frame, using an export method as described in Opening a Detail Window, above.

BrowserExport
BrowserExport(soupEntry, soupStore) Connection calls this method to convert a soup entry into a text frame that can be displayed in a row in a Data Browser window. It returns a text frame. soupEntry soupStore A soup entry to be converted to a text frame. The store of the soup from which the entry came. You can use NewtonScript store methods such as GetSoup on this reference.

Each slot in the returned text frame should:


n

Have a name that corresponds to an element in the displayInfo array. This name is generally the same as the name of a slot in soupEntry, but it doesnt have to be. However, if the slot names in the soup entry and the text frame are different, you need to specify the path attribute of the

Meta Data Format

16-19

CHAPTER

16

Supporting Newton Connection

displayInfo, editInfo, and exportInfo array elements so that Connection can nd the data for searching and sorting.
n

Contain a string that will be displayed in the Data Browser. This string is generally a string version of the data contained in a slot in soupEntry.

Opening a Data Browser beginning on page 16-16 illustrates the connection between the soup entry and the text frame. The frame can contain slots that do not have names referred to in displayInfo and, thus, are not displayed in the Data Browser. Those slots can contain anything. Connection calls this method with its context set to the (main) meta data entry. If this method is not present, the Export method, if there is one, is called instead.

EditExport
EditExport(soupEntry, soupStore) Connection calls this method to display a soup entry in a Detail Window. It returns a text frame. soupEntry soupStore A soup entry to be converted to a text frame. The store of the soup from which the entry came. You can use NewtonScript store methods such as GetSoup on this reference.

If you want to use the same text frame for the Data Browser and the Detail Window, you do not need to supply this method. Connection will use the same text frame or, if the text frame has been ushed from memory, call BrowserExport. (If BrowserExport does not exist, Connection calls Export.) Each slot in the returned text frame should:
n

Have a name that corresponds to an element in the displayInfo array. This name is generally the same as the name of a slot in soupEntry, but it doesnt have to be. However, if the slot names in the soup entry and the

16-20

Meta Data Format

CHAPTER

16

Supporting Newton Connection

text frame are different, you need to specify the path attribute of the displayInfo, editInfo, and exportInfo array elements so that Connection can nd the data for searching and sorting.
n

Contain a string that will be displayed in the Detail Window. This string is generally a string version of the data contained in a slot in soupEntry.

The frame can contain slots that do not have names referred to in editInfo and, thus, are not displayed in the Detail Window. Those slots can contain anything. Connection calls this method with its context set to the (main) meta data entry. Note that Connection will hold onto this text frame as long as the Detail Window is open. If the user performs any edits, Connection will modify this text frame, and pass this modied text frame to the EditImport method. Thus, you may wish to provide additional slots in the text frame for use by the EditImport method.

EditImport
EditImport(textFrame, soupStore) Connection calls this method before inserting an entry in a soup as a result of the user editing the entry in the Detail Window. When it is time for Connection to place the results of a user editing data in a Detail Window, Connection modies the text frame used to ll the Detail Window and passes that text frame to the EditImport method. EditImport converts the text frame into a soup entry. textFrame The text frame to be converted to a soup entry. Note that the text frame passed to this method is the text frame created by the export method, modied to reect the edits made by the user in the Detail Window. For example, you might nd it useful to place a reference to the original soup entry in the text frame at export time and to take advantage of this at import time. The store of the soup into which the entry will be placed

soupStore

Meta Data Format

16-21

CHAPTER

16

Supporting Newton Connection

This method is called with its context set to the (main) meta data entry. This method should perform whatever tests are necessary to test the validity of the frame that will be inserted in your soup. In particular, this method should make certain that:
n n n

The data exists The data is of the type expected by your program The data contains the correct information

It is important that this routine not allow a frame that would crash your Newton application. Since this routine is passed the store that contains the soup that will receive the entry, you can have this method perform verication that depends on other entries. When you import from native format les, Connection calls the EntryValidation meta data method after calling the NativeImport method, and EntryValidation validates the entry. EditImport needs to do validation because Connection does not call the EntryValidation method for you. You can call EntryValidation from your EditImport method, however. You do not have to do that, but it is better to have your validation centralized. (See EntryValidation beginning on page 16-46.) This method must return one of the following four results (these are the same four results as returned by the EntryValidation method):
n

nil. This indicates there was no error, but the frame should not be added to the soup. A string indicating an error condition that will be presented to the user. The returned string is appended to this message: Could not update " AppName" entry because The word AppName is replaced by the appropriate application name and the result is presented to the user in an alert.

16-22

Meta Data Format

CHAPTER

16

Supporting Newton Connection

A frame to be added to a soup. This should be in the format you use in your soup. An array of frames, each of which is to be added to soups. If the rst element of the array is nil, the frame that was being edited is deleted.

The frame, or frames, returned by this method can contain a slot with the name MetaDataSoupRef. If such a slot is present, it contains a reference to the soup into which to insert the frame. Connection removes this slot from the frames before inserting them in the soups. If this slot is not present, Connection inserts the frame into the soup that contained the entry in the corresponding line of the Data Browser, which is normally the soup that the edited entry came from. If this method is not present, the Import method, if present, is used instead.

Export
Export(soupEntry, soupStore) This method exists primarily for backward compatibility with version 1. If the TabExport, EditExport, or BrowserExport methods are missing, this method is called instead. soupEntry soupStore A soup entry to be converted to a text frame. The store of the soup from which the entry came. You can use NewtonScript store methods such as GetSoup on this reference.

Connection calls this method with its context set to the (main) meta data entry. This method should return one of the following:
n n

nil. If this method returns nil, the soup entry is not exported. A text frame.

If you are using Export in place of BrowserExport or EditExport, it must return a text frame.

Meta Data Format

16-23

CHAPTER

16

Supporting Newton Connection

Import
Import(textFrame, soupStore) This method exist primarily for backward compatibility with version 1. If either the TabImport or EditImport methods are missing, this method is called instead. If this method is also missing, Connection returns nil. textFrame soupStore The text frame to be converted to a frame in the format you use in your soup The store of the soup into which the entry will be placed

This method is called with its context set to the (main) meta data entry. This method should do whatever tests are necessary to test the validity of the frame that will be inserted in your soup. In particular, this method should make certain that:
n n n

The data exists The data is of the type expected by your program The data contains the correct information

It is important that this routine not allow a frame that would crash your Newton application. Since this routine is passed the store that contains the soup that will receive the entry, you can have this method perform verication that depends on other entries. When you import from native format les, Connection calls the EntryValidation meta data method after calling the NativeImport method, and EntryValidation validates the entry. Import needs to do validation because Connection does not call the EntryValidation method for you. You can call EntryValidation from your Import method, however. You do not have to do that, but it is better to have your validation centralized in your EntryValidation method. (See EntryValidation beginning on page 16-46.)

16-24

Meta Data Format

CHAPTER

16

Supporting Newton Connection

This method must return one of the following four results (these are the same four results as the EntryValidation method):
n

nil. This indicates there was no error, but the frame should not be added to the soup. A string indicating an error condition that will be presented to the user. The returned string is appended to one of these messages: Could not Import from "AppName" because Could not update "AppName" because The word AppName is replaced by the appropriate application name and the result is presented to the user in an alert. A frame to be added to a soup. Note that in this case, the returned frame should be the same frame that was passed in as an parameter, although you can modify it. An array of frames, each of which is to be added to soups. The rst frame of this array should either be nil, or the frame that was passed in as an parameter. Again, the frame can be modied.

The frame, or frames, returned by this method can contain a slot with the name MetaDataSoupRef. If such a slot is present, it contains a reference to the soup into which to insert the frame. If this slot is not present, Connection inserts the frame into the main soup for the application. Connection removes this slot from the frames before inserting them in the soups.

Controlling the Connection Windows


Four of these ve meta data items control the appearance of data in the Data Browser, the Detail Window, and the tab template.
n n

DisplayInfo determines the appearance of data within the Data Browser. EditInfo and Column0Width determine the appearance of data within the Detail Window on the Macintosh. This is not used in Windows Connection. ExportInfo determines the appearance of the template creation dialog.

The fth meta data item in this section, CompareScripts, contains scripts used for searching in the Data Browser.

Meta Data Format

16-25

CHAPTER

16

Supporting Newton Connection

DisplayInfo
This array item denes how a text frame appears in the Data Browser. Each element of the array determines the appearance of data from one slot from a text frame. Each element has a slot named Slot that names a slot from the text frame. The string contained in that text frame slot is displayed in the eld dened by that element. Figure 16-5 on page 16-17 illustrates this relationship. This item is required. You also need to have a BrowserExport (page 16-19) or Export (page 16-23) item to convert an entry frame into a text frame. When the user opens an application in Connection, Connection presents the Data Browser window. (The Calendar and Notepad are special cases, where the Data Browser may not be displayed.) The Data Browser has a Header area, and a spreadsheet-like area below the Header. The spreadsheet-like area is called the Results Grid, because it displays the results of the search specied in the Header area. On the Macintosh, you can scroll the Data Browser horizontally to see columns that are not visible. In the Windows version of Connection, the Data Browser does not scroll horizontally. The displayInfo item can contain up to 31 elements, each element specifying the appearance of one column of the Results Grid. Using the displayInfo array, you can specify:
n n

The initial order of the columns. The user can change this order. The initial width of the columns. In Macintosh Connection, the user can change the column width. In Windows Connection, the user cannot change the width. Which of the columns are initially hidden. What type of data Connection should consider that each slot contains. Connection uses this information for searching and sorting.

n n

16-26

Meta Data Format

CHAPTER

16

Supporting Newton Connection

Here is an example: displayInfo: [ 'honorific, 'firstname, 'lastname, {slot:'email, size:20}, {slot:'listby, hidden:TRUE}, ], The order of the elements in this array species the order the entry slots are initially shown in the Results Grid. Each element in the array gives information about one slot, and therefore describes one column in the Data Browser. Each element in the array can be a frame or can be the name of a slot in the defaultDefinitions item (see DefaultDenitions beginning on page 16-55). In this example, the last two elements are frames, while the rst three elements are names of slots in the defaultDefinitions frame. You might want to store denitions in defaultDefinitions because the displayInfo, editInfo, exportInfo, and nativeExportExceptions arrays use similar formats, so that you can often use the same slot information for more than one. You can also use defaultDefinitions to provide default values. Each element in the displayInfo array can have the slots, or attributes, shown in Table 16-2. You must give the slot attribute when you give a frame specication. Note that case is not signicant. Each of these attributes can be given as:
n n n

A value A function that returns a value A symbol that is the name of a slot in the attributeFunctions item frame that is a function that returns the value

Meta Data Format

16-27

CHAPTER

16

Supporting Newton Connection

Table 16-2 Slot Name

DisplayInfo slots Meaning

Default

Slot

A symbol that is the name of a slot in the text frame and possibly also the name of a slot in the defaultDefinitions frame. If the default denition exists, other slots in this displayInfo element override values given in the defaultDefinitions frame. Value of the slot attribute 15 A string that you want used as the column heading.

Label

Size

An integer that gives the initial width of the column, expressed as the number of times the character 0 (zero) will t in the column. A symbol that is the name of a type that species how Connection performs searches and sorts. If you do not give this slot, or Connection does not recognize the type, Connection uses 'string. Possible values are shown in Table 16-11 on page 16-57. The symbol can also be the name of a slot in the editTypes frame. A Boolean that species whether or not this column should be initially invisible. If you do not give this slot, Connection shows the column. A Boolean that species whether or not a column should be searchable. If you do not give this slot, the column is searchable. The column is sortable whether or not this slot is true. A path specication (see The NewtonScript Programming Language) that tells Connection where to obtain soup data. This is useful if soup data consists of a frame of frames and access is needed to data in one of the sub-frames. In addition, if the slot name in the soup entry and the text frame is different, you need to specify the path attribute so that Connection can nd the data. Connection uses this for searching and sorting.
continued

Type

'string

Hidden

nil

Unsearchable

nil

Path

Value of the slot attribute

16-28

Meta Data Format

CHAPTER

16

Supporting Newton Connection

Table 16-2 Slot Name

DisplayInfo slots (continued) Meaning

Default

CompareScript

none

A symbol giving the name of a slot in the CompareScripts frame. (See CompareScripts on page 16-32.) The function in that slot is invoked when the user searches this column.

EditInfo
This array denes how a text frame appears in a Detail Window. Each array element describes how one slot from the text entry will appear in the Detail Window. Thus, each array element describes one field in the Detail Window. Each array element can be:
n n n

A frame The name of a slot in the defaultDefinitions frame The symbol 'e_line which indicates a dividing line

Thus, each array element is either a symbol or a frame:


n

If the element is a symbol, then the symbol must be the name of a slot in the defaultDefinitions frame or 'e_line. If the element is a frame, then the frame has slots that describe the data. The slot slot may be a reference to the slot in the defaultDefinitions item frame. The values in that defaultDefinitions slot are default values for the slots in the editInfo element. Any attributes contained in the editInfo element override the slot denitions in the defaultDefinitions item frame.

Meta Data Format

16-29

CHAPTER

16

Supporting Newton Connection

For example: editInfo: [ {slot:'firstname, size:30, sameline:TRUE}, {slot:'lastname, size:30, sameline:TRUE}, 'honorific, 'e_line, // draws a dividing line 'email, {slot:'listBy}, ], In this example, 'honorific and 'email are names of slots in the defaultDefinitions frame. The first two elements are frames. It is possible that 'firstname and 'lastname are slots in defaultDefinitions. In that case, the size and sameline values given here override any size and sameline values that are given in defaultDefinitions. Connection displays elds in the order specied in this array, laying them out left to right and top to bottom, so the rst array element specied here appears at the top left of the Detail Window. Each element in the editInfo array can have the slots shown in Table 16-3.

Table 16-3 Slot Name Default

EditInfo slots Meaning

Slot

A symbol that is the name of a slot in the text frame and possibly also the name of a slot in the defaultDefinitions frame. If the default definition exists, other slots in this editInfo element override values given in the defaultDefinitions frame. Value of the slot attribute A string that you want used as the eld label.

Label

continued

16-30

Meta Data Format

CHAPTER

16

Supporting Newton Connection

Table 16-3 Slot Name Default

EditInfo slots (continued) Meaning

Size

15

An integer that gives the initial width of the column, expressed as the number of 0 characters that will t in the column. A symbol that is the name of a type that species how Connection should convert data from the soup to strings for display and, for some types, how Connection performs searches. If you do not give this slot, or Connection does not recognize the type, Connection uses 'string. Possible values are shown in Table 16-11 on page 16-57. The symbol can also be the name of a slot in the editTypes frame. A Boolean that indicates whether or not the eld should be on the same line as the previous eld. If this is not given or is nil, the eld appears on a new line. This is ignored if this eld follows an 'e_line. An array of strings. If you supply this, the type should be 'picklist. A Boolean saying whether or not this eld is editable. If you do not supply this, the eld is editable. An integer that gives the number of lines in the eld when the type attribute is 'text.

Type

'string

Sameline

nil

Choices Uneditable NumLines

none nil 4

Column0Width
This item species the default width of the leftmost column in the Detail Window for each line. This can be:
n n n

An integer A function that returns an integer A symbol that is the name for a slot in the attributeFunctions item that is a function that returns an integer

Meta Data Format

16-31

CHAPTER

16

Supporting Newton Connection

The leftmost column will hold the labels for each of the elds. A label that is longer than the specied width will be allowed to display in its natural size. Shorter labels are padded to occupy the amount of space indicated by this item, thus enabling the second column to be left justied. The integer species the number of 0 (zero) characters that would t. If unspecied, it defaults to 15.

CompareScripts
This is a frame where each slot is a function that does a comparison. Slots from this frame are referred to by the compareScript slots of the elements in displayInfo. If a user wishes to lter the data displayed in a Data Browser by using the search function, Connection compares each soup entry with the userspecied search criteria to determine whether or not to display the entry. If you wish to provide your own way for performing these comparisons, then you set the compareScript slot of one of the displayInfo items to the name of a frame in this compareScripts item. You must have a compare function for constructed elds, which are elds for which the text representation in a Data Browser is not a straight-forward mapping of a Newton type in an entrys slot to a Connection type. If you do not have this, the results are unpredictable. The order in which Connection passes entries to your compare function is undened. Each slot in this frame contains a function that takes two parameters.
n n

The rst parameter is the current entry in the current soup. The second parameter is a frame with the slots shown in Table 16-4. true. This indicates that this item satisfies the search criterion. nil. This indicates that this item does not satisfy the search criterion. A piece of data, which can be a character, string, integer, or real number. Connection uses this data in place of the data from the soup entry and then does its default comparison.

The function must return one of the following values:


n n n

16-32

Meta Data Format

CHAPTER

16

Supporting Newton Connection

Table 16-4 Slot

Second parameter of compare function Meaning

SlotName DataType SearchType SearchText SearchValue

The path to the data within the current frame, as specied by either the path or slot meta data item The value of the meta data type item. An integer representing the type of search requested by the user (see Table 16-5) A string corresponding to what the user entered into the search eld. An optional slot that you can use to store a converted version of searchText so that you do not have to convert it for each comparison. Connection uses this slot that way when you do not have your own compare function, and you are encouraged to follow this practice.

When doing an advanced search, the user can request one of the search types shown inTable 16-5. Connection uses the values shown in that table for the searchType slot of the second compare function parameter, so you can get that information in your compare function.
Table 16-5 Value Search Types Type of Search

0 or 1 2 3 4 5 6 7 8 9

Begins with (a simple search is equivalent to this) Contains Ends with Equals Not equals Greater than or equal Greater than Less than Less than or equal

Meta Data Format

16-33

CHAPTER

16

Supporting Newton Connection

All searches should be of the following form: <soup data > <operator > <user search data >

ExportInfo
This is an array that controls what can be imported or exported using text templates. The elements in this array dene elds that appear in Connections template creation dialog. Note that this array simply determines the appearance of the dialog box; the importing is done by the TabImport method (see TabImport beginning on page 16-37), while exporting is done by the TabExport method (see TabExport on page 16-36). Here is an example: exportInfo: [ 'honorific, {slot: 'firstname, label: "First Name"}, {slot: 'lastname, label: "Last Name"}, 'email, 'listby, ], When the user chooses the Create Template or the Edit Template command, Connection displays a dialog box in which the user can choose which elds to import or export. The order the elements appear in the exportInfo array determines the order of the elds in the dialog. Each element in the array can be a frame or can be the name of a slot in the defaultDefinitions item (see DefaultDenitions beginning on page 16-55). In this example, the rst element and the last two are names of slots in the defaultDefinitions frame, while the second and third are frames. You might want to store denitions in defaultDefinitions because the displayInfo, editInfo, exportInfo, and nativeExportExceptions arrays use similar formats, so that you can often use the same slot information for more than one.

16-34

Meta Data Format

CHAPTER

16

Supporting Newton Connection

You can also give the slots shown in Table 16-7.

Table 16-6 Slot name Default

ExportInfo Slots Meaning

Slot

A symbol that is the name of a slot in the text frame and possibly also the name of a slot in the defaultDefinitions frame. If the default denition exists, other slots in this displayInfo element override values given in the defaultDefinitions frame. Value of the slot attribute Value of the slot attribute A string that you want used as the descriptive label.

Label

Path

A path specication (see The NewtonScript Programming Language) that tells Connection where to obtain soup data. This is useful if soup data consists of a frame of frames and access is needed to data in one of the sub frames.

Moving Data to and From External Files


Users can import data from and export data to two formats:
n

Native format, sometimes called Newton Text Format. Connections native format is a text format that corresponds to a attening of soup entries. See Native Format beginning on page 16-81 for details of the format. A native format le may be a temporary le that is for or from translation to or from a third-party personal computer application le, such as a spreadsheet le, data-base le, or PIM le. Text format. Text format is a text le in which data from individual entry slots are separated by a user-specied character, usually a tab, and entries are separated by another user-specied character, usually a carriage return. This kind of le is often suitable for communicating with spreadsheet or database applications. TabExport converts data from soup entries into text format, while tabImport converts data from text format into soup entries.

Meta Data Format

16-35

CHAPTER

16

Supporting Newton Connection

Entries should be validated before being written into a synch le. You can do that by writing an EntryValidation method; see EntryValidation beginning on page 16-46. When importing in native format, Connection calls EntryValidation and ApplyCommands before writing the new entry into the synch le. With text format importing, by contrast, EntryValidation is not called for you. You should call it yourself from TabImport or otherwise validate the data in your TabImport method. ( ApplyCommands is called for you with both text format and native format importing.)

TabExport
TabExport(entry , soupStore) When the user starts a text format export operation, for each entry, Connection calls ExportFilter and then calls this method to export the entry as modied by ExportFilter. If you want to modify the entry before exporting it, you should do that in ExportFilter. (See ExportFilter beginning on page 16-43.) entry soupStore A soup entry to be converted to a text frame that will form one row of the text format le The store of the soup from which the entry came

Connection calls this method with its context set to the (main) meta data entry. This method should return one of the following:
n n

nil. If this method returns nil, the soup entry is not exported. A text frame. Each slot in the text frame that you want to be a field in a text format export le should have a name that corresponds to a name in the slot attribute in an element of the exportInfo array . As with other text frames, you can have additional slots, but they will not be written to the text le.

If this method is not present, Connection uses the BrowserExport method, if there is one, instead. See BrowserExport beginning on page 16-19. If BrowserExport also does not exist, Connection uses the Export method, instead. See Export beginning on page 16-23.

16-36

Meta Data Format

CHAPTER

16

Supporting Newton Connection

TabImport
TabImport(textFrame, soupStore) Connection calls this method before entering an entry in a soup as a result of a text format import operation. textFrame The text frame to be converted to a valid frame in the format you use in your soup. The names of each of the text frames slots are the slot names specied in the exportInfo array. Note, though, that this text frame may not contain all of the slots specied in exportInfo, because the text le may not have had all of those elds. The store of the soup into which the entry will be placed

soupStore

When Connection reads a record from a text le for a tab import operation, it creates a text frame that corresponds to the information in the record. Next it calls this method to convert the text frame to a frame in the format you use in your soup. This method should perform whatever tests are necessary to test the validity of the frame that will be inserted into your soup. In particular, this method should make certain that:
n n n

The data exists The data is of the type expected by your program The data contains the correct information

It is important that this routine not allow a frame that would crash your Newton application. Since this routine is passed the store that contains the soup that will receive the entry, you can have this method perform verication that depends on other entries. When you import from native format les, Connection calls the EntryValidation meta data method after calling the NativeImport method, and EntryValidation validates the entry. TabImport needs to do validation because Connection does not call the EntryValidation method for you. You can call EntryValidation from your TabImport

Meta Data Format

16-37

CHAPTER

16

Supporting Newton Connection

method, however. You do not have to do that, but it is better to have your validation centralized. (See EntryValidation beginning on page 16-46.) This method is called with its context set to the (main) meta data entry. This method must return one of the following four results (these are the same four results as the EntryValidation method):
n

nil. This indicates there was no error, but the frame should not be added to the soup. A string indicating an error condition that will be presented to the user. The returned string is appended to this message: Could not Import from "AppName" because The word AppName is replaced by the appropriate application name and the result is presented to the user in an alert. A frame to be added to a soup. An array of frames, each of which is to be added to soups.

n n

The frame, or frames, returned by this method can contain a slot with the name MetaDataSoupRef. If such a slot is present, it contains a reference to the soup into which to insert the frame. If this slot is not present, Connection inserts the frame into the main soup for the application. Connection removes this slot from the frames before inserting them in the soups. Connection uses the results of tabImport to create addEntry commands, as described in Command Frames beginning on page 16-48. It then passes those commands, one at a time, to your ApplyCommands item, if there is one, to give it a chance to do or modify the command. If you want to do something sophisticated such as checking for duplicate entries, you should do that in ApplyCommands rather than TabImport. If this method is not present, the Import method (if present) is used instead. See Import beginning on page 16-24.

16-38

Meta Data Format

CHAPTER

16

Supporting Newton Connection

NativeExport
NativeExport(entry , state, soupStore) When the user starts a native format export operation Connection calls this method once for each entry to export the entry. entry state A soup entry to be converted to a native format frame. A state parameter that is a frame that can hold information between calls. This is empty when Connection calls NativeExport for the rst entry in a soup. Your NativeExport method can place information in this frame and the information is passed back to it the next time Connection calls it. The frame is cleared when Connection exports the rst entry in a different soup. The store of the soup from which the entry came.

soupStore

Connection calls this method with its context set to the (main) meta data entry. This method should return one of the following:
n n

nil. If this method returns nil, the soup entry is not exported. A frame. Each slot in the frame should be one eld in a native format export le. The name of each slot in the text frame should correspond to the eld name.

If this method does not exist, Connection exports the entry frame as-is. Connection calls ExportFilter before calling NativeExport. If you want to export a different entry, export additional entries for each entry, split an entry into several entries, or export an additional soup for each entry, you should do that in ExportFilter. (See ExportFilter beginning on page 16-43.)

Meta Data Format

16-39

CHAPTER

16

Supporting Newton Connection

NativeImport
NativeImport(nativeFrame , soupStore) Connection calls this method before entering an entry in a soup as a result of a native format import operation. nativeFrame soupStore A frame created from the native format description. The store of the soup into which the entry will be placed.

A native format le consists of command descriptions. Each command description describes one or more objects, such as soups or soup entries, or gives instructions for something to do to a soup, such as deleting entries. Native format syntax is described in Native Format beginning on page 16-81. Connection opens and reads the le to be imported, one command description at a time. If syntax errors are noted, processing continues at the next syntactically valid command description. Command descriptions can:
n n n n

Add entries Replace entries Delete entries Modify entries

If the command description adds or replaces entries, Connection builds all the objects comprised by that description. When a single description is completely parsed, if it contains an entry to be added or that will replace another entry, Connection calls NativeImport, passing it the frame specied by the native format command description. NativeImport makes any changes that you want made before the frame is added to the soup. Connection then passes the entry to the meta data EntryValidation method (described in EntryValidation beginning on page 16-46). If EntryValidation returns an error, then import is aborted. If EntryValidation returns a frame, or an array of frames, then Connection continues processing.

16-40

Meta Data Format

CHAPTER

16

Supporting Newton Connection

Connection takes all the frames that need to be put in the soup and makes command frames for them, with one command frame for each entry. Command frames are discussed in Command Frames beginning on page 16-48; for now, it is enough to know that a command frame species an entry and an action, such as adding the entry, deleting the entry, or changing the entry. If the command description in the native format file specified deleting or modifying an entry, Connection builds the command frame without first calling NativeImport or EntryValidation. After all the descriptions in the native le have been successfully parsed into actual command objects, Connection applies each command, in creation order. For each command, Connection first passes it to the meta data ApplyCommands method (described in ApplyCommands beginning on page 16-47), if that exists. If ApplyCommands returns an error, import is aborted, even though some commands may already have been applied. If ApplyCommands returns a command frame, then Connection applies that command. If ApplyCommands returns any other frame, Connection assumes that this is a new entry that has been added to the soup. Otherwise (that is, on nil), Connection advances to the next command without further ado. NativeImport is called with its context set to the (main) meta data entry. It can return the following:
n

nil. This indicates there was no error, but the frame should not be added to the soup. A string indicating an error condition that will be presented to the user. The returned string is appended to this message: Could not Import into "AppName" because The word AppName is replaced by the appropriate application name and the result is presented to the user in an alert. An integer error code. A frame to be added to a soup. An array of frames, each of which is to be added to soups.

n n n

Meta Data Format

16-41

CHAPTER

16

Supporting Newton Connection

The frame, or frames, returned by this method can contain a slot with the name MetaDataSoupRef. If such a slot is present, it contains a reference to the soup into which to insert the frame. If this slot is not present, Connection inserts the frame into the soup indicated in the native format le. Connection removes this slot from the frames before inserting them in the soups.

NativeExportExceptions
This array is used to control native format export operations. Each array element describes one piece of data that will NOT be exported. Each array element is either:
n

A symbol that is the name of a slot in the defaultDefinitions frame that describes the data. A frame that consists of one or two slots that describe the data. One of these slots (the slot attribute) may actually be a reference to the slot in the defaultDefinitions item frame. If you give the path slot here, it overrides the path denition in the defaultDefinitions item frame.

You can give the slots shown in Table 16-7.

Table 16-7 Slot Name Default

NativeExportExceptions slots Meaning

Slot

A symbol that is either the name of a slot in the entry or the name of a slot in the defaultDefinitions frame. In the second case, other slots override values given in the defaultDefinitions frame. Value of the slot attribute A path specication (see The NewtonScript Programming Language) that tells Connection where to obtain soup data. This is useful if soup data consists of a frame of frames and access is needed to data in one of the sub frames.

Path

16-42

Meta Data Format

CHAPTER

16

Supporting Newton Connection

ExportFilter
ExportFilter(exportFrame) Connection calls this method before calling NativeExport or TabExport. You can use this method to change an entry so that:
n n n n

A different entry is exported. A set of entries is exported for each entry the user selected. An entire soup is exported in place of a single entry. Any combination of the above. For example, you could export the entry passed in plus an entire soup.

Connection calls this method with its context set to the (main) meta data entry. You do not give a return value for this function. You modify the parameter instead. The parameter is a frame that can have four slots: exportFrame = {exportEntry: anEntry, exportState: anything , exportSoup: aSoup, exportAgain: anything } On the rst call to ExportFilter for a given entry, the parameter contains two slots: exportFrame = { exportEntry: theEntry, exportState: {}} The slot exportState is a state variable that persists for this entire soup. It is the same state variable that is passed to NativeExport. If you want to respond to this entry by exporting additional entries, because, for example, you want ExportFilter to break the original entry into several parts, then add the slot exportAgain. You can give exportAgain any value you wish, including nil. You may want to save information about

Meta Data Format

16-43

CHAPTER

16

Supporting Newton Connection

the state of the entry in exportAgain. Thus, you can use exportAgain as a state variable for this entry. Its value persists until ExportFilter is called again for another entry. For example: exportFrame = {exportEntry: createdEntry, exportState:{}, exportAgain: {original:theEntry, place: 1} } In this example, ExportFilter has set exportAgain so that it contains the original entry and an indicator of where you are in processing the entry. Connection:
n n

Exports the entry given in exportEntry. Calls ExportFilter again, passing in the same exportFrame. Thus, you can store state information in exportAgain. While exportAgain exists, each repeated call will leave exportEntry as you last set it, thus, if you want to remember the initial entry, but export several different frames, you need to clone and save it either in exportAgain or inside the state object you put in exportAgain and keep putting the next different frame to export in exportEntry.

When you do not want ExportFilter to be called again for this entry either:
n n

Remove exportAgain. Set exportEntry to nil. (You should never remove exportEntry. Set it to nil when you do not want an entry to be written.)

As soon as exportEntry is nil or the slot exportAgain does not exist, Connection moves on to the next real entry from the current soup. You might want to respond to an entry by exporting an additional soup. This is fairly rare, but occurs when you treat soups as documents are treated on the Macintosh, so that there is one soup per document. In that case, you keep

16-44

Meta Data Format

CHAPTER

16

Supporting Newton Connection

track of all these soups using your own reference soup. This reference soup has a single entry for each document soup. The meta data for the application only references the reference soup. When a user opens this application in Connection they see a list of all of the documents that the application has (that is, a list of all the other soups). When the user does an export the user really wants to export the contents of the document soup referred to by the reference entry they have selected. You implement this by providing an ExportFilter method. To do this, ExportFilter should add a slot to the exportFrame giving a reference to the soup that should be exported. For example: exportFrame = {exportEntry: theEntry, exportState:{}, exportSoup: anAdditionalSoup } Connection:
n

Schedules the soup given in exportSoup to be exported after all the soups currently scheduled to be written. (ExportSoup will be written once for each time that you set the slot, so only set it once for a given soup.) If the newly scheduled soup has a meta data entry, Connection uses that information for exporting the soup. If newly scheduled soup does not have a meta data entry, Connection uses the meta data that was in effect when that soup was scheduled for exporting. When Connection calls that soup, it passes ExportFilter and NativeExport the same exportState variable that was used the soup was scheduled. Removes this slot before the next call to ExportFilter. (This is true even if exportAgain is present.) Exports the entry given in exportEntry. (If you do not want it to be exported, set exportEntry to nil.) Moves on to the next entry, because exportAgain does not exist in this example.

Meta Data Format

16-45

CHAPTER

16

Supporting Newton Connection

EntryValidation
EntryValidation(entryFrame, soupStore) Connection calls this method prior to putting an entry in a synch le as a result of native and translator import operations. You may wish to call this method from within your EditImport and TabImport methods in order to centralize entry validation code. entryFrame soupStore A frame to be validated The store of the soup into which the entry will be placed

This method should do whatever is necessary to test the validity of the frame that is passed in as the rst parameter. In particular, this method should make certain that:
n n n

The data exists The data is of the type expected by your program The data contains the correct information

It is important that this routine not allow a frame that would crash your Newton application. Since this routine is passed the store that contains the soup that will receive the entry, you can have this method perform verication that depends on other entries. This method is called with its context set to the (main) meta data entry. This method must return one of four results:
n

nil. This indicates there was no error, but the frame should not be added to the soup. A string indicating an error condition. Connection appends the returned string to this message: Could not Import into "AppName" because The word AppName is replaced by the appropriate application name and the result is presented to the user in an alert. A frame to be added to a soup. Note that in this case, the returned frame must be the same frame that was passed in as a parameter, although you can modify it.

16-46

Meta Data Format

CHAPTER

16

Supporting Newton Connection

An array of frames, each of which is to be added to soups. The rst frame of this array must either be nil, or the frame that was passed in as a parameter. Again, you can modify the frame.

The frame or frames returned by this method can contain a slot with the name MetaDataSoupRef. If such a slot is present, it contains a reference to the soup into which to insert the frame. If this slot is not present, Connection inserts the frame into the main soup for the application. Connection removes this slot from the frames before inserting them in the soups. Connection provides some methods to help in validation. See Data Validation Functions beginning on page 16-69.

ApplyCommands
ApplyCommands (soup, commandFrame ) If this item exists, Connection calls the method it contains after all command frames have been built for importing from native format and text format. soup commandFrame A reference to a soup. A command frame. A command frame is documented in Command Frames beginning on page 16-48. In general, a command frame indicates whether to add, replace, modify, or delete one or more entries in the soup indicated by the rst parameter.

This method should return one of the following four types of results:
n

nil. This indicates that for modify and delete commands, the method handled the command. A string indicating an error condition that will be presented to the user. The returned string is appended to this message: Could not Import into "AppName" because The word AppName is replaced by the appropriate application name and the result is presented to the user in an alert. A frame that you have added. In this case, Connection assumes that you have already taken care of the command. However, you must return the frame you added, so that Connection can use it for internal bookkeeping.

Meta Data Format

16-47

CHAPTER

16

Supporting Newton Connection

A command frame. This tells Connection to perform the operation contained in the command frame. This must be the command frame that was passed in, though you can modify it.

IMPORTANT

If you add data and return the command frame passed to the ApplyCommands method, you should take care to insure that complete copies are added, rather than references to shared data. This applies specically to the addEntry or addSlots slots in the command frame. For example, code such as: commandFrame.addSlots.newSlot := "String"; will cause problems for Connection, and may cause it to terminate. Instead, return new copies of the data. You can do that with code like this: commandFrame.addSlots.newSlot := DeepClone("String"); Note that memory is not much of a consideration in this case, because there is plenty of it available inside Connection, and the newly cloned data will become unreferenced after it is added to the appropriate soup. s Command Frames This is the format for a command frame, as passed into and sometimes returned by the ApplyCommands method. Criteria is a list of name/object pairs that must match slots in the target frame. The best way to store this list is as a frame. However, criteria must be a at frame, which is a frame that does not contain frames or arrays. For example: criteria := { name: "Bob" }

16-48

Meta Data Format

CHAPTER

16

Supporting Newton Connection

Table 16-8 Slot

Command frame format Type Meaning

sequence

integer

Species the order in which commands are applied to the store. The rst command in the native format le gets the sequence number 1, which means it is done rst. If you break a command up into several commands, they all have the same sequence number. In that case, they are performed in the order in which they were returned by your function. If present, this slot selects entries (either by unique ID, or by equality of slots), to be modied according to the addSlots and removeSlots frames, or deleted if neither of those is present. This is explained following the table. If present, this is the frame to be added. If present, each slot of this frame is added to each entry specied by criteria. If present, each slot of this frame is removed from each entry specied by criteria. You should set each slot in this frame to nil.

criteria

either an integer or a at frame1

addEntry addSlots

frame frame

removeSlots

frame

1. A at frame is a frame that does not contain frames or arrays.

This frame is at and matches the following entry. Notice that the matched entry does not have to be at. { name: "Bob", age: 20, zone: { country: "USA", state: "OH" } },

Meta Data Format

16-49

CHAPTER

16

Supporting Newton Connection

The criteria does not match these entries: { names: "Bob"} {age: 20 } { name: "bob" } This criteria will not match the following entry, because the criteria is not at: criteria := { person: { firstName:"Bob" } } { person: { firstName:"Bob", lastName: (name:"Jones") } If a conversion method split an import entry into multiple chunks because, for example, it was too big to be a single Note, the add command for each chunk will have the same sequence number. The ApplyCommands method can determine what action to perform by examining which slots are present in the command:

Table 16-9 Slots Present

Meaning of having command slots present Meaning

addEntry addEntry, criteria

Add a new entry. Replace all entries matching the criteria with the single new entry in addEntry. If nothing matches the criteria, no changes are made. Delete all entries matching the criteria. Modies each of the entries matching the criteria, adding slots from addSlots, and removing slots from removeSlots. Error. addSlots and removeSlots are ignored. Error. addSlots and removeSlots are ignored.

criteria criteria, addSlots and/or removeSlots addSlots and/or removeSlots without criteria addEntry, criteria, addSlots and/or removeSlots

16-50

Meta Data Format

CHAPTER

16

Supporting Newton Connection

Soup-Related Items
These items will not be needed in most meta data entries. They control what happens when a soup does not exist.

DontCreateSoups
Under certain circumstances, Connection will create a soup if it does not yet exist, unless the value of this item is true. Those circumstances are:
n n

When opening a Data Browser When importing from a native format le that includes an entry for an application On the Macintosh when the user pastes while the Application Browser is frontmost

Note that if DontCreateSoups is true and the soups dont exist, Connection will not even show this application in the Application Browser in Macintosh Connection or in the menus in Windows Connection.

SoupIndicies
When Connection needs to create a soup, it uses this item and SoupInfo to create the soup. (See DontCreateSoups for a discussion of when Connection needs to create soups.) The indexes given here should be an array of soup index frames as described in the Data Storage and Retrieval chapter.

SoupInfo
When Connection needs to create a soup, it uses this item and SoupIndicies to create the soup. (See DontCreateSoups for a discussion of when Connection needs to create soups.) See the Data Storage and Retrieval chapter for information on the soup info frame.

Meta Data Format

16-51

CHAPTER

16

Supporting Newton Connection

Multi-Soup Applications
A multi-soup application is one that uses data from more than one data soup. A multi-soup application must have one meta data frame for each soup it uses. One of these meta data entries is referred to as the main meta data, and the others are referred to as dependent meta data entries. The main meta data entry lists its dependent soups in the Dependents item; the dependents point to the main soup in the EditWith item. Multi-soup applications present several unique, difcult, and even unsolvable problems for Connection. Connections response to this situation has been to give you as the multi-soup application developer the control necessary to do the right thing, since only you really know what that is. Connection accomplishes this by using and requiring some items to come from the dependent meta data entries and other items to be in the main meta data. These items are required in dependent meta data entries: Soup Name EditWith If these items are present in a dependent meta data, Connection uses them: Version NewEntry NativeExportExceptions SoupIndicies SoupInfo All other items for a dependent meta data are obtained from the main meta data. Note that this includes several methods. Thus, you need to do the right thing when one of these methods is called. This is the reason that the

16-52

Meta Data Format

CHAPTER

16

Supporting Newton Connection

MetaDataSoupRef slot exists in frames returned from EntryValidation and the import functions, so that you can specify a soup into which to insert a frame. (If MetaDataSoupRef is not specied and the frame being written was originally a soup entry, it is written back to the soup it came from.) Also note that when methods from the main meta data are called, their context will be set to the main meta data, not to a dependent meta data. (The only exception to this is if the NewEntry item is a method, rather than a frame, the NewEntry method from a dependent meta data will be called in the context of the same dependent meta data.) Other than writing methods that may have to deal with multiple soups, the only other special responsibility of a main meta data is to provide the Dependents item. When you export from a multi-soup application, the main soup is exported before any of the dependents; the dependents are exported in the same order as they appear in the Dependents item. The same exportState variable is used for the main and dependent soups. The rest of this section discusses the two meta data items needed for multisoup applications. If your application has a single soup, you do not need to have these items.

Dependents
The presence of this item identies this as a main meta data entry of a multi-soup application. This is an array of strings, each string being a soup name of a dependent meta data entry (that is, the name contained in the soup item of a dependent meta data). When searching soups for entries to be displayed in the Data Browser for an open application, Connection will search the soup specied by this meta data entry and the soups specied by the dependent meta data entries. Similarly, export operations will export entries from the all soups specied by the main and dependent meta data entries.

Meta Data Format

16-53

CHAPTER

16

Supporting Newton Connection

EditWith
If editWith is present and not nil, then this is a dependent meta data of a multi-soup application. The value of editWith is a symbol that is the soup name (that is, the value of the soup item) for the main meta data. For example, if the soup item has the value "mainSoupName": editWith: 'mainSoupName, If the soup item has the value "main_soup": editWith: '|main_soup|, Connection uses editWith to get the name of the main soup when an error occurs during synchronization. When such an error occurs, Connection reports conicts in terms of the application that contained the conict. Connection searches its available meta data entries to nd the referenced one, and if it contains an EditWith item, the conict is reported to the user using the name item of the meta data belonging to the soup specied by the EditWith slot.

Centralizing Denitions
The meta data includes three items that are for convenience or documentation purposes. You can centralize denitions in these frames, either because they will be used more than once or because you prefer to have the denitions centralized.

AttributeFunctions
Any place an attribute value can be specied, you can give a symbol which will be interpreted as the name of a slot in the AttributeFunction frame. The referenced slot is then a function that will return the actual attribute value. The referenced function is called in the context of the main meta data entry and is not passed any parameters. It is expected to return a value that would have been appropriate had the attribute been dened in place.

16-54

Meta Data Format

CHAPTER

16

Supporting Newton Connection

You should take care not to use the same slot names in the defaultDefinitions and attributeFunctions frames. Which frame has precedence is not dened.

DefaultDenitions
This is a frame of frames. Each slot within defaultDefinitions holds a frame that can be used to provide shorthand entries or defaults in the displayInfo, editInfo, exportInfo, and nativeExportExceptions arrays. You should take care not to use the same slot names in the defaultDefinitions and attributeFunctions frames. Which frame has precedence is not dened. There are two ways to use defaultDefinitions frames:
n

You can give the name of a defaultDefinitions frame as an element in a editInfo, displayInfo, exportInfo, or nativeExportExceptions array. You can give the name in the slot slot in a editInfo, displayInfo, exportInfo, or nativeExportExceptions element. When you do this, the values in the defaultDefinitions frame act as defaults, so that you can override them by specifying slots explicitly in the array element.

Each slot in defaultDefinitions should be a frame whose name is the same as a slot in the text frame. Each frame contains slots that are used for the displayInfo, editInfo, exportInfo, and nativeExportExceptions arrays. For example: DefaultDefinitions: { honorific:{label:"Ms./Mr.", size:5}, firstname:{label:"First Name"}, lastname:{label:"Last Name"}, title: {label:"Title:"}, email:{label:"E-Mail"},

Meta Data Format

16-55

CHAPTER

16

Supporting Newton Connection

listby:{type:'listByType}, cardType:{type:'cardType}, }, In this case, honorific, firstname, lastname, title, email, listby, and cardType are the names of slots in the text frame returned by BrowserExport. The frames in defaultDefinitions can contain any slots you can give in the displayInfo, editInfo, exportInfo, and nativeExportExceptions arrays. If the slot does not have meaning where you use the frame that contains it, it is ignored. Table 16-10 shows all the meaningful info array slots, their default values, and which info arrays they apply to.

Table 16-10

Info array slots ExportInfo NativeExportExceptions

Default

DisplayInfo

EditInfo

Slot Label Value of the slot attribute 15 'string nil nil none nil nil

X X

X X

X X

Size Type Hidden Sameline Choices Uneditable Unsearchable

X X X

X X

X X X X
continued

16-56

Meta Data Format

CHAPTER

16

Supporting Newton Connection

Table 16-10

Info array slots (continued) ExportInfo NativeExportExceptions

Default

DisplayInfo

EditInfo

Path

Value of the slot attribute none 4

CompareScript NumLines

X X

EditTypes
This is a frame that contains denitions for data types that are not built into Connection. The built-in types are shown in Table 16-11.

Table 16-11 Type Effect

Connection Built-In Types

'string

Creates a string eld. A string eld can contain up to 255 characters. Any character (alphabetic characters, numbers, and special characters) are allowed.The eld is a single line, with the initial width specied by the size slot. If there are more characters in the string than can be displayed in the set size, the eld can scroll horizontally. All searches and sorts are case and diacritical mark insensitive.

'char 'text

Creates a character eld. A character eld is like a string eld, but can hold no more than 1 character. Creates a text eld. Similar to 'string except allowed to be up to 32767 characters in Detail Windows. Also in Detail Windows, will display as numLines lines and will scroll vertically.
continued

Meta Data Format

16-57

CHAPTER

16

Supporting Newton Connection

Table 16-11 Type Effect

Connection Built-In Types (continued)

'integer

Creates an integer eld. Data of this type will display as a single line in Detail Windows, the width being specied by the size attribute. Only digits and a minus sign can be entered by the user in Detail Window editing. For searching and sorting, the value is treated as a signed 30 bit integer

'real

Creates a real number eld. Similar to 'integer except searches and sorts are performed on real numbers. Note that Connection does not restrict which characters the user may use when editing this eld in Detail Windows. As in NewtonScript, you can use decimal or exponential notation.

'picklist 'folder

Creates a popup eld. The width of the eld is specied by the size slot. The contents of the eld is specied by the choices slot. Creates a folder eld. In Detail Windows, elds with this type display as a pop-up whose items correspond to the currently dened set of Newton Folders. Searches and sorts are performed on the string that represents the current choice.

'dateNTime 'date 'time 'day

Creates a dateNTime (date and time) field. See note following table. Creates a date eld. See note following table. Creates a time eld. See note following table. Creates a day eld. See note following table. For purposes of searching and sorting, this is considered an integer from 0 to 6, with Sunday being 0. Creates a dateInMonth eld. See note following table. Creates a month eld. See note following table. For purposes of searching and sorting, this is considered an integer from 1 to 12. Creates a year eld. See note following table. Creates an integer eld. See note following table.

'dateInMonth 'month 'year 'duration

16-58

Meta Data Format

CHAPTER

16

Supporting Newton Connection

Note:

In the soup entry, the underlying value for 'dateNTime, 'date, 'time, 'day, 'dateInMonth, 'month, and 'year is a number of minutes since midnight (that is, the beginning) of January 1, 1904. In addition, the underlying value of 'duration is a number of minutes. A value of 30, for example might indicate 12:30 am on Friday, January 1, 1904 or might indicate a duration of 30 minutes. Connection interprets the value differently depending on what you dene as the eld type. Consider, for example, a value of 1470. Table 16-12 shows how the eld type determines what is shown in the Data Browser or Detail Window. In searching and sorting, Connection searches and sorts according to the interpreted value, rather than the underlying value. That means, for example, 30 and 1470 displayed in a 'time eld would both equally satisfy a search for 12:30 am. u

Table 16-12 Field Type

Interpretation of date and time value of 1470 Interpretation

'dateNTime 'date 'time 'day 'dateInMonth 'month 'year 'duration

12:30 am January 2, 1904 January 2, 1904 12:30 am Saturday 2 January 1904 1470 minutes

Meta Data Format

16-59

CHAPTER

16

Supporting Newton Connection

The types you create in the editTypes frame are not really new types. Each slot in editTypes must have a type slot, and that slot must specify one of the built-in types. Each slot in a frame in editTypes can actually be:
n n n

A value A function that returns a value A symbol that is the name of a slot in the attributeFunctions item frame that is a function that returns the value

Using an editTypes makes most sense for a type 'picklist, in that you can give the list a label and a list of choices. For example: editTypes: { phoneType: { type:'PICKLIST, label:"Type", choices:[ "Phone", "Home", "Work", "Fax", "Car", "Beeper", "Mobile", "Other" ] } } You also may nd editTypes useful for documentation purposes, in that you can give a special name to a built-in type.

16-60

Meta Data Format

CHAPTER

16

Supporting Newton Connection

Writing Meta Data Frames


Many, but not all, of the functions available on the Newton for applications are available for use in methods that are part of the meta data. Table 16-13 and Table 16-14 show the operators and functions that can be used in meta data functions. Additionally, Connection provides some functions which are only available for the meta data (see Newton Connection-Only Functions beginning on page 16-65). Those additional functions do not exist on the Newton, and thus cannot be debugged with NTK. Debugging is discussed in Debugging Meta Data beginning on page 16-77.

NewtonScript Functions Available for Use in Meta Data


The following Newton operators and global functions may be used by meta data functions. In addition to these functions, meta data functions may also use any of the methods of soup and store objects.

Table 16-13

Newto n numeric operators for meta data functions

* + / < << <= <>

= > >= >> abs acos and asin

atan atan2 band bnot bor bxor ceiling cos

cosh div exp fabs floor fmod log log10


continued

Writing Meta Data Frames

16-61

CHAPTER

16

Supporting Newton Connection

Table 16-13

Newto n numeric operators for meta data functions

max min mod negate

not or pow real

sin sinh sqrt tan

tanh

Table 16-14

Newton global functions for meta data functions

AddArraySlot Apply ArrayMunger ArrayPos ArrayRemoveCount BeginsWith BinaryMunger Capitalize CapitalizeWords Chr ClassOf Clone CurrentException Date DateNTime DeepClone Downcase

EndsWith EntryChange EntryChangeWithModTime EntryCopy EntryModTime EntryMove EntryRemoveFromSoup EntryReplace EntryReplaceWithModTime EntrySize EntrySoup EntryStore EntryTextSize EntryUndoChanges EntryUniqueID EntryValid ExtractByte

16-62

Writing Meta Data Frames

CHAPTER

16

Supporting Newton Connection

Table 16-14

Newton global functions for meta data functions (continued)

ExtractBytes ExtractChar ExtractCString ExtractLong ExtractPString ExtractUniChar ExtractWord ExtractXLong FindStringInArray GC GetLocale GetSlot GetStores GetUnionSoup GetVar HasSiblingSlot HasSlot HasVariable HourMinute Intern IsArray IsBinary IsFrame IsImmediate

IsInstance IsReadOnly IsSoupEntry IsSubclass Length LessEqualOrGreater LessOrGreater LongDateStr NumberStr Ord Perform PrimClassOf Query Random RemoveSlot ReplaceObject Rethrow SetAdd SetContains SetDifference SetLength SetOverlaps SetRemove SetUnion
continued

Writing Meta Data Frames

16-63

CHAPTER

16

Supporting Newton Connection

Table 16-14

Newton global functions for meta data functions (continued)

ShortDate ShortDateStr Signum Sort SPrintObject StackTrace StrCompare StrConcat StrEqual Stringer StringToDate StringToNumber StringToTime StrLen StrMunger StrPos StrReplace StuffByte StuffChar StuffCString

StuffLong StuffPString StuffUniChar StuffWord Substr Throw Time TimeInSeconds TimeStr TotalClone TotalMinutes TrimString Unordered UnorderedGreaterOrEqual UnorderedLessOrEqual UnorderedOrEqual UnorderedOrGreater UnorderedOrLess Upcase

16-64

Writing Meta Data Frames

CHAPTER

16

Supporting Newton Connection

Newton Connection-Only Functions


The following functions are only available from within Connection and do not exist on the Newton. You can, therefore, use them in meta data methods but not elsewhere.

DockerFlowParagraph
DockerFlowParagraph(paragraph, lineSpec , locale, maxYHeight , defFontSpec ) Flows a paragraph, and in the process compute its height and the character offset of the rst character on the rst line that is below the passed in maxYHeight . The return value is an array containing this information:
Index Contents

0 1 2 paragraph

An error number or 0 Height of owed paragraph The integer giving the character offset of the character that starts the line that is the rst line below the passed-in value. The paragraph to be owed; the horizontal bounds of this paragraph are used to ow the paragraph.

Writing Meta Data Frames

16-65

CHAPTER

16

Supporting Newton Connection

lineSpec

A specication of the line spacing to be used to determine paragraph height as follows:


LineSpec Effect

Use the line spacing specied by the slot view line spacing in the paragraph object Use note pad line spacing, that is, 28 pixels Use calendar note line spacing, that is, 18 pixels Use calendar day note line spacing, that is, 18 pixels The pixel spacing to be used

-1 -2 -3 otherwise locale

A locale bundle used to get line breaking characters; will use current locale if this is nil. The locale bundle is a frame that contains localization information. See the chapter Localizing Newton Applications for more information on the locale bundle. An integer that species a height in pixels to be used. An encoded (10 bits each for family, size, and face) font specication to be used as a default, in case there are no style specs for the paragraph. See the section Specifying a Font in the chapter Working with View Classes.

maxYHeight defFontSpec

GetFolderName
GetFolderName (store, folderSymbol) Returns the name of the folder specied by the symbol parameter. Nil is returned if the folder isnt found in the specied store. This function should be used rather than just using SPrintObject of the symbol because the

16-66

Writing Meta Data Frames

CHAPTER

16

Supporting Newton Connection

symbol and its associated name may be different in non-US localized versions of Newton. store folderSymbol The store containing the folder. The symbol to convert to a string.

GetStoresLocale
GetStoresLocale (store) Returns the locale bundle for the specied store. The locale bundle is just like the one on the Newton. The locale bundle is a frame that contains localization information. See the chapter Localizing Newton Applications for more information on the locale bundle. store The store for which the locale is returned.

StringToParagraphArray
StringToParagraphArray(storeRef, theString, widthSpec) Returns an array with a paragraph object based on the input string. It does the bulk of its work by calling DockerFlowParagraph. storeRef The store to be used to determine the width of the Newton to be used for paragraph widths and locale information. The string to be turned into an array of paragraphs. An integer used to specify the width of the paragraphs as follows:
WidthSpec Effect

theString widthSpec

-1

Use notepad default width, that is, Newton screen width, and maxYHeight passed to DockerFlowParagraph is 3600, and the line spacing passed to DockerFlowParagraph is 28
continued

Writing Meta Data Frames

16-67

CHAPTER

16

Supporting Newton Connection

WidthSpec

Effect

-2

Use calendar note default width, that is, Newton screen width - 16, and maxYHeight passed to DockerFlowParagraph is 151, and the line spacing passed to DockerFlowParagraph is 16 Use calendar crib note default width, that is, Newton screen width - 16, and maxYHeight passed to DockerFlowParagraph is 151, and the line spacing passed to DockerFlowParagraph is 16 Use todo list default width, that is, 204 pixels, and maxYHeight passed to DockerFlowParagraph is 3600, and the line spacing passed to DockerFlowParagraph is 16 Use names note default width, that is 237 pixels, and maxYHeight passed to DockerFlowParagraph is 149, and the line spacing passed to DockerFlowParagraph is 18 If less than 0, use Newton screen width as width; if greater than 0, use passed in width; use natural line spacing, that is, the line spacing specied by the font being used, and use a maxYHeight of 0 (that is, none).

-3

-4

-5

otherwise

Unless widthSpec is -1, the paragraphs are created with the tsSimple font in size 12; for widthSpec of -1, the tsFancy font is used in size 18.

16-68

Writing Meta Data Frames

CHAPTER

16

Supporting Newton Connection

Data Validation Functions


These are functions that Connection provides to help you validate data. You would probably call these functions from your EntryValidation method. (See EntryValidation beginning on page 16-46.) ValidateSlots ValidateSlots (which, toValidate , validationFrame) Takes a validation frame and does slot-level verification. ValidateSlots returns either:
n n

An error string. A frame. In this case, the returned frame should be used instead of the original toValidate parameter since ValidateSlots might have made changes to the data. which A string that identies the application and will be used in error messages. For example, the calendar passes "Calendar" for this parameter The frame to be validated The frame which species how the validation should be performed. Details are discussed after the example.

toValidate validationFrame

Here is a typical use of ValidateSlots: entryValidation: func (toValidate, store) begin toValidate:=ValidateSlots("Names",toValidate,namesValidation); if IsFrame (toValidate) then begin // Do any other special validation here end; return toValidate; end;

Writing Meta Data Frames

16-69

CHAPTER

16

Supporting Newton Connection

The validationFrame parameter to ValidateSlots species how the frames slots should be validated. It is a frame of frames where each slot species a slot in the entry to be validated. Heres an example of a validation frame from the Date Book application: calendarValidation: { viewStationery: {validType: ['meeting, 'repeatingMeeting, 'cribNote], required: true}, mtgStartDate: {validType: 'int, required: true}, mtgDuration: {validType: 'int, required: true}, mtgText: {validType: 'string, required: true}, mtgStopDate: {validType: 'int}, repeatType: {validType: [kDayOfWeek, kWeekInMonth, kDateInMonth, kDateinYear, kPeriod, kNever]}, mtgInfo: {validType: 'int}, mtgAlarm: {validType: 'int}, notesData: {validType: 'note, paraFormat: CalendarFormatProto, nilOK: true}, viewBounds: {validType: 'rect, nilOK: true}, }, Note that there is one slot for each slot in the entry to be validated. The frame for each slot contains the information used for validation. Table 16-15 shows the format.

Table 16-15 Slot

Format for validation frames Values Meaning

validType required

See Table 16-16 true

Species the type of validation for the slot. This slot is required. If a required slot exists then the specied slot must exist in the frame.
continued

16-70

Writing Meta Data Frames

CHAPTER

16

Supporting Newton Connection

Table 16-15

Format for validation frames (continued)

nilOK

true or 'delete

Is nil OK in this slot? If 'delete is specied, the slot is deleted if it contains nil. The default value is true. True means that the frame to be validated need not supply a value for this slot (although if the required slot is true, the slot will still need to be present). 'delete causes ValidateSlots to omit that slot in the resulting validated frame. If the validType is 'note, this value is used for the notes maximum width.

formatProto

integer

The validType slot can contain the values shown in Table 16-16.

Table 16-16 Value

ValidType slot values Meaning

an array 'int 'note 'rect 'string 'labels 'symbol Any other symbol

The slot must match one of the values in the array The slot must contain an integer The slot must contain an array of valid paragraphs The slot must contain a valid rectangle. Left < right, top < bottom. The slot must contain a valid unicode string The slot must contain a symbol The slot must contain a symbol The type of the data in the slot must match the symbol

Writing Meta Data Frames

16-71

CHAPTER

16

Supporting Newton Connection

The validType slot must contain either a type symbol (such as 'int, 'string, or 'company) or an array of values. In the case of the type symbol, the type of the object in the slot to be validated must match that type symbol. In the case of an array, the value of the object must appear in the array. If the validType slot holds a symbol other than the ones explicitly listed in Table 16-16, then the corresponding slot in the frame is valid only if its type is the type indicated by that symbol. Table 16-17 shows some sample validType values.

Table 16-17 Example

Sample ValidTypes Effect

validType: 'symbol validType: 'this validType: 'that validType: ['this] validType: "This" validType: ["This"] validType: 7 validType: [7, 8, 9] validType: ['this, 'that] validType: [7, 8, 9, "This"]

The slot must contain a symbol The slot must contain an object of type 'this The slot must contain an object of type 'that The slot must contain the symbol 'this This is an error The slot must contain a string equal to "This" This is an error The slot must contain either 7, 8, or 9 The symbol 'this or the symbol 'that The slot must contain 7, 8, 9 or "This"

16-72

Writing Meta Data Frames

CHAPTER

16

Supporting Newton Connection

ValidateNotes ValidateNotes (toValidate , slotSymbol, formatProto, store ) After the slots have been veried, you can call ValidateNotes to ow and split notes. ValidateNotes takes an array of paragraphs, and returns an array of arrays of paragraphs. toValidate slotSymbol formatProto The entry to validate. The slot that contains the note data. A frame that species how the note should be verified. It can contain the slots shown in Table 16-18. Examples are shown later in this section. The store that will contain the validated note entry.

store

Table 16-18 Slot

FormatProto slots Meaning

lineHeight maxRight defaultFontSpec maxBottom

The line height used to display the data on the Newton. The largest allowable value for the right bounds. The font used if no style is specied. The maximum bottom bounds. If the note would be longer than this maximum bottom, two possible things can happen. If okToSplit is true, the note is split into multiple notes which are returned. If okToSplit isnt specied or is nil, the note is truncated after the last paragraph that did t. Indicates whether its OK for ValidateNotes to return multiple notes.

okToSplit

Writing Meta Data Frames

16-73

CHAPTER

16

Supporting Newton Connection

Heres an example of using it to verify that a To Do entry contains valid data: toValidate:= ValidateSlots ("Calendar", toValidate, todoValidation); if IsFrame (toValidate) then // It passed toValidate:=ValidateNotes(toValidate,'data, toDoParaFormat,store); This routine is responsible for calling the validation routine on each element, and arranging the paragraphs to t, possibly returning multiple arrays when they dont all t in one note. A caller might want three different results:
n n

Just validate this list Validate this list and chop off all paragraphs that start below some given height Validate this list and break into as many lists as needed such that each ts in some given height

Two slots of the formatProto parameter control which of these cases you get: okToSplit and maxBottom. If there is no maxBottom slot, no splitting is done. If there is a maxBottom slot, then splitting happens at that height and whether or not the note split or truncated is controlled by okToSplit. If okToSplit is nil or not present, no paragraphs that would begin below maxBottom are returned. If okToSplit is true, the returned array will contain multiple arrays of paragraphs, such that each inner array satises a height of maxBottom. In this last case, the splits wont necessarily occur at paragraph boundaries, but wherever they are needed. Here are two example formatProto frames: toDoParaFormat: { lineHeight:16, maxRight:204, defaultFontSpec:simpleFont12, maxBottom: 1000, },

16-74

Writing Meta Data Frames

CHAPTER

16

Supporting Newton Connection

noteParaFormat: { lineHeight:28, maxRight:240, defaultFontSpec:fancyFont18, maxBottom:3600, okToSplit:true }, VerifyParagraph VerifyParagraph (paragraph, maxRight, formatProto) This function veries that the specied paragraph would be valid in a paragraph array, modifying it if necessary. paragraph maxRight formatProto The paragraph to verify. The maximum value allowable for viewBounds.right. Described in ValidateNotes beginning on page 16-73.

Possible return values are:


n n

nilparagraph is invalid, no error message. frame the paragraph is OK (or was xed). The OK paragraph is the return parameter. This can be the same frame that was passed in or a new frame. int an error number: n 1 = invalid paragraph n 2 = bad tab array n 3 = bad style array n 4 = bad font

Writing Meta Data Frames

16-75

CHAPTER

16

Supporting Newton Connection

VerifyParagraphScript VerifyParagraphScript (paragraph, formatProto, which) Performs the same function as VerifyParagraph except it returns an error string instead of the numbers specied above. paragraph formatProto which The paragraph to verify. Described in ValidateNotes beginning on page 16-73. A string used in forming the error message. It should be the name of the application that will contain the entry (Calendar for example).

VerifyParagraphArray VerifyParagraphArray (array , formatProto, locale) Takes an array of paragraphs that will be used in a note, and returns an array of arrays of paragraphs. Each array returned should be used to create a note. This is called by ValidateNotes. array formatProto locale An array of paragraphs that is about to be put into a note. Described in ValidateNotes beginning on page 16-73. The locale bundle to use when verifying the paragraphs. The locale bundle is a frame that contains localization information. See the chapter Localizing Newton Applications for more information on the locale bundle.

This routine is responsible for calling the validation routine on each element, and arranging the paragraphs to t, possibly returning multiple arrays when they didn't all t in one note. A caller might want three different results: 1. Just validate this list 2. Validate this list and chop off all paragraphs that start below some given height 3. Validate this list and break into as many lists as needed such that each ts in some given height.

16-76

Writing Meta Data Frames

CHAPTER

16

Supporting Newton Connection

Two slots of the formatProto parameter control which of these cases you get: okToSplit and maxBottom. If there is no maxBottom slot, no splitting will be done. If there is a maxBottom slot, then splitting will happen at that height and whether the paragraph is truncated or split is controlled by okToSplit. If okToSplit is nil or not present, no paragraphs below maxBottom are returned. If okToSplit is true, the returned array will contain multiple arrays of paragraphs, such that each inner array satises a height of maxBottom. In this last case, the splits won't necessarily occur at paragraph boundaries, but wherever they are needed.

Debugging Meta Data


You can debug a meta data le by running the methods on the Newton using NTK. Note that the functions described in Newton Connection-Only Functions,do not exist on the Newton, however, and cannot be run there. Therefore, you may want to write your methods so they use only functions that exist on the Newton and, when your meta data works with those functions, add Connection-only functions. When Connection loads a synch le, it performs some validation of the meta data entries. This validation consists primarily of checking to see that required items are present, and that if an item is present, it is of the right type. If a meta data entry fails this validation check, an error message similar to one of the following is presented to the user. These have an error number (N), that is an indication of what is wrong. The possible numbers and their interpretations are shown in Table 16-19. The Directory information for the Xyz Application is corrupted. There is a good chance the rest of the le is also corrupted. Suggest you delete this le and re-sync or use a backup. (N) The Directory information for one of the Applications is too corrupted to even get its name. There is a good chance the rest of the le is also corrupted. Suggest you delete this le and re-sync or use a backup. (N)

Debugging Meta Data

16-77

CHAPTER

16

Supporting Newton Connection

Table 16-19 N Item

Meta data validation error messages Problem

1 2 3 4

Soup Name Version NativeExportExceptions

missing or not a string missing or not a string not an integer not an array; or array is zero length; or each entry in the array is not a non-zero length frame or a symbol that names a frame in defaultDefinitions not an array or is a zero length array, or one of the dependent meta data entries doesnt exist or has a problem or doesnt point up to the main meta data Note that Connection will validate the dependent meta data and will return the error number, if any, associated with the dependent meta data, not a 5

Dependents

6 7 8 9 10

NewEntry SoupIndicies SoupInfo EditWith EditInfo

not a frame or a method not an array not a frame not a symbol or main meta data did not exist or this meta data also had a dependents item not an array; or array is zero length; or each entry in the array is not a non-zero length frame or a symbol that names a frame in defaultDefinitions not a frame; or is a zero length frame; or each slot is not a function
continued

11

AttributeFunctions

16-78

Debugging Meta Data

CHAPTER

16

Supporting Newton Connection

Table 16-19 N Item

Meta data validation error messages (continued) Problem

12

DisplayInfo

not an array; or array is zero length; or array has more than 31 entries; or each entry in the array is not a non-zero length frame or a symbol that names a frame in defaultDefinitions not an array; or array is zero length; or each entry in the array is not a non-zero length frame or a symbol that names a frame in defaultDefinitions not a frame; or each slot in the frame is not a non-zero length frame not a frame; or is a zero length frame; or each slot in the frame is not a frame not a method not a method not a method not a method not a method not a method not a method not a method not a method not an integer or an symbol
continued

13

ExportInfo

14 15 16 17 18 19 20 21 22 23 24 25

DefaultDefinitions EditTypes Import TabImport EditImport Export TabExport BrowserExport EditExport EntryValidation ApplyCommands Column0Width

Debugging Meta Data

16-79

CHAPTER

16

Supporting Newton Connection

Table 16-19 N Item

Meta data validation error messages (continued) Problem

26

for main meta data entries there was no displayInfo item or no BrowserExport or Export item or there was an editInfo item and no EditExport or Export item or no EditImport or Import item DontCreateSoups NativeExport NativeImport ExportFilter DeleteEntry not a Boolean not a method not a method not a method not a function

27 28 29 30 31

Troubleshooting Notes
This section has some notes that may help you in creating your meta data.
n

Meta data lends itself to iterative development quite well. Implement one part, test it, and then go on, rather than propagating mistakes throughout. Contrary to intuition, native export and import are often the easiest parts of the meta data to implement, because here are fewer layers that you dont control directly. The exported at les are simply text les with a special type and creator ID, so you can look at what was created. If you have a Macintosh, you need to change the creator type to TEXT using ResEdit or some similar program. Remember to perturb your data to test your validation routines before considering any given part of your meta data complete. Remember that anything in your soup entries that you dont explicitly reference is usually ignored. If you have a frame that contains some easily displayed data and also a massive, complicated structure that will take some work, do the easy ones rst; then you know at least that you have the fundamentals in place before you do the hard part.

16-80

Debugging Meta Data

CHAPTER

16

Supporting Newton Connection

Always remember that validation can return strings, arrays, and nil. If you modify or check slots in the candidate entry frame after validating it, you should call IsFrame(candidate ) to make sure you have a frame. Most functions can add slots to whatever frame they are operating upon, and many can return strings. If you are having a problem completing a given operation, and its one of the functions that can display an error message that you return, then you can use the error message to print debugging information. Alternatively, you can store information in a frame during processing to make it contain pertinent information about what happened. You can use native export to get the contents of the frame into a text le that you can examine.

Native Format
Newton Text Format, usually called native format, is a language that can describe any object that can exist inside Newton and has commands for adding, deleting, modifying or replacing these objects. Native format text that can be used to create a frame in Newton is called a frame description. It is source to a frame in the same way that a .c text file is source to a C program. You use labels within a frame description to name or reference an object. A label is an alphanumeric string enclosed in angle bracket, such as <0> or <name1>. You use native format for transferring information between Newton soups and desktop applications that need more exibility than can be provided by text format. (Text format les consist of rows that contain elds separated by tabs or other characters. The rows are separated by carriage returns or other characters.) On the Macintosh, les containing native format import information are of type DCKe and creator DOCK. (Note that the les contain text.)

Native Format

16-81

CHAPTER

16

Supporting Newton Connection

A native format le begins with a version string, and contains a list of databases, and the commands to perform on them. For example: FORMAT-VERSION 1 { DATABASE "Calendar" { ... } DATABASE "Home-Made Soup" { ... } }. The commands have been removed from this example, but would appear in place of the ellipses.

Commands
Create new objects with ADD; remove existing objects with DELETE; or alter them with MODIFY and REPLACE. For example: DATABASE "Home-Made Soup" { ADD aObject DELETE bObject } In practice, aObject and bObject would actually be frame descriptions. The full frame description syntax is described in Native Format Syntax beginning on page 16-88. Typical frames are specied just like in NewtonScript: curly braces enclosing a comma-delimited list of slots denitions. For example: DATABASE"Home-Made Soup"{ ADD{ person:"Bob", task:"bring soup", count:67, |sub-tasks|:nil } DELETE{ task: "bring brussel sprouts" } }

16-82

Native Format

CHAPTER

16

Supporting Newton Connection

There are three things to note here:


n

The slot name sub-tasks contains a special character and so must be delimited by vertical bars. The DELETE command performs a query on the soup named in the DATABASE command. From that soup, it deletes all objects that match the frame given in the DELETE command. Therefore, you generally only give criteria that specify the objects you want to delete. You do not have to give an entire object denition. White space is ignored. Unlike in NewtonScript, the last slot of a frame denition in native format cannot be followed by a comma. If there is one, the le will not be imported.

n n

ADD
ADD frame The ADD command takes one parameter: a frame to add as a brand new object to a given database. The last modied date of that object, once it has been imported, will be the time that it was imported. You cannot specify a modication time with a _modTime slot. You cannot specify a unique ID with a _uniqueID slot. If you have a unique ID in mind, you probably want to use the MODIFY or REPLACE command.

DELETE
DELETE criteria The DELETE command takes one parameter. It can be either an integer, which is interpreted as the unique ID of the entry to delete, or a frame. In the latter case, the frame is constrained to be at, that is, it can have no entries that are arrays, frames or binary objects (other than real numbers and strings). When using a frame for criteria, all entries in the given database that have the slots and values specied, regardless of what other slots they may have, will be deleted. You may not specify a _modTime slot; the delete command will not match entries based on their last modied date.

Native Format

16-83

CHAPTER

16

Supporting Newton Connection

REPLACE
REPLACE criteria WITH frame The REPLACE command takes two parameters. The rst is the criteria, exactly as in the DELETE command. The second is the new entry to put it in its place, exactly as in the ADD command. No slots from the replaced entry will carry over to the replacement except _uniqueID; you must fully specify it. A REPLACE is exactly like a DELETE followed by an ADD, except that the replaced entries keep their old _uniqueID.

MODIFY
MODIFY criteria DELETESLOTS frame SETSLOTS frame This command takes three parameters:
n n

Criteria, just like DELETE and REPLACE What looks like a frame, but is actually treated as a list of slots to remove from the matching entries A list of slots to add or set in the matches. It is best to specify nil as the value of the slots in the DELETESLOTS frame. As always, you cannot specify _uniqueID or _modTime slots.

Warnings
This section discusses some potential problems you should be aware of in using native format.

The Re-Add Problem


A typical scenario, using import/export, is that Connection exports the current state of a Newton; a third party application imports that data; users alter the data using the third party application; the application writes a le for Connection to import; and Connection re-synchronizes the altered data back into the Newton. Unfortunately, if the third party application writes the le the same way Connection does (all ADD commands), that assumes that those objects are not currently in the Newton, and importing this le will 16-84

Native Format

CHAPTER

16

Supporting Newton Connection

create duplicates. When updating a Newton, it is best to use the REPLACE or MODIFY command with the unique ID of the changed object (supplied on export in a comment).

Circular and Multiple References


It is possible that an entry in a database could contain circular or multiple references. Since entries are self contained, the loop would have to be formed entirely with sub-objects of the entry (including, perhaps, the entry itself). With a totally at export format, you could never describe such an entry. In situations like this, you can use labels to forward declare parts of the entry. Immediately inside any frame description, you may put any number of labeled values for use inside the command clause that contains that frame. The denitions will be available throughout the outermost frame in scope (such as throughout the subject frame of an ADD command, or throughout the subject frame of the WITH clause in a MODIFY command). For example: ADD { <0> := { next: <1> := { next: <2> := { next: name: "ring on child: <0> }

<1> } <2> } <0> } a string",

The things to note about this example are that:


n n n n

Labels are alphanumeric strings delimited with angle brackets The list of forwards is not comma delimited Labels can be referenced before being dened It is an error to redene a label within the scope of a single command clause It is an error to reference a label that is not dened by the end of the command clause containing the reference.

Native Format

16-85

CHAPTER

16

Supporting Newton Connection

Additionally, whenever you dene a value (for example, in a slot) you can label that value at the point of use. Again, the scope of the denition is everywhere in the current command clause. For example: ADD { name: "another ring on a string", child: <0> := { next: { next: { next: <0> } } } } ADD <0> := { name: "ring", next: { next: { next: { next: <0> } } } } Note that, since there are no named slots in arrays, within an array, you may not use the list of forwards, you may only label values at the point of use (though you can use labels dened both outside and inside the array). Here is an example of an array: ADD <0> := { name: "array1", next: [[[<0>]]] }

Binary Objects and Parenthetical Notation


A special notation is used to represent binary objects, or assign a class other than 'string to a string. The notation for this is either (className: "some string data") or (className:# hex data). See the section Native Format Syntax beginning on page 16-88. The class name is absent if there is no class, although the colon is always required. You can specify strings that have special classes, such as company addresses, an example of which is: (company: "Newton Cafe"), or (faxPhone: "415 555-8080"). An example of raw, classless binary data is: (:# 0000FFFF 0000FFFE 000011FF).

16-86

Native Format

CHAPTER

16

Supporting Newton Connection

Binary objects can be any size. If they contain an odd number of nibbles, they are rounded up to the next whole number of bytes by appending 0 bytes.

Export Considerations
When Connection exports in native format (as opposed to with a tab template or translator), you can expect the le to look exactly as this document describes for importing, with a few special rules. Connection exports a database as a series of ADD commands, outputting after each ADD keyword a comment containing the unique-ID and last modication time (if present) of the entry. /* ID=integer */ or /* ID=integer, TIME=integer */ When Connection exports a database, it will list the indexes. When you write a le, you don't have to do this for existing soups (or even new ones you createif you don't want indexes) and their indexes will remain unchanged. When you provide an exportInfo array in the application meta data, it is respected for text exporting. When you provide a nativeExportExceptions array, it is respected for native format exporting. Additionally, Connection will not export copy protected entries. Graphics in Exporting When Connection is about to export a frame that contains graphic data, it calls a routine that does a machine specic imaging of the frame. This routine is platform-dependent and, so, is different on the Macintosh and under Windows. This routine (which comes with Connection and which you cannot change) returns either nil or a binary object. If it a binary object, Connection exports that object as a slot named _exportPictof the very frame it just imaged. The type of the binary object is some meaningful symbol such as PICT. Other platforms might use TIFF, GIF, CCIT3, Postscript, and so on. This type symbol is meant to tell native-format-savvy 3rd party applications how to interpret the data that follows.

Native Format

16-87

CHAPTER

16

Supporting Newton Connection

On the Macintosh, this routine only images ink and polygons. On import, Connection skips over any slots named _exportPict, so that it doesnt convert graphic information back into ink or polygons. One consequence of the way Newton works is that a complicated picture might be built out of many ink- or polygon-views. Each of these views will contain its own _exportPict slot. To correctly draw a composite picture from these elements, you must use the rectangles supplied in the frame ( viewBounds) or if the particular format supports it, the rectangles supplied in the _exportPict object itself, such as the bounds box of a PICT.

Native Format Syntax


This section gives the syntax denitions for native format. In the following denitions, text like this: literal is text that will actually appear, character for character (case is not signicant) in the input le. Text like this: terminal is a construct that is not further dened; the name describes whether it is an identier or an integer. The special symbols in Table 16-20 are used in the syntax descriptions. They do not appear in an input le, unless they appear in the literal style, such as in the denition of array.

16-88

Native Format

CHAPTER

16

Supporting Newton Connection

Table 16-20 Symbol

Symbols used in syntax descriptions Meaning

production ::= rule ; ( expr ) expr* expr+ expr? expr-a |expr-b [] [^]

denition grouping zero or more occurrences of expr one or more occurrences of expr zero or one occurrences of expr alternation character set by inclusion character set by exclusion

Grammar
This section gives the grammar for native format statements. import-file::= FORMAT-VERSION number { (soup-spec { edit-op*} )*}. ; soup-spec::= DATABASE " name" (INDEXES (slot-path , )* slot-path)? ; edit-op::= ADD (LABEL :=)? frame | DELETE ((LABEL :=)? frame|id) | MODIFY ((LABEL :=)? frame|id) DELETESLOTS frame SETSLOTS frame | REPLACE ((LABEL :=)? frame|id) WITH (LABEL :=)? frame ; slot-path::= (slot-spec .)* slot-spec :

index-type ;

Native Format

16-89

CHAPTER

16

Supporting Newton Connection

frame::= { forward-list? slot_list? } ; slot-spec::=

slot-name | slot-index ;

forward-list::= (LABEL := atomic-value)+ ; slot-list::= (slot-decl , )* slot-decl ; slot-decl::=

slot-name : value ;

value::= LABEL | (LABEL :=)? atomic-value ; atomic-value::=SYMBOL | INT | REAL | CHAR | STRING | frame | array | binary ; array::= [ (type-name : )? ((value , )* value)? ] ; binary::= ( type-name? : STRING? ) | ( type-name? : # BYTES ) ;

Native Format Lexical Denitions


Unlike the syntactic denitions above, within a lexical token, white space is signicant and not allowed unless specically noted (such as in a SYMBOL or STRING). letter::= [A -Za-z ] ; digit::= [0 -9 ] ; underscore::= _ ; hex-digit::= [0 -9A-Fa-f ] ; newline::= \n ; SYMBOL::= ' (letter|underscore)(letter|digit|underscore)* | | [^newline] | ;

16-90

Native Format

CHAPTER

16

Supporting Newton Connection

INT::= digit+ | 0 (X |x ) hex-digit+ ; REAL::= digit+ . digit* ; CHAR::= $ [^newline] | $\ hex-digit hex-digit | $\\ ; STRING::= " [^newline]* " LABEL::= < (letter|digit|underscore)+ > ; BYTES:= ({hex-digit}{hex-digit})+

Version
The current format version is 1. Valid input les start with the version of their format.

Case
Case is not signicant except within character or string literals.

Symbols
Identiers that appear in an import le in the position of a value will be treated as a symbol name to be looked up or registered. Symbols must not exceed 254 characters in length. A valid symbol is any sequence of letters, digits and underscores that does not start with a digit, orif enclosed in vertical barsany sequence of characters that does not include a newline character.

Strings
Strings are sequences of characters enclosed in double-quotes. Within a string, case is signicant. Within a string \" evaluates to a double quote, \t is a tab and \n is a newline. Strings cannot contain newline characters other than in the \n form. Strings can span multiple lines by ending them with a double-quote and then starting them again with another double-quote after any amount of white space. For example: "This is" " only one string"

Native Format

16-91

CHAPTER

16

Supporting Newton Connection

You can specify a class other than 'string, for your string, by using the paren notation: (myStringClass: "Hello, World!") String constants specied in import les can contain the \u switch-into/ out-of-unicode-mode symbol, exactly as described in the NewtonScript reference. Binary Data Binary data can be expressed as a '#' followed by a sequence of hex digits. It may only appear inside parenthetical notation. If a class name is provided before the colon, it becomes the class of the binary data. (:# 01234590)(sampleData:# 0A0F 18A1 0A0F 1111 F0FE)

Labels
Labelsstrings of letters, digits and underscores enclosed in angle brackets are used to represent objects previously or not yet dened. A label is not an assignment, it is a denition, and in particular you cannot label a label (such as <0>:=<1>).

Comments
Comments are indicated as in C and C++:
n n

/*... */ for comments that may include newline characters // ... comment to end of line

Specifying Soup Indexes in Import Files


You can use an import le to create new soups. If you do, you may want to specify indexes. Indexes are specied as frames with several slots, only two of which really get set to anything interesting ( 'path, and 'type). See the chapter Data Storage and Retrieval for information on soup indexes.

16-92

Native Format

CHAPTER

16

Supporting Newton Connection

You specify an index for a new soup by expressing the path as a . delimited sequence of path speciers (that is, slot names and array indexes), followed by a : and the symbol of the class. You can check this out in Native Format Syntax beginning on page 16-88, or in any exported le. A typical database command that species the index might look like this: DATABASE "Names" INDEXES sortOn:'String { } An atypical one might look like this: DATABASE "Goofy" INDEXES people.0.name.last:'String { } This specication would imply that all entries in the Goofy soup had a slot named people that contained an array. At element 0 in the array was a frame that contained a slot named name containing a slot named last whose value was a string. If you are writing an import le and you expect the soup you are importing into to exist, you dont need to specify indexes. Specifying an index that already exists in the soup does no damage. Specifying an index that does not exist in the soup will add the index. If the entries in the soup do not satisfy the index then serious errors may occur.

Native Format

16-93

CHAPTER

17

Utility Functions

This chapter describes a number of utility functions. The following groups of functions are included here:
n n n n n n n n n n n n n n n

Object system String Font Bitwise Array Math Floating point math Control of oating point math Financial Exception Handling Message sending Data extraction Data stufng Power handler Miscellaneous

17-1

CHAPTER

17

Utility Functions

Object System Functions


The functions described in this section operate on NewtonScript objects. They perform operations such as getting and checking for slots, removing slots, cloning frames, and so forth. ClassOf ClassOf(object) Returns the class of an object. object The object whose class to return.

The return value is a symbol. Some of the common object classes are: 'int, 'char, 'boolean, 'string, 'array, 'frame, 'function, and 'symbol. Note that this is not necessarily the same as the primitive class of an object. For binary, array, and frame objects, the class can be set differently from the primitive class. Frames or arrays without an explicitly assigned class are of the primitive class 'frame or 'array, respectively. If a frame has a class slot, the value of the class slot will be returned. Here are some examples: f:={multiply:func(x,y) x*y}; classof(f); #1294 Frame f:={multiply:func(x,y) x*y, class:'Function}; classof(f); #1294 Function s:="India Joze"; classof(s); #1237 String See also PrimClassOf on page 17-8.

17-2

Object System Functions

CHAPTER

17

Utility Functions

Clone Clone(object) Makes and returns a shallow copy of an object; that is, references within the object are copied, but the data pointed to by the references is not. object The object to copy.

This is an efcient way to create multiple frames with the same set of slots. Here is an example: seaFrame := {Ocean: "Pacific", Size: "large" , Color: "blue"}; clone (seaFrame); #1665 {Ocean: "Pacific", Size: "large", Color: "blue"} Note that the two frames point to the same strings. DeepClone DeepClone(object) Makes and returns a deep copy of an object; that is, all of the data referenced within the object is copied, including that referenced by magic pointers (pointers to ROM objects). object The object to copy.

It is not guaranteed that every part of the data structure is in RAM. (Certain information, such as the symbols naming frame slots, may be shared with the original object.) Contrast this function with Clone which only makes a shallow copy, and the functions TotalClone and EnsureInternal which ensure that the object exists entirely in internal RAM.

Object System Functions

17-3

CHAPTER

17

Utility Functions

EnsureInternal EnsureInternal(object) Ensures that the object exists entirely in internal RAM. This function may copy all, some, or none of the object to ensure that it exists in RAM. Note that magic pointers are not followed; that is, objects referenced through magic pointers are not copied. object The object to ensure exists in internal RAM.

This function returns an object, which may or may not be a copy of the original object. Note that EnsureInternal(DeepClone(x)) is the same as TotalClone(x) GetVariable GetVariable(frame, slotSymbol) Returns the value of a slot in a frame. If the slot is not found, nil is returned. frame slotSymbol A reference to the frame in which to begin the search for the slot. A symbol naming the slot whose value you want to get.

This function begins its search for the slot in the specied frame and makes use of the full proto and parent inheritance. GetSlot GetSlot(frame, slotSymbol) Returns the value of a slot in a frame. Only the frame specied is searched. frame slotSymbol A reference to the frame in which to look for the slot. A symbol naming the slot whose value you want to get.

17-4

Object System Functions

CHAPTER

17

Utility Functions

If the slot doesn't exist, this function returns nil. Here is an example: seaFrame := {Ocean: "Pacific", Size: "large", Color: "blue"}; getSlot(seaFrame, 'Color); #1692 "blue" Unlike GetVariable, GetSlot searches for a slot only in the indicated frame. Inheritance is not used to nd the slot. The use of the NewtonScript dot operator is similar to the GetSlot function in that it also returns the value of a frame slot. For example, the expression frame.slot returns the value of the specified slot. However, when using the dot operator, if the slot is not found in the specied frame, proto frames are also searched for the slot (but not parent frames). HasSlot HasSlot(frame, slotSymbol) Returns true if the slot exists in the frame, otherwise, returns nil. Inheritance is not used to nd the slot. frame slotSymbol Here is an example: seaFrame := {Ocean: "Pacific", Size: "large", Color: "blue"}; hasSlot(seaFrame, 'Color); #1A TRUE hasSlot(seaFrame, 'Depth); #2 NIL The name of the frame in which to look for the slot. A symbol naming the slot whose existence you want to check.

Object System Functions

17-5

CHAPTER

17

Utility Functions

The exists operator and the HasVariable function are similar to the HasSlot function in that they also check for the existence of a slot in a frame. However, they use different inheritance rules. HasVariable HasVariable(frame, slotSymbol) Returns true if the slot exists in the frame, otherwise, returns nil. This function searches proto and parent frames of the specied frame if the slot is not found there. frame slotSymbol The name of the frame in which to begin the search for the slot. A symbol naming the slot whose existence you want to check. You must use a single quote before the slot name because it is a symbol.

The exists operator and the HasSlot function are similar to the HasVariable function in that they also check for the existence of a slot in a frame. However, they use different inheritance rules. Intern Intern( string ) Creates and returns a symbol whose name is given as the string parameter string. If a symbol with that name already exists, the pre-existing symbol is returned. string IsArray IsArray(obj) Returns true if obj is an array. obj The object to test. The name of the symbol.

17-6

Object System Functions

CHAPTER

17

Utility Functions

IsBinary IsBinary(obj) Returns true if obj is a binary object. obj IsFrame IsFrame(obj) Returns true if obj is a frame. obj IsImmediate IsImmediate(obj) Returns true if obj is an immediate. obj IsInstance IsInstance(obj, class) Returns true if obj's class symbol the same as class or a subclass of class. obj Map Map(obj, function) Applies a function to the slot name and value of each element of an array or frame. obj function An array or frame. A function to apply to the elements or slots in obj. The function is passed two parameters: slot and value. The slot parameter contains an integer array index if obj is an array, or it contains a symbol naming a slot, if obj is a frame. The value parameter contains the value of the array or frame slot referenced by the slot parameter. The object to test. The object to test. The object to test. The object to test.

Object System Functions

17-7

CHAPTER

17

Utility Functions

This is equivalent to: foreach slot,value in obj do call function with (slot,value) PrimClassOf PrimClassOf(object) Returns the primitive class of an object. object The object whose primitive class to return.

Returns a symbol identifying the primitive data structure type of the object, one of: 'immediate, 'binary, 'array, or 'frame. See also ClassOf on page 17-2. RemoveSlot RemoveSlot(object, slot ) Removes a slot from a frame or array. object slot The name of the frame or array from which to remove the slot. A symbol naming the frame slot you want to remove, or the index of the array slot to remove.

This function returns the modied frame or array. ReplaceObject ReplaceObject(originalObject, targetObject) Causes all references to an object to be redirected to another object. originalObject targetObject The original object. The object to which you want to redirect references to originalObject.

This function always returns nil. Note that you cannot specify immediate objects as parameters to this function. 17-8

Object System Functions

CHAPTER

17

Utility Functions

Here is an example: x:={name:"Star"}; y:={name:"Moon"}; replaceobject(x,y); x; #469E69 {name: "Moon"} y: #46A1E9 SetClass SetClass(object, classSymbol) Sets the class of an object. object classSymbol The object whose class to set. A symbol naming the class to give to the object.

{name: "Moon"}

This function returns the object whose class was set. You can set the class of the following kinds of objects: frames, arrays, and binary objects. Note that you cannot set the class of an immediate object. When setting the class of a frame, if a class slot doesn't exist, one is created in the frame. For example: x:={name: "Star"}; setclass(x, 'someClass); #46ACC9 {name: "Star", class: someClass}

Object System Functions

17-9

CHAPTER

17

Utility Functions

TotalClone TotalClone(object) Makes and returns a deep copy of an object; that is, all of the data referenced within the object is copied. object The object to copy.

This function is identical to DeepClone, except that this function guarantees that the object returned exists entirely in internal RAM. TotalClone does not follow magic pointers, so that objects referenced through magic pointers are not copied.

String Functions
These functions operate on and manipulate strings. BeginsWith BeginsWith( string, substr ) Returns true if string begins with substr, or returns nil otherwise. This function is case and diacritical-mark insensitive. An empty substr matches any string. string substr Capitalize Capitalize( string ) Capitalizes the rst character in string and returns the result. string is modied. string The string to modify. The string to test. A string.

17-10

String Functions

CHAPTER

17

Utility Functions

Downcase Downcase( string ) Changes each character in string to lowercase and returns the result. string is modied. string CapitalizeWords CapitalizeWords( string ) Capitalizes the rst character of each word in string and returns the result. string is modied. string EndsWith EndsWith( string, substr ) Returns true if string ends with substr, or returns nil otherwise. This function is case and diacritical-mark insensitive. An empty substr matches any string. string substr EvalStringer EvalStringer( frame, array ) Returns a string containing all of the elements in array concatenated. Any symbols in array are evaluated in the context of the specied frame. frame array A frame used as the context for evaluating symbols in array. An array. The string to test. A string. The string to modify. The string to modify.

Numbers, strings, characters, and symbols are converted to their natural string representation. For elements that are frames, arrays, and Booleans, this function converts them to an empty string.

String Functions

17-11

CHAPTER

17

Utility Functions

FindStringInArray FindStringInArray( array , string ) Finds a string in an array. This function compares the string to each element of the array. If the string matches the value of an array element, the index of that array element is returned. If the string is not found in the array, nil is returned. array string An array to test. A string.

The string comparison used to nd a match is case sensitive. The string in the array must exactly match the string you specify in order for it to be found; a partial word will not be found. FindStringInFrame FindStringInFrame( frame, stringArray, path ) Finds one or more strings, specied by stringArray, in a frame. frame stringArray path A frame to test. An array containing strings. A Boolean indicating whether or not a description of the locations of successful searches should be returned.

This function compares the strings to each slot of the frame that contains a string. If all of the strings you specify in stringArray are found somewhere in the frame, this function returns true. This function recursively searches arrays and frames referenced within the target frame for the strings. If all of the specied strings are not found within the target frame, including other frames and arrays referenced in it, nil is returned. The string comparison used to nd a match is NOT case sensitive (unlike FindStringInArray). And, the search looks for word beginnings only, so it will not nd a string unless it begins a word. For example in the string blackboard, this function would nd the strings blackboard or black, but not board.

17-12

String Functions

CHAPTER

17

Utility Functions

If path is true, and the strings are found in the frame, this function returns an array of entries describing where each occurrence of the strings was found in the frame. A group of three entries is added to the array for each occurrence of a found string. The rst entry in each group is the complete value of the slot where the string was found. The second entry is the path to the slot where the string was found (array elements are indicated by their index). This second entry can be either a slot access expression (e.g. aSlot.anotherSlot.lastSlot), or a path expression array (e.g. [pathExpr: aSlot, 3, lastSlot]) if the path includes an array. And the third entry is the offset (in characters) of the string within the slot where it was found. Here is an example: myframe:={type: 'person, data: {name: "Christine Morrison", employer: {company: "Apple", years: 4, boss: "John Morris"}}} findstringinframe(myframe, ["Morris"], true) #52185B1 ["Christine Morrison", data.name, 10, "John Morris", data.employer.boss, 5]

String Functions

17-13

CHAPTER

17

Utility Functions

FormattedNumberStr FormattedNumberStr( number, formatString ) Returns a formatted string representation of a real number. number formatString A real number. A string specifying how the number should be formatted.

This function works similar to (but not exactly like) the C function printf. The formatString species how the real number should be formatted; that is, whether to use decimal or exponential notation, how many places to include after the decimal point. It accepts the following format speciers: %f %e %E %g %G Use decimal notation (such as "123.456000"). Use exponential notation (such as "1.234560e+02"). Use exponential notation (such as "1.234560E+02"). Use %f or %e, whichever is shorter. Use %f or %E, whichever is shorter.

You can also specify a decimal point followed by a number, after the % symbol (for example,"%.2f") to indicate how many places to show following the decimal point.
Note

FormattedNumberStr, NumberStr, and SPrintObject use the current values of GetLocale().numberFormat. More importantly, they do unexpected things with real numbers. For instance, consider this code: FormattedNumberStr(3.0, "%.0f") This results in "3." not "3.0". If you try the above code with your Newton set to French Canadian Locale, for example, you will get "3," instead of "3.".

17-14

String Functions

CHAPTER

17

Utility Functions

In other words, you will need to strip the decimal character from numbers based on the locale. You can do this with a function like this: StripDecimal: func(x) SubStr(x, 0, StrPos(x, GetLocale().numberFormat.decimalPoint, 0)) ; IsAlphaNumeric IsAlphaNumeric(str) Returns true if str is neither nil nor an empty string. str IsWhiteSpace IsWhiteSpace(char) Returns true if char is a space ($\20), tab ($\09), linefeed ($\0A), or carriage return ($\0D) character; otherwise, this function returns nil. char NumberStr NumberStr( number ) Returns a string representation of the number passed in. number An integer or real number to be converted. A character. A string to test.

For example, if you pass in the value 1234.56, youll get back this string: "1234.56". If you pass in an integer, the string will contain an integer, and if you pass in a real number, the string will contain a real number.

String Functions

17-15

CHAPTER

17

Utility Functions

ParamStr ParamStr( baseString, paramStrArray ) Takes a base string containing substitution placeholders and replaces the placeholders with other strings from an array. baseString paramStrArray The base string containing substitution placeholders. An array of strings to be substituted for the placeholders in the base string.

This function returns the base string after the substitutions have been made. The substitution placeholders in the base string are the following character pairs: "^0", "^1", and so on up to "^9". There can be a maximum of 10 placeholders specied in any order in the base string. But no numbers can be skipped; that is, if the string contains ^2, it must also contain ^1 and ^0. The substitution is done by replacing placeholder ^0 with the rst element from the string array. Then placeholder ^1 is replaced by the second element, and so on. For example, if your baseString is this: "^2 ^0 of each ^1." And your paramStrArray is this: ["Monday", "week", "Every"] Then ParamStr would return this string: "Every Monday of each week."

17-16

String Functions

CHAPTER

17

Utility Functions

SmartConcat SmartConcat(text , len, addText) This function takes an existing smart string text object, adds text, and returns the length of the text object. text len addText A reference to a smart string text object produced by SmartStart. The current length of the string. A string to be added.

This and the other two smart string functions, SmartStart and SmartStop, allow a string to be built up incrementally without generating intermediate garbage on the NewtonScript heap. The caller has to keep track of the current length and pass it in to the SmartConcat function. The smart string object is just a string with excess length, automatically expanded as necessary, and truncated to the correct size when complete. You use SmartStart to allocate the space you expect to need. Then, you build the string using SmartConcat. Finally, if you wish to truncate the string so it is only as long as necessary, you can use SmartStop. For example: ss := SmartStart( 100 ); // param is initial size (hint make it avg. size) off := 0; // need this to maintain length off := SmartConcat( ss, off, "The" ); // new offset // returned off := SmartConcat( ss, off, "quick brown" ); off := SmartConcat( ss, off, "fox jumped" ); off := SmartConcat( ss, off, "over the" ); off := SmartConcat( ss, off, "lazy" ); off := SmartConcat( ss, off, "dog" ); SmartStop( ss, off ); // reclaims all space (rarely used)

String Functions

17-17

CHAPTER

17

Utility Functions

SmartStop is rarely used because the smart string object is usually used for a local variable that will disappear, anyway. For example: func () local x := SmartStart() foreach.... SmartConcat DrawString( x ); end; SmartStart SmartStart(len) This function pre-allocates space for a smart string and returns the reference for this string. len The length you want the string to be.

See SmartConcat, for a description of how to use smart strings. SmartStop SmartStop(string, len ) This function redenes the real physical length of the string. string len A smart string object. The length you want the resulting string to be.

See SmartConcat, for a description of how to use smart strings. SPrintObject SPrintObject( object ) Returns a string of the object passed in. Numbers, strings, characters, and symbols are converted to their natural string representation. For frames, arrays, and Booleans, this function returns an empty string.

17-18

String Functions

CHAPTER

17

Utility Functions

To convert the contents of a frame or array into strings, use the Foreach statement along with the Stringer function to iterate over each slot. To convert a Boolean into a string, you must check for true or nil and return the appropriate string. See the note on page 17-14. StrCompare StrCompare( a, b ) Returns a negative number if string a is less than string b . Returns zero if string a and b are equal. Returns a positive number if string a is greater than string b . Case is not signicant (i.e., Hello and hello are equal). a b A string. A string.

Note that this is a content comparison of the two strings, not a pointer comparison. StrConcat StrConcat( a, b ) Concatenates string b onto string a and returns the result as a new string. a b StrEqual StrEqual( a, b ) Returns true if the two strings, a and b , are equal. a b A string. A string. A string. A string.

Case is not signicant. Note that this is a content comparison of the two strings, not a pointer comparison.

String Functions

17-19

CHAPTER

17

Utility Functions

StrFontWidth StrFontWidth( string, fontSpec ) Returns the width of the string in pixels, if drawn in the specied font. string fontSpec A string. A frame having the following format: {family:familyName,face:faceName,size:pointSize} For more information about specifying fonts, see the section Specifying a Font in the chapter Working With View Classes. Stringer Stringer( array ) Returns a string containing all of the elements in the array concatenated. array An array.

Numbers, strings, characters, and symbols are converted to their natural string representation. For elements that are frames, arrays, and Booleans, this function converts them to an empty string. StringFilter Stringfilter(str, filter, instruction ) Returns a string ltered according to the instruction. str filter instruction The string to be ltered. A string containing characters to be ltered from the string. One of the symbols shown in Table 17-1.

17-20

String Functions

CHAPTER

17

Utility Functions

Table 17-1

Instruction symbols for StringFilter Meaning

Instruction Symbol

'passAll 'passBeginning

Return any letter in str also in filter. Look for any character in filter, and return everything in str after and including that character. Pass only the rst letter of a group in the lter and pass everything else. This is useful to collapse an arbitrary number of spaces to one. Returns any letter in str not in filter Rejects any letter that is in filter until it reaches a letter that isnt in filter. It returns everything past that point.

'passOne

'rejectAll 'rejectBeginning

StringToNumber StringToNumber( string ) Parses a string representing a number and returns the real number value (never an integer). string A string.

The format of the real number returned by this function is determined by values in the current locale bundle. See the Localization chapter for more information. Strings with the following kinds of numbers can be parsed: 1 1.2 -12,345 (12,345.78)a, b

String Functions

17-21

CHAPTER

17

Utility Functions

StrLen StrLen( string ) Returns the number of characters in a string, excluding the null terminator. string StrMunger StrMunger( dstString, dstStart, dstCount, srcString, srcStart, srcCount ) Replaces characters in dstString using characters from srcString and returns the destination string after munging is complete. This function is destructive to dstString . dstString dstStart dstCount The destination string. The starting position within dstString. The number of characters to be replaced in dstString. You can specify nil for dstCount to go to the end of the string A string. This can be nil to simply delete the characters. The starting position in srcString from which to begin taking characters to place into dstString. The number of characters to use from srcString. You can specify nil to go to the end of srcString. A string.

srcString srcStart srcCount Here is an example:

StrMunger("abcdef", 2, 3, "ZYXWV", 0, nil) "abZYXWVf"

17-22

String Functions

CHAPTER

17

Utility Functions

StrPos StrPos( string, substr , start ) Returns the position of substr in string, or nil if substr is not found. The search begins at character position start. (The rst character position in a string is zero.) This function is not case sensitive. string substr start Here is an example: StrPos("abcdef", "Bcd", 0) 1 SubStr SubStr( string, start, count ) Returns a new string containing count characters from string, starting at position start. Character positions begin with zero for the rst character. string start count StrReplace StrReplace( string, substr , replacement, count ) Replaces each occurrence of substr in string with replacement . count is the number of replacements to perform, or nil to replace all occurrences. This function returns the number of replacements performed. string is modied. string substr replacement count A string. A string. A string. An integer. A string. An integer. An integer. A string. A string. An integer.

String Functions

17-23

CHAPTER

17

Utility Functions

StrTruncate StrTruncate( string, length ) Truncates a string to the indicated length, in pixels. (Of course, the length does not include the null terminator.) Returns the truncated string. string length A string. An integer.

StrTruncate requires a current font in order to work. For example, if you call it from a view, the function will use the viewFont slot information. Heres an example of how to use the function from the Inspector: {viewFont: ROM_fontsystem10, msg: func() StrTruncate("abcdefg",25) }:msg() This function adds an ellipsis (...) to the end of the truncated string. StrWidth StrWidth( string ) Returns the width of the string in pixels. string TrimString TrimString( string ) Removes any white space (spaces, tabs, and new line characters) from the beginning and end of string and returns the result. string is modied. string Upcase Upcase( string ) Capitalizes each character in string and returns the result. string is modied. string A string. A string. A string.

17-24

String Functions

CHAPTER

17

Utility Functions

Font Functions
These functions return font information. They all take a font specication as a parameter. You can specify either a font frame or its integer equivalent. For more information about how to specify a font, refer to the section Specifying a Font in the chapter Working With View Classes. FontAscent FontAscent( fontSpec ) Returns the vertical distance from the font baseline to its ascent line in pixels. fontSpec FontDescent FontDescent( fontSpec ) Returns the vertical distance from the font baseline to its descent line in pixels. fontSpec FontHeight FontHeight( fontSpec ) Returns the maximum height of the font in pixels. This equals the font ascent plus the descent plus the leading. fontSpec FontLeading FontLeading( fontSpec ) Returns the font leading in pixels. This is the vertical distance from the font descent line to the ascent line of the next text line below it. fontSpec A font specication. A font specication. A font specication. A font specication.

Font Functions

17-25

CHAPTER

17

Utility Functions

Bitwise Functions
These functions perform logical operations on bits. Band, Bor, Bxor, and Bnot Band(a, b ) Bor(a, b ) Bxor(a, b ) Bnot(a) These bitwise functions each return an integer result of their operation on one or two integer parameters. They perform bitwise AND, OR, XOR, and NOT, respectively. a b An integer. An integer.

Array Functions
These functions operate on and manipulate arrays. AddArraySlot AddArraySlot (array , value) Appends a new element onto an array. array value An array. A value to be added as new element in the array.

17-26

Bitwise Functions

CHAPTER

17

Utility Functions

For example: myArray := [123, 456] #1634 myArray addArraySlot (myArray, "I want chopstix"]) #12 "I want chopstix" myArray #1634 [123, 456, "I want chopstix"] Array Array( size, initialValue ) Returns a new array with size number of elements that each contain initialValue . size initialValue ArrayMunger ArrayMunger( dstArray, dstStart, dstCount, srcArray, srcStart, srcCount ) Replaces elements in dstArray using elements from srcArray and returns the destination array after munging is complete. This function is destructive to dstArray. dstArray dstStart dstCount srcArray srcStart srcCount The destination array. The starting element in the destination array. The number of elements to be replaced in dstArray. You can specify nil for dstCount to go to the end of the array. An array. Can be nil to simply delete the elements. The starting position in the source array from which to begin taking elements to place into the destination array. The number of elements to use from the source array. You can specify nil to go to the end of the source array. An integer. A value.

Array Functions

17-27

CHAPTER

17

Utility Functions

Here is an example: ArrayMunger([10,20,30,40,50], 2, 3, [55,66,77,88,99], 0, nil) [10, 20, 55, 66, 77, 88, 99] Using ArrayMunger is the most efcient way to join two arrays. To put B at the front of A: ArrayMunger(A, 0, 0, B, 0, nil) To put B at the end of A: ArrayMunger(A, Length(A), 0, B, 0, nil) You can also do this with SetUnion, which has the additional property that it eliminates duplicates, but ArrayMunger is much faster if you dont need that property. ArrayPos ArrayPos( array , item, start, test ) Searches for item in array, beginning at array position start, using test . Test is a function you supply. array item start test An array. An item that may be in the array. An integer. A function.

This function uses test to determine if an element satises the search. Test is called once for each array element and is passed two parameters:
n n

item The value of the current array element

When test nds an element that satises the search criteria you want, it should return true. If you specify nil in place of a function for test, ArrayPos tests for equality.

17-28

Array Functions

CHAPTER

17

Utility Functions

This function returns the array position of the rst item that tests true. If no items are found that meet the test then this function returns nil. ArrayRemoveCount ArrayRemoveCount( array , startIndex, count ) Removes one or more elements from an array. array startIndex count The array from which to remove elements.This parameter is modied by this function. An integer the index of the rst element to remove. An integer specifying the number of elements to remove.

Any elements following those removed are shifted left so that no empty elements remain. Length Length (array ) Returns the number of elements in the array. array For example: myArray := [123, 456, "I want chopstix"] length (myArray) #12 3 Note that arrays are indexed from 0, but length returns a count of the number of characters. Therefore, the last element of this example is element 2.
Note

An array.

If you pass a string to this function, you will get a length that is (numChars+1)*2, because characters are stored in Unicode and the null terminator is counted. To get the length of strings, use StrLen instead. u

Array Functions

17-29

CHAPTER

17

Utility Functions

SetAdd SetAdd (array ,value,uniqueOnly) Appends an element to the specied array and returns the modied array. array value uniqueOnly The array to which SetAdd appends the element in value . The element to append to the array specied by array. Whether only unique elements are to be added to the array; if the value of this parameter is non-nil, SetAdd appends value to the array only if it is not already present in the array. If the element specied by the value parameter is already present in the array, SetAdd returns nil and does not append the element. If uniqueOnly is nil, the item is appended to the array without checking whether it is unique.

Note

The type of comparison used in this function is pointer comparison, not content comparison. u SetContains SetContains( array , item ) array item An array. An item that may be in the array.

Searches each element of an array to determine if item is equal to one of the array elements. If a match is found, this function returns the array index of the matching array element. If item is not found in the array, nil is returned.
Note

The type of comparison used in this function is pointer comparison, not content comparison. u

17-30

Array Functions

CHAPTER

17

Utility Functions

SetDifference SetDifference( array1 , array2 ) Returns an array that contains all of the elements in array1 that do not exist in array2 . array1 array 2 An array. An array.

If array1 is nil, nil is returned.


Note

The type of comparison used in this function is pointer comparison, not content comparison. u SetLength SetLength (array , length) Sets the length of an array. array length An array. An integer.

This function is useful for increasing or decreasing the size of an array. If you increase the size of the array, new elements are lled with a nil value. For example: myArray := [123, 456, "I want chopstix"] #1634 myArray setLength (myArray, 4) #1634 [123, 456, "I want chopstix", NIL] myArray [3] := 789 #3156 789 myArray #1634 [123, 456, "I want chopstix", 789]

Array Functions

17-31

CHAPTER

17

Utility Functions

SetOverlaps SetOverlaps( array1 , array2 ) Compares each element in array1 to each element in array2 , and returns the index of the rst element in array1 that is equal to an element in array2. If no equivalent elements are found, nil is returned. array1 array 2
Note

An array. An array.

The type of comparison used in this function is pointer comparison, not content comparison. u SetRemove SetRemove (array , value) SetRemove removes the specified element from the specified array and returns the modied array. The length of the array is decreased by one and all of the elements after the deleted element are shifted by one to the next lowest numbered array position. If the item is not found in the array, this function returns nil. array value
Note

The array from which SetRemove removes the specied element The element to remove from the array specied by array

The type of comparison used in this function is pointer comparison, not content comparison. u

17-32

Array Functions

CHAPTER

17

Utility Functions

SetUnion SetUnion( array1 , array2, uniqueFlag ) Returns an array that contains all of the elements in array1 and all of the elements in array2 . array1 array 2 uniqueFlag An array. An array. If any non-nil value, SetUnion will not include any duplicate items in the array it returns. If uniqueFlag is nil, all elements from both arrays are included, even if there are duplicates.

If both of the arrays are nil, an empty array is returned. SetUnion can eliminate duplicates. If you do not need that property, you can combine two arrays more efciently using ArrayMunger. See page 17-27.
Note

The type of comparison used in this function is pointer comparison, not content comparison. u Sort Sort( array , test, key ) Sorts an array and returns it after it is sorted. The sort is destructive; that is, the array you give it is modied. The sort also is not stable; that is, elements with equal keys wont necessarily have the same relative order after the sort. array test An array. Denes the sort order. It can be a function object that takes two parameters A and B and returns a positive integer if A sorts after B, returns zero if A sorts equivalently to B, and a returns a negative integer if A sorts before B.

Array Functions

17-33

CHAPTER

17

Utility Functions

For much greater speed, specify one of the following symbols for test : '|<| '|>| Sort in ascending numerical order Sort in descending numerical order

'|str<| Sort in ascending string order '|str>| Sort in descending string order key Denes the sort key within each array element. Specify nil to use the array elements directly as they are. You can specify a path expression, in which case the array elements are assumed to be frames or arrays and the path is applied to each element to nd the sort key. Or, you can specify a function that takes one parameter and returns the key.

This example sorts myArray in ascending numerical order according to the timestamp slot of the entries: Sort(myArray, '|<|, 'timestamp) This example sorts myArray in descending string order according to the rst and last names concatenated together: Sort(myArray, '|str>|, func (e) e.first && e.last)

Integer Math Functions


These math functions operate on or return integers. (Some of the oating point functions can also operate on integers.) Abs Abs(x) Returns the absolute value of an integer or real number. x An integer or real number.

17-34

Integer Math Functions

CHAPTER

17

Utility Functions

Ceiling Ceiling(x) Returns the smallest integer not less than the specied real number. (Rounds up the real number to an integer.) x Floor Floor(x) Returns the largest integer not greater than the specied real number. (Rounds down the real number to an integer.) x Max Max( a, b ) Returns the maximum value of the two integers a and b . a b Min Min( a, b ) Returns the minimum value of the two integers a and b. a b Real Real(x) Converts the specied integer to a real number. x An integer. An integer. An integer. An integer. An integer. A real number. A real number.

Integer Math Functions

17-35

CHAPTER

17

Utility Functions

Random Random (low, high) Returns a random integer in the range between the two integers low and high. The range is inclusive of the numbers low and high. low high For example: random (0, 100) #120 72 SetRandomSeed SetRandomSeed (seedNumber) Seeds the random number generator with the number you specify. seedNumber An integer or real number. An integer. An integer.

When seeded with the same number, the random number generator ( Random function) will return the same sequence of random numbers each time you reseed it. To generate virtually random numbers, you can seed it with the value returned from the time function Ticks, like this: SetRandomSeed(Ticks());
Note

There is only one random number generator on the Newton, so calls by other functions may interfere with your function getting a consistent sequence of values. u

17-36

Integer Math Functions

CHAPTER

17

Utility Functions

Floating Point Math Functions


NewtonScript provides the oating point math functions documented in this section. NewtonScript includes special values to account for oating-point results that cannot be otherwise represented. These values are the innities, +INF and -INF, and the not-a-number value NaN. An Innity is a special bit pattern that can arise in one of two ways: 1. When an operation should produce a mathematical innity (such as 1/0), the result is an Innity. 2. When an produces a number with a magnitude too great for the numbers intended oating-point storage format, the result may be a value with the largest possible magnitude or it may be an Innity. These bit patterns (as well as NaNs, introduced next) are recognized in subsequent operations and produce predictable results. The Innities, one positive (abbreviated +INF) and one negative ( -INF), generally behave as suggested by the theory of limits. For example:
n n n

Adding 1 to +INF yields +INF. Dividing 1 by +0 yields -INF. Dividing 1 by -INF yields 0.

When an operation cannot produce a meaningful result, the operation delivers a NaN. For example, 0 divided by 0, +INF added to -INF, and sqrt(1) yield NaNs. NaNs propagate through arithmetic operations. Thus, the result of 3.0 added to a NaN is the same NaN. See the IEEE Floating Point standard documentation or the Apple Numerics Manual for more information on Infinities and NaNs. That manual describes SANE, the Standard Apple Numerics Environment. Newtons oating point facilities are not SANE-compliant, but include many elements of SANE.

Floating Point Math Functions

17-37

CHAPTER

17

Utility Functions

Acos Acos(x) Returns the arccosine of x. x Acosh Acosh(x) Returns the arc-hyperbolic-cosine of x. x Asin Asin(x) Returns the arcsine of x. x Asinh Asinh(x) Returns the arc-hyperbolic-sine of x. x Atan Atan(x) Returns the arctangent of x. x An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number.

17-38

Floating Point Math Functions

CHAPTER

17

Utility Functions

Atan2 Atan2(x,y) Returns the arctangent of x/y in [-pi, pi] using the sign of both parameters to determine the quadrant of the computed value. x y Atanh Atanh(x) Returns the arc-hyperbolic-tangent of x. x CopySign CopySign(x,y) Returns a value with the magnitude of x and sign of y. x y
Note

An integer or real number. An integer or real number.

An integer or real number.

An integer or real number. An integer or real number.

The order of the parameters for CopySign matches the recommendation of the IEEE 754 oating point standard, which is opposite from the SANE copysign function. u Cos Cos(x) Returns the cosine of x. x An integer or real number.

Floating Point Math Functions

17-39

CHAPTER

17

Utility Functions

Cosh Cosh(x) Returns the hyperbolic cosine of x. x Fmod Fmod(x,y) Returns the oating-point modulus of x and y. That is, if m = fmod(x, y) and q = trunc(x / y) then q * y + m = x. x y Erf Erf(x) Returns the error function of x. x Erfc Erfc(x) Returns the complementary error function of x. x Exp Exp(x) Returns ex. x An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number.

17-40

Floating Point Math Functions

CHAPTER

17

Utility Functions

Expm1 Expm1(x) Returns the base e exponential of x - 1, that is: exp(x) - 1 x An integer or real number.

For small enough parameters, expm1 is expected to be more accurate than the straight forward computation of exp(x) - 1. Fabs Fabs(x) Returns the oating-point absolute value of x. x FDim FDim(x,y) Returns the positive difference between its parameters:
n n n n

An integer or real number.

x > y returns x - y x <= y returns +0 If one parameter is a NaN, returns that NaN. If both parameters are NaNs, returns the rst parameter. An integer or real number. An integer or real number.

x y FMax FMax(x,y)

Returns the maximum of its two parameters. This corresponds to the max function in Fortran. NaN parameters are treated as missing data. If one

Floating Point Math Functions

17-41

CHAPTER

17

Utility Functions

parameter is a NaN and the other is a number, then the number is returned. If both are NaNs, then the rst parameter is returned. x y FMin FMin(x,y) Returns the minimum of its two parameters. This corresponds to the min function in Fortran. NaN parameters are treated as missing data. If one parameter is a NaN and the other is a number, then the number is returned. If both are NaNs, then the rst parameter is returned. x y Gamma Gamma(x) Returns the gamma function of x. x Hypot Hypot(x,y) Returns the square root of the sum of the squares of x and y, without undue overow or underow. x y An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number.

17-42

Floating Point Math Functions

CHAPTER

17

Utility Functions

IsFinite IsFinite(x) Returns a Boolean indicating whether or not x is innite. True means that x is nite; nil means x is innite. x IsNaN IsNaN(x) Returns a Boolean indicating whether or not x is a NaN. True means that x is NaN. x
Note

An integer or real number.

An integer or real number.

Saying that x is a NaN and is not a number are not the same thing. The string "foo" is not a number, but is not a NaN either. NaN is a special numerical value. u IsNormal IsNormal(x) Returns true if x is normalized, nil otherwise. LessEqualOrGreater LessEqualOrGreater(a, b ) Returns true if neither a nor b is a NaN, and therefore the two parameters are ordered. a b An integer or real number. An integer or real number.

Floating Point Math Functions

17-43

CHAPTER

17

Utility Functions

LessOrGreater LessOrGreater(a, b ) Returns true if one of the following is true:


n n

a is greater than or less than b Neither a or b is a NaN, and therefore the two parameters are ordered An integer or real number. An integer or real number.

a b LGamma LGamma(x)

Returns the base-e logarithm of the absolute value of the gamma of its parameter x, for x > 0>Logb(x). x Log Log(x) Returns the logarithm of x. x Logb Logb(x) Returns the binary exponent of x as a signed integral value. When the input parameter is a denormalized number, the exponent is determined as if the input parameter had rst been normalized. An integer or real number. An integer or real number.

17-44

Floating Point Math Functions

CHAPTER

17

Utility Functions

Log1p Log1p(x) Returns the base e logarithm of 1+x, that is: log (1+x) For small enough parameters, log1p is expected to be more accurate than the straightforward computation of log (1+x). x Log10 Log10(x) Returns the base-10 logarithm of x. x NearbyInt NearbyInt(x) Returns x rounded to the nearest long int and delivers the result as a real. For example, 12345678.875 rounds to 12345679.0. NearbyInt differs from Rint only in that it does not raise the inexact exception. It is the NearbyInt function recommended by the IEEE oating-point standard 854. x NextAfterD NextAfterD(x,y) Returns the next representable number after x in the direction of y. If x and y are equal, then the result is x. x y An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number.

Floating Point Math Functions

17-45

CHAPTER

17

Utility Functions

Pow Pow(x,y) Returns xy. x y Random RandomX(x) Returns a two-element array, based on the random seed x, which is a real. The rst element of the result is a pseudo-random number that is the result of the SANE randomx function. The second element is the new seed returned by the randomx function. x Remainder Remainder(x,y) Returns the remainder of x divided by y. x y RemQuo RemQuo(x,y) Returns a two-element array. The rst element is the remainder of x divided by y. The second element is the seven low-order bits of x divided by y as a value between -127 and 127. x y An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number.

17-46

Floating Point Math Functions

CHAPTER

17

Utility Functions

Rint Rint(x) Returns x rounded to the nearest long int and delivers the result as a real. For example, 12345678.875 rounds to 12345679.0. x RintToL RintToL(x) Returns x rounded to the nearest int. The result is undened if the rounded value is outside the range of int. x Round Round(x) Returns x rounded to the nearest integral value in double format similar to the Fortran anint function. That is: add half to the magnitude and truncate. x Scalb Scalb(x,y) Scales y by a given integer power x of 2, returning x * 2y. This is more efcient than a straightforward computation of x * 2y. x y An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number.

Floating Point Math Functions

17-47

CHAPTER

17

Utility Functions

SignBit SignBit(x) Returns a non-zero value if the sign of the parameter x is negative. This includes, NaNs, innities and zeros. x Signum Signum(x) Returns 1.0, -1.0, or 0.0, depending on the sign of x, according to these rules:
n n

An integer or real number.

If x is an integer, returns -1 if x < 0, 1 if x > 0, or 0 if x = 0. If x is a real, returns -1.0 if x < 0, 1.0 if x > 0, or 0.0 if x = 0. An integer or real number.

Otherwise this function throws the exception kFramesErrNotANumber. x Sin Sin(x) Returns the sine of x. x Sinh Sinh(x) Returns the hyperbolic sine of x. x Sinh Sqrt(x) Returns the square root of x. x An integer or real number. An integer or real number. An integer or real number.

17-48

Floating Point Math Functions

CHAPTER

17

Utility Functions

Tan Tan(x) Returns the tangent of x. x Tanh Tanh(x) Returns the hyperbolic tangent of x. x Trunc Trunc(x) Returns a real number that contains the integral value nearest to but no larger in magnitude than x. x Unordered Unordered(a, b ) Returns true if a or b is a NaN, and therefore unordered. a b An integer or real number. An integer or real number. An integer or real number. An integer or real number. An integer or real number.

UnorderedGreaterOrEqual UnorderedGreaterOrEqual(a, b ) Returns true if one of the following is true:


n n

a is greater than or equal to b a or b is a NaN, and therefore unordered An integer or real number. An integer or real number. 17-49

a b

Floating Point Math Functions

CHAPTER

17

Utility Functions

UnorderedLessOrEqual UnorderedLessOrEqual(a, b ) Returns true if one of the following is true:


n n

a is less than or equal to b a or b is a NaN, and therefore unordered An integer or real number. An integer or real number.

a b UnorderedOrEqual

UnorderedOrEqual(a, b ) Returns true if one of the following is true:


n n

a is equal to b a or b is a NaN, and therefore unordered An integer or real number. An integer or real number.

a b

UnorderedOrGreater UnorderedOrGreater(a, b ) Returns true if one of the following is true:


n n

a is greater than b a or b is a NaN, and therefore unordered An integer or real number. An integer or real number.

a b

17-50

Floating Point Math Functions

CHAPTER

17

Utility Functions

UnorderedOrLess UnorderedOrLess(a, b ) Returns true if one of the following is true:


n n

a is less than b a or b is a NaN, and therefore unordered An integer or real number. An integer or real number.

a b

Managing the Floating Point Environment


These functions manage the oating point environment. A number of them have to do with oating point exceptions. These are different from other exceptions. The oating point exception macros are shown in Table 17-2.
Table 17-2 Macro Floating point exceptions Value Meaning

FE_INEXACT FE_DIVBYZERO FE_UNDERFLOW FE_OVERFLOW FE_INVALID FeClearExcept

0x00000010 0x00000002 0x00000008 0x00000004 0x00000001

Inexact Divide-by-zero Underow Overow Invalid

FeClearExcept(excepts) Clears the supported exceptions represented by excepts. excepts One or more oating-point exceptions. You can construct excepts by bitwise ORs of the exception macros. For example: FE_OVERFLOW BOR FE_INEXACT

Floating Point Math Functions

17-51

CHAPTER

17

Utility Functions

FeGetEnv FeGetEnv(envp) Stores the current oating-point environment in the envp object. envp A pointer to an object for the oating-point environment.

FeGetExcept FeGetExcept(flagp , excepts) Stores a representation of the exception ags indicated by the integer parameter excepts in the object flagp. flagp excepts A pointer to an object for the oating-point exception ags. One or more oating-point exceptions. You can construct excepts by bitwise ORs of the exception macros. For example: FE_OVERFLOW BOR FE_INEXACT FeHoldExcept FeHoldExcept(envp) Saves the current environment in the envp object, clears the exception ags, and clears oating-point exception enables. envp A pointer to an object for the oating-point environment.

FeRaiseExcept FeRaiseExcept(excepts) Raises the supported exceptions represented by excepts. excepts One or more oating-point exceptions. You can construct excepts by bitwise ORs of the exception macros. For example: FE_OVERFLOW BOR FE_INEXACT

17-52

Floating Point Math Functions

CHAPTER

17

Utility Functions

FeSetEnv FeSetEnv(envp) Installs the oating-point environment represented by the object pointed to by envp. envp A pointer to an object for the oating-point environment. The value of envp must be set by a call to fegetenv or feholdexcept, by an implementationdened macro of type fenv_t, or by the use of the pointer macro FE_DFL_ENV as the parameter.

FeSetExcept FeSetExcept(flagp, excepts) Sets or clears the exception ags indicated by the int parameter excepts according to the representation in the object pointed to by the pointer parameter flagp. flagp A pointer to an object for the oating-point exception ags. The value of flagp must have been set by a previous call to fegetexcept. One or more oating-point exceptions. You can construct excepts by bitwise ORs of the exception macros. For example: FE_OVERFLOW BOR FE_INEXACT This function does not raise exceptions; it just sets the state of the ags. FeTestExcept FeTestExcept(excepts) Determines which of the specied subset of the exception ags are currently set. The parameter excepts species the exception ags to be queried as a bitwise OR of the exception macros. This function returns the bitwise OR of the exception macros corresponding to the currently set exceptions included in excepts.

excepts

Floating Point Math Functions

17-53

CHAPTER

17

Utility Functions

excepts

One or more oating-point exceptions. You can construct excepts by bitwise ORs of the exception macros. For example: FE_OVERFLOW BOR FE_INEXACT

FeUpdateEnv FeUpdateEnv(envp) Saves the current exceptions, installs the environment represented through its pointer parameter envp, and then re-raises the saved exceptions. envp A pointer to an object for the oating-point environment.

This function, which supersedes the SANE function procexit, can be used in conjunction with feholdexcept to write routines which hide spurious exceptions from their callers.

Financial Functions
These functions perform nancial calculations. Annuity Annuity(rate , periods) Calculates the present value factor of an annuity at a given interest rate over the specied number of periods. rate periods The interest rate per period (for example, 12% per year would be specied as a monthly rate of .01). An integer specifying the number of periods.

17-54

Financial Functions

CHAPTER

17

Utility Functions

Compound Compound(rate , periods) Calculates compounded interest factor over the specied number of periods. rate periods The interest rate per period (for example, 12% per year would be specied as a monthly rate of .01). An integer specifying the number of periods.

International Currency Settings These are not separate functions, but this issue is nancial, and, so, is mentioned here. There are two ways to handle currency settings.
n n

FormattedNumberStr formats floating point numbers. You can get the local currency prex and currency sufx from GetLocale.

Here is a sample function that takes a oating point number and returns a correctly-formatted currency string: GetCurrencyString: func(x) begin local s; s := GetLocale().numberFormat.currencyPrefix; // format the number with 2 decimal places s := s & formattedNumberStr(x, "%.2f"); s := s & GetLocale().numberFormat.currencySuffix; end; Here is the quick way to do this: GetCurrencyString: func(x) GetLocale().numberFormat.currencyPrefix & formattedNumberStr(x, "%.2f") & GetLocale().numberFormat.currencySuffix;

Financial Functions

17-55

CHAPTER

17

Utility Functions

Note that the rst parameter to formattedNumberStr must be a real number. See the Localization chapter for more information on GetLocale and on other localization issues.

Exception Functions
These functions are used to raise and handle NewtonScript exceptions in an application. For more information about exception handling and how to use these functions, refer to the chapter Flow of Control in The NewtonScript Programming Language. For a list of system exceptions, see the appendix Errors in this book. The section Managing the Floating Point Environment beginning on page 17-51 describes some functions that deal with oating-point exceptions, which are not related to NewtonScript exceptions. Throw Throw(name , data) Raises an exception and creates an exception frame with the specied name and data. name data An exception symbol that names the exception being raised. The data for the exception. The possible values for this parameter depend on the composition of name and are shown inTable 17-3.

See Flow of Control in The NewtonScript Programming Language for more information on Throw.

17-56

Exception Functions

CHAPTER

17

Utility Functions

Table 17-3 Exception symbol

Exception frame data slot name and contents Slot name

Slot contents

contains prex type.ref contains prex evt.ex.ms| any other Rethrow Rethrow()

data message error

a data object, which can be any NewtonScript object a message string an integer error code

Reraises the current exception to allow the next enclosing Try statement an opportunity to handle it. Rethrow throws the current exception again, passing along the same parameters are were passed with the original call to the Throw function. This allows you to pass control from within an exception handler to the next enclosing Try statement.
IMPORTANT

You can call the Rethrow function only from within the dynamic extent of an onexception clause. s CurrentException CurrentException() During exception processing (that is, inside the dynamic extent of an onexception block), returns the frame that is associated with the current exception. You can examine the frame returned by CurrentException to determine what kind of exception you are handling. For example, you can call the HasSlot function to determine if the frame contains a slot named error, and take appropriate action thereafter. (The format of the frame depends on the exception, but it always contains a name slot with the exception symbol.)

Exception Functions

17-57

CHAPTER

17

Utility Functions

CurrentException gives a meaningful response only from within the dynamic extent of an onexception clause. Outside the extent of onexception, it returns nil.

Message Sending Functions


These methods and functions send messages or execute functions. Perform Perform(frame, message, parameterArray) Sends a message to a frame; that is, a method with the name of the message is executed in the frame. frame message parameterArray The frame to which to send the message. A symbol naming the message to send. An array of parameters to be passed along with the message.

The Perform function returns the return value of the message it sent. Note that the method named by message is executed in the context of frame, not in the context of the frame from within which Perform is called. Heres an example of using this function in the Inspector: f:={multiply: func(x,y) x*y}; perform(f, 'multiply, [10,2]); #50 20 Note that f:multiply(10,2) is equivalent to Perform(f, 'multiply,[10,2])

17-58

Message Sending Functions

CHAPTER

17

Utility Functions

Apply Apply(function, parameterArray) Calls a function, passing the supplied parameters. The Apply function returns the return value of the function it called. function parameterArray The function to call. An array of parameters to be passed to the function.

Apply respects the environment of the closure it is passed. Heres an example of using this function in the Inspector: f:=func(x,y) x*y; Apply(f[10,2]); #50 20 The Apply call is equivalent to: f(10,2); AddDeferredAction AddDeferredAction(function, parameterArray) Queues a function to be run the next time the system main event loop is executed. function parameterArray A function to be executed the next time the system main even loop is executed. An array of parameters to be passed to the function.

You use this function so that the currently executing method (within which this function is called) has a chance to nish its execution and return up the call chain before the function is called. The specied function is called before the next event is handled.

Message Sending Functions

17-59

CHAPTER

17

Utility Functions

Note

If you use the special variable self or the keyword inherited in your AddDeferredAction function, you need to create another function that calls it in a special way in order for it to work correctly. Then, call your function instead of AddDeferredAction. Here is a function you can dene as a slot in your application base frame: MyAddDeferredAction: func(function, parameterArray) AddDeferredAction (func() Apply(function, parameterArray),'[]); In this case, you should call the function MyAddDeferredAction when you want to use AddDeferredAction. u Sending a message using AddDeferredAction is not as straightforward as you might think. For example, this code wont work: AddDeferredAction(frame.message, parameterArray) You must do this, instead: AddDeferredAction(func() frame:message(param, param, ...), []) In fact, heres a wrapper function that you can create and use to send deferred messages: MyAddDeferredMessage: func(frame, message, parameterArray) AddDeferredAction(func() Perform(frame, message, parameterArray), '[]); AddDeferredAction puts a type of event in a first-in-first-out queue which also contains user actions. Normally, this means that if you call AddDeferredAction and then the user clicks, the deferred action will occur rst. However, just because the user takes an action does not mean that it is processed immediately. Different components of the Newton operating

17-60

Message Sending Functions

CHAPTER

17

Utility Functions

system are processed in separate threads and so you cannot rely on events being processed in a predictable order. Note also that idle scripts can get called several times before deferred action scripts are called. Suppose that you have, for example, some networking code that includes code to initialize a form. Since this is networking code, you have an idle script thats being called every 200 milliseconds to look for new names on the network. You then have the form initialized by a deferred action. The idle script may be called two or three times before the deferred action is completed. AddDelayedAction AddDelayedAction(function, parameterArray, delay) Queues a function to be run after a delay. function parameterArray delay A function to be executed after a delay. An array of parameters to be passed to the function. The number of milliseconds after which the function should be executed. The maximum value is 858993, which yields a delay of just over 14 minutes.

Note

If you use the special variable self or the keyword inherited in your AddDelayedAction function, you need to create another function that calls it in a special way in order for it to work correctly. Then, call your function instead of AddDelayedAction. Here is a function you can dene as a slot in your application base frame: MyAddDelayedAction: func(function, parameterArray, delay) AddDelayedAction (func() Apply(function, parameterArray),'[], delay); In this case, you should call the function MyAddDelayedAction when you want to use AddDelayedAction. u

Message Sending Functions

17-61

CHAPTER

17

Utility Functions

You send a message using AddDelayedAction just like you do with AddDeferredAction. For example, this code wont work: AddDelayedAction(frame.message, parameterArray, delay) You must do this, instead: AddDelayedAction(func() frame:message(param, param, ...), [], delay) Here is a wrapper function that you can create and use to send delayed messages: MyAddDelayedMessage: func(frame, message, parameterArray, delay) AddDelayedAction(func() Perform(frame, message, parameterArray), '[], delay);

Data Extraction Functions


These functions are used to extract chunks of data out of other objects of various types. All integers are stuffed and extracted in twos-complement big-endian form. In this form, byte 0 is the most signicant byte, as found on the Newton and Macintosh. The opposite of this is little-endian, where byte 0 is least signicant byte, as found on Intel-based computers. For example, the number 0x12345678 is stored as: big-endian little-endian 12 78 34 56 56 34 78 12

All Unicode conversions use the Macintosh extended character set for codes greater than or equal to 128.

17-62

Data Extraction Functions

CHAPTER

17

Utility Functions

ExtractByte ExtractByte(data, offset) Returns one signed byte from the given offset. data offset For example: ExtractByte("\uFFFFFFFF",0); #3FC 255 ExtractBytes ExtractBytes(data, offset, length , class) Returns a binary object of class class containing length bytes of data starting at offset within data. data offset length class ExtractChar ExtractChar(data, offset) Returns a character object of the character at the given offset in the data. data offset The data from which the return value is to be extracted. An integer giving the position in data from which the return value is to be extracted. The data from which the return value is to be extracted. An integer giving the position in data from which the return value is to be extracted. An integer giving the number of bytes to extract. The class of the return value. The data from which the return value is to be extracted. An integer giving the position in data from which the return value is to be extracted.

Gets one byte at the specied offset, converts it to Unicode and returns the character it makes from it.

Data Extraction Functions

17-63

CHAPTER

17

Utility Functions

For example: ExtractChar("\uFFFFFFFF",0); #2C76 $\u02C7 //Note $a is at offset 1 in a Unicode string ExtractChar("abc",0); #6 $\00 ExtractChar("abc",1); #616 $a ExtractLong ExtractLong(data, offset) Returns an integer object of the low 30 bits of an unsigned long at the given offset, right-justied (that is, the low 30 bits of a four-byte value). data offset The data from which the return value is to be extracted. An integer giving the position in data from which the return value is to be extracted.

Reads four bytes at the specied offset, but ignores the high-order bits (rst two). Returns a 30 bit signed value ExtractLong("\uFFFFFFFF",0); #FFFFFFFC -1 ExtractLong("\uC0000007",0); #1C 7 ExtractXLong ExtractXLong(data, offset) Returns a 30-bit signed integer, left-justied (that is the high 30 bits of a four-byte value) from the specied offset. data offset The data from which the return value is to be extracted. An integer giving the position in data from which the return value is to be extracted.

17-64

Data Extraction Functions

CHAPTER

17

Utility Functions

For example: ExtractXLong("\u0000000F",0); #4 1 ExtractWord ExtractWord(data, offset) Returns an two-byte signed integer object from the given offset. data offset For example: ExtractWord("\uFFFFFFFF",0); #FFFFFFFC -1 //if you want unsigned use: band(ExtractWord(-),0xFFFF); #40004 65535 ExtractPString ExtractPString(data, offset) Returns a Unicode string object derived from the Pascal-style string (a length byte followed by text) at the given offset. data offset The data from which the return value is to be extracted. An integer giving the position in data from which the return value is to be extracted. The data from which the return value is to be extracted. An integer giving the position in data from which the return value is to be extracted.

Data Extraction Functions

17-65

CHAPTER

17

Utility Functions

ExtractUniChar ExtractUniChar(data, offset) Gets two bytes at the specied offset and returns the Unicode character represented by those bytes. data offset For example: ExtractUniChar("abc",0); #616 $a The data from which the return value is to be extracted. An integer giving the position in data from which the return value is to be extracted.

Data Stufng Functions


These functions are used to stuff chunks of data into objects of various types. All integers are stuffed in twos-complement big-endian form. For a discussion of this, see Data Extraction Functions on page 17-62. s WARNING It is important that the destination for the data stufng functions is large enough to hold the data being stuffed. If the destination is not large enough, the NewtonScript heap may become corrupted. Be sure to take into account the offset. Here is a formula you can use: Length( destObj) offset >= size of stuffed data

In this formula, destObj is the destination object and offset is the position within the destination object where the data is to be stuffed. s

17-66

Data Stufng Functions

CHAPTER

17

Utility Functions

StuffByte StuffByte(aString , offset, toInsert) Writes the low order byte of toInsert , at the specied offset in aString . aString offset toInsert For example: x := "\u00000000"; StuffByte(x,0,-1); x[0] #FF006 $\uFF00 x := "\u00000000"; StuffByte(x,0,0xFF); x[0] #FF006 $\uFF00 StuffChar StuffChar(aString , offset, toInsert) Stuffs one byte into aString at the specied offset. aString offset toInsert A string in which data is to be stuffed. The position in aString at which stufng is to begin. A character or integer to be stuffed in aString . You pass it a two byte Unicode value as toInsert. The function makes a one-byte character from that value and stuffs the one-byte character. A string in which data is to be stuffed. The position in aString at which stufng is to begin. The data to be stuffed in aString.

This accepts a character or integer as its third parameter, toInsert :


n n

If toInsert : is an integer: writes the low byte of toInsert . If toInsert: is a character: converts from Unicode and writes a byte.

Data Stufng Functions

17-67

CHAPTER

17

Utility Functions

For example: x := "\u00000000"; StuffChar(x,1,Ord($Z)); x[0] #5A6 $Z x := "\u00000000"; StuffChar(x,1,-1); x[0] #1A6 $\1A ExtractByte(x,1) #68 26 ExtractByte(x,0) #0 0 StuffLong StuffLong(aString , offset, toInsert) Writes four bytes at the specied offset using the 30 bit signed value you pass it as the third parameter, and sign extends it to 32 bytes. aString offset toInsert For example: x := "\u00000000"; StuffLong(x,0,-1); x[0] #FFFF6 $\uFFFF x[1] #FFFF6 $\uFFFF A string in which data is to be stuffed. The position in aString at which stufng is to begin. The data to be stuffed in aString.

17-68

Data Stufng Functions

CHAPTER

17

Utility Functions

x := "\u00000000"; StuffLong(x,0,0x3FFFFFFA); x[0] #FFFF6 $\uFFFF x[1] #FFFA6 $\uFFFA StuffUniChar StuffUniChar(aString , offset, toInsert) Stuffs the two-byte Unicode encoding for the character indicated by toInsert into aString at the specied offset. aString offset toInsert For example: x := "\u00000000"; StuffUniChar(x,0,"\uF00F"[0]); x[0] #F00F6 $\uF00F x := "\u00000000"; StuffUniChar(x,0,0x0AA0); x[0] #AA06 $\u0AA0 A string in which data is to be stuffed. The position in aString at which stufng is to begin. A character or integer to be stuffed in aString .

Data Stufng Functions

17-69

CHAPTER

17

Utility Functions

StuffWord StuffWord(aString , offset, toInsert) Writes the low order two bytes of toInsert at the specied offset. aString offset toInsert For example: x := "\u00000000"; StuffWord(x,0,0x3FFF1234); x[0] #12346 $\u1234 x := "\u00000000"; StuffWord(x,0,-1); x[0] #FFFF6 $\uFFFF A string in which data is to be stuffed. The position in aString at which stufng is to begin. The data to be stuffed in aString.

Power-Related Functions
These functions deal with power issues. AddPowerOffHandler AddPowerOffHandler (view) Registers a view as a power-off handler. view A view.

This means that the view will be sent a powerOffScript message during the system power down (sleep) sequence so that it has a chance to do clean-up operations before the system goes to sleep. Typically, this function is called from the views viewSetupFormScript method.

17-70

Power-Related Functions

CHAPTER

17

Utility Functions

For more information about power off handling, refer to the message powerOffScript in the chapter Handling System Messages. BatteryLevel BatteryLevel(0) Returns values between 0 and 100, where 100 is a maximally charged and 0 is a minimally charged system. However, do not rely on these values, as the battery charge will always uctuate depending on age, battery type and other parameters. Give 0 (zero) as the parameter. RemovePowerOffHandler RemovePowerOffHandler (view) Unregisters a view that has previously been registered as a power-off handler. view A view.

Typically, this function is called from the views viewQuitScript method to remove the view from the power off handler list when the view is being disposed.

Miscellaneous Functions
These are other miscellaneous functions and methods. BinaryMunger BinaryMunger( dst, dstStart, dstCount, src, srcStart, srcCount ) Replaces bytes in dst using bytes from src and returns dst after munging is complete. This function is destructive to dst . dst dstStart A value to be changed. The starting position in dst and

Miscellaneous Functions

17-71

CHAPTER

17

Utility Functions

dstCount src srcStart

The number of bytes to be replaced in dst. You can specify nil for dstCount to go to the end of dst. A value. Can be nil to simply delete the contents of dst. The starting position in the source binary from which to begin taking elements to place into the destination binary. The number of bytes to use from the source binary. You can specify nil to go to the end of the source binary.

srcCount

Bytes are numbered counting from zero. Chr Chr(integer) Converts a decimal integer to its Unicode character equivalent. integer Here is an example: chr(65) $A Compile Compile(string) Compiles an expression sequence and returns a function that evaluates it. string The expression to compile. An integer.

Here are two examples. Note that, in the rst example, x is a local variable. compile("x:= {a:self.b, b:1234}") #440F711 <CodeBlock, 0 args #440F711> f:=compile("2+2") f(); #440F712 4

17-72

Miscellaneous Functions

CHAPTER

17

Utility Functions

Note

All characters used in NewtonScript code must be 7-bit ASCII. This usually is no problem, but can create problems with Compile in certain situations. Suppose you tried this call: Compile ("blah, blah, blah, \u0F0F\u")

The Unicode character is not a 7-bit character, it is 16 bits. Therefore, you get an error. (The \u switch turns on Unicode character mode.) You should do this instead: Compile ("blah, blah, blah, \\u0F0F\\u")

The backslash escape character preceding the \u prevents Unicode mode from being turned on for the compile. (The \u is read simply as the string "\u" instead of the Unicode switch.) Note, also, that: compile("func()...") returns a function that constructs the function. The environment is captured when the function constructor is executed: f := compile("func()b"); x := {a:f, b:0}; g:=x:a(); #440F713 <CodeBlock, 0 args #440F711> Executing the function construction captures the message environment with x as receiver. g(); #440F714 0 So now it can nd b.
u

Miscellaneous Functions

17-73

CHAPTER

17

Utility Functions

GetAppParams GetAppParams( ) Returns a frame containing information about the screen size and other system conguration items. The frame returned contains these slots: appAreaTop The Y coordinate of the top left corner of the screen. appAreaLeft The X coordinate of the top left corner of the screen. appAreaWidth The width of the screen in pixels. appAreaHeight The height of the screen in pixels. buttonBarPosition A symbol ('top, ' left, ' bottom, or 'right) indicating where the button bar is. This is useful if you want to locate your application ush against the button bar. (The button bar contains the Newton application/ scroller icons.) In order to make your applications compatible on future Newton systems, you must compute the size and location of your application based on the values in this frame. This frame may be expanded to include additional slots as other system parameters become relevant on future Newton systems. GetGlobals GetGlobals() Returns the system globals frame. This frame contains all NewtonScript global variables.

17-74

Miscellaneous Functions

CHAPTER

17

Utility Functions

s WARNING Do not create slots in the system globals frame unless it is absolutely necessary. Slots created there are persistent and will continue to exist long after your application is gone. And, slots created there can conict with system data and other applications globals. In most cases, you can put any global data that you need in your application base view or in the system soup. For information on using the system soup, see the section System and User Preferences Data beginning on page 8-11. If you must store data in the globals frame, create just a single slot and store all your data in it. It is imperative that you remove the slot when it is no longer needed. You can do this in the applications RemoveScript method. Follow the PIE Developer Technical Support (DTS) guidelines for naming a global slot. That is, name it with your appSymbol, which includes the signature you have registered with PIE DTS, as explained in Appendix C, Newton Signature Guidelines. s MungePhone rootView:MungePhone(inNum , country) This is the main method that you call to convert nd the correct dialing sequence to use in your current location. It is a method of the root view. Builds from inNum a dialing string based on current user conguration settings. The returned string prexes inNum with an international access code, country code, and area code as appropriate. inNum The phone number to convert. It should generally be of the form <area-code > <phone-number > For example: 415 555 1212 A phone number in San Francisco, USA 81 555 1212 phone number in London, UK

Miscellaneous Functions

17-75

CHAPTER

17

Utility Functions

country

A string that is the name of the country in which inNum is to be dialed. For example: "USA" for "415 555 1212" "UK" for "81 555 1212" Note that the country must be one from ROM_countries, which is discussed below. If you give nil instead of a string, MungePhone assumes that the call is within the country specied in the Country setting in the user s personal preferences.

If the user has stored a calling card number with inNum in the calling options in the Names application, the calling card number is appended to the phone dialing string. ROM_countries is a frame that has one slot for each country for which Newton can convert phone numbers. Each slot is a frame, though the only slot you care about is the name slot. You can get an array of the names of all known countries like this: local countryNames := foreach item in ROM_countries collect item.name ; CallOptionsSlip is the system slip for getting and setting the user call options. This includes the current area code, dialing prex, long distance access code and any calling card numbers the user may have. MungePhone automatically checks these user configuration items, so they will be gured into the return string. Ord Ord (char) Converts a character to its Unicode decimal integer equivalent. char A character.

17-76

Miscellaneous Functions

CHAPTER

17

Utility Functions

Here is an example: ord($A) 65 SetExtrasInfo SetExtrasInfo(appSymbol , newInfo) Changes the extras drawer information for the application specied by appSymbol to the information frame specified in newInfo. The return value of the function is the information frame that was in effect before this call. appSymbol newInfo An application symbol. A new information frame for the application represented by appSymol.

Currently, the only slots supported for the information frame are icon and text: { icon: //BitMap or PICT that shows in the extras drawer text: //text displayed below the icon } If either slot is missing or nil, the value of that slot is not changed. If the application isnt found, this function returns nil.
Note

This function may not be dened in ROM it may be supplied by NTK. u

Miscellaneous Functions

17-77

CHAPTER

17

Utility Functions

Sleep Sleep(ticks ) Puts the Newton to sleep (suspends processing) for the number of ticks given. ticks For example: for i:= 5 to 1 by -1 do begin SetValue(infoView, 'text, "Will restart in " & i & " seconds!"); RefreshViews(); Sleep(6); end; If you leave out the RefreshViews call, the view is not updated until after the last iteration, because calling sleep postpones the view event handling. Notice that the screen is not updated during sleep, even if there is a pending update.
IMPORTANT

An integer giving the number of ticks to sleep. A tick is one sixtieth of a second.

Do not use the sleep function to put the Newton to sleep for very long. The sleep function suspends the Application task, in which all NewtonScript code runs, so the user can do nothing else during a sleep. Occasionally, particularly during communications, you may need to sleep for several seconds, even half a minute, but, in general, sleeping for more than a fraction of a second is too much. If you need a longer delay, consider AddDeferreredAction, AddDelayedAction, or a viewIdleScript method as alternatives. Those methods return control to the main event loop. s

17-78

Miscellaneous Functions

CHAPTER

17

Utility Functions

SysBeep rootView:SysBeep() Plays the system beep sound, or if the system volume is turned off, ashes the current view. This message must be sent to the root view. For example: :SysBeep();

Summary of Functions and Methods


This section contains a summary of the functions and methods described in this chapter. Object System Functions ClassOf(object) Clone(object) DeepClone(object) EnsureInternal(object) GetVariable(frame, slotSymbol) GetSlot(frame, slotSymbol) HasSlot(frame, slotSymbol) HasVariable(frame, slotSymbol) Intern( string ) IsArray(obj) IsBinary(obj) IsFrame(obj) IsImmediate(obj) IsInstance(obj, class) Map(obj, function) PrimClassOf(object) RemoveSlot(object, slot ) ReplaceObject(originalObject, targetObject) SetClass(object, classSymbol) TotalClone(object)

Summary of Functions and Methods

17-79

CHAPTER

17

Utility Functions

String Functions BeginsWith( string, substr ) Capitalize( string ) Downcase( string ) CapitalizeWords( string ) EndsWith( string, substr ) EvalStringer( frame, array ) FindStringInArray( array , string ) FindStringInFrame( frame, stringArray, path ) FormattedNumberStr( number, formatString ) IsAlphaNumeric(str) IsWhiteSpace(char) NumberStr( number ) ParamStr( baseString, paramStrArray ) SmartConcat(text , len, addText) SmartStart(len) SmartStop(string, len ) SPrintObject( object ) StrCompare( a, b ) StrConcat( a, b ) StrEqual( a, b ) StrFontWidth( string, fontSpec ) Stringer( array ) Stringfilter(str, filter , instruction) StringToNumber( string ) StrLen( string ) StrMunger( dstString, dstStart, dstCount, srcString, srcStart, srcCount ) StrPos( string, substr , start ) SubStr( string, start, count ) StrReplace( string, substr , replacement, count ) StrTruncate( string, length ) StrWidth( string ) TrimString( string ) Upcase( string )

17-80

Summary of Functions and Methods

CHAPTER

17

Utility Functions

Font Functions FontAscent( fontSpec ) FontDescent( fontSpec ) FontHeight( fontSpec ) FontLeading( fontSpec ) Bitwise Functions Band(a, b ) Bor(a, b) Bxor(a, b) Bnot(a) Array Functions AddArraySlot (array , value) Array( size, initialValue ) ArrayMunger( dstArray, dstStart, dstCount, srcArray, srcStart, srcCount ) ArrayPos( array , item, start, test ) ArrayRemoveCount( array , startIndex, count ) Length (array ) SetAdd (array ,value,uniqueOnly) SetContains( array , item ) SetDifference( array1 , array2 ) SetLength (array , length) SetOverlaps( array1 , array2 ) SetRemove (array , value) SetUnion( array1 , array2, uniqueFlag ) Sort( array , test, key ) Integer Math Functions Abs(x) Ceiling(x) Floor(x) Max( a, b ) Min( a, b )

Summary of Functions and Methods

17-81

CHAPTER

17

Utility Functions

Real(x) Random (low, high) SetRandomSeed (seedNumber) Floating Point Math Functions Acos(x) Acosh(x) Asin(x) Asinh(x) Atan(x) Atan2(x,y) Atanh(x) CopySign(x,y) Cos(x) Cosh(x) Fmod(x,y) Erf(x) Erfc(x) Exp(x) Expm1(x) Fabs(x) FDim(x,y) FMax(x,y) FMin(x,y) Gamma(x) Hypot(x,y) IsFinite(x) IsNaN(x) IsNormal(x) LessEqualOrGreater(a, b ) LessOrGreater(a, b ) LGamma(x) Log(x) Logb(x) Log1p(x)

17-82

Summary of Functions and Methods

CHAPTER

17

Utility Functions

Log10(x) NearbyInt(x) NextAfterD(x,y) Pow(x,y) RandomX(x) Remainder(x,y) RemQuo(x,y) Rint(x) RintToL(x) Round(x) Scalb(x,y) SignBit(x) Signum(x) Sin(x) Sinh(x) Sqrt(x) Tan(x) Tanh(x) Trunc(x) Unordered(a, b ) UnorderedGreaterOrEqual(a, b ) UnorderedLessOrEqual(a, b ) UnorderedOrEqual(a, b ) UnorderedOrGreater(a, b ) UnorderedOrLess(a, b ) Managing the Floating Point Environment FeClearExcept(excepts) FeGetEnv(envp) FeGetExcept(flagp , excepts) FeHoldExcept(envp) FeRaiseExcept(excepts) FeSetEnv(envp) FeSetExcept(flagp, excepts) FeTestExcept(excepts) FeUpdateEnv(envp)

Summary of Functions and Methods

17-83

CHAPTER

17

Utility Functions

Financial Functions Annuity(rate , periods) Compound(rate , periods) Exception Functions Throw(name , data) Rethrow() CurrentException() Message Sending Functions Perform(frame, message, parameterArray) Apply(function, parameterArray) AddDeferredAction(function, parameterArray) AddDelayedAction(function, parameterArray, delay) Data Extraction Functions ExtractByte(data, offset) ExtractBytes(data, offset, length , class) ExtractChar(data, offset) ExtractLong(data, offset) ExtractXLong(data, offset) ExtractWord(data, offset) ExtractPString(data, offset) ExtractUniChar(data, offset) Data Stufng Functions StuffByte(aString , offset, toInsert) StuffChar(aString , offset, toInsert) StuffLong(aString , offset, toInsert) StuffUniChar(aString , offset, toInsert) StuffWord(aString , offset, toInsert)

17-84

Summary of Functions and Methods

CHAPTER

17

Utility Functions

Power-Related Functions AddPowerOffHandler (view) BatteryLevel(0) RemovePowerOffHandler (view) Miscellaneous Functions BinaryMunger(dst, dstStart, dstCount, src, srcStart, srcCount) Chr(integer) Compile(string) GetAppParams( ) GetGlobals() rootView:MungePhone(inNum , country) Ord(char) SetExtrasInfo(appSymbol , newInfo) Sleep(ticks ) rootView:SysBeep()

Summary of Functions and Methods

17-85

APPENDIX

Errors
This appendix lists the exceptions and error codes that the Newton system software generates. These are grouped into the following categories:
n n n n n

system exceptions Newton system errors Newton hardware errors Newton communications errors NewtonScript environment errors

Each of the categories is subdivided into several tables of related error codes to make it easier to nd an error.

System Exceptions
These are the exceptions that can be raised by the Newton system software. You can handle these exceptions if you so choose.
Exception |evt.ex.fr| |evt.ex.fr;type.ref.frame| |evt.ex.fr.type| |evt.ex.fr.type;type.ref.frame| |evt.ex.fr.comp| |evt.ex.fr.intrp| |evt.ex.fr.intrp;type.ref.frame| Description

NewtonScript frame exception NewtonScript frame exception, with frame data Bad type exception Bad type exception, with frame data Compiler exception Interpreter exception Interpreter exception, with frame data
continued

A-1

APPENDIX

Errors

Exception |evt.ex.fr.store| |evt.ex.comm|

Description

Store exception Communications toolbox error

Newton System Errors


These are the Newton system software errors

Common Errors
These are errors that can occur at almost any time.
Error code Description

0 7000

No error Not enough memory available

Application Errors
These are the application errors.
Error code Description

8001 8002 8003 8004 8005 8006 8007 8008 8009

PCMCIA card battery must be replaced PCMCIA card battery is running low Nothing to undo The routing slip is already open Close box must be tapped to hang up the modem Nothing to print Exception not handled The length of a styles slot had to be extended A length in the read-only styles slot is too short to display the text
continued

A-2

APPENDIX

Errors

Error code

Description

8010 8011 8012 8013 8100 8101 8102 8103 8104 8105

Communications card has been inserted Note has too many items Note is too large Note is too long Blank note could not be created Item could not be moved Changes could not be saved A problem has occurred Problem with the PCMCIA card Note could not be changed

Package Errors
These are the package errors.
Error code Description

10401 10402 10403 10404 10405 10406 10407 10408 10409 10410

Bad package Package already exists Bad package version Unexpected end of package Unexpected end of package part Part type is already registered Part type is not registered No such package exists Newer package already exists Newer version of application already installed

A-3

APPENDIX

Errors

Newton Hardware Errors


These are the Newton hardware errors.

PCMCIA Card Errors


These are the PCMCIA card errors.
Error code Description

10501 10502 10503 10504 10505 10506 10507 10508 10509 10510 10511 10512 10520 10521 10522 10523 10524 10525 10526 10527 10528

Unrecognized card Card not ready Bad power on card Unexpected card error Card reset Card is not initialized Card service is not installed Card service is not suspended Card service has not been resumed No usable congurations on card Card could not be formatted Card could not be formatted because it is write-protected Bad CIS parser procedure pointer Unknown tuple in CIS Unknown subtuple in CIS CIS tuple order is bad CIS tuple size is bad CIS tuple specied as no link has a link CIS tuple specied with a link has no link CIS tuple link target is bad Bad CIS tuple version 1
continued

A-4

APPENDIX

Errors

Error code

Description

10529 10530 10531 10532 10533 10534 10535

Bad CIS tuple version 2 Bad CIS JEDEC tuple Bad CIS checksum Missing CIS Blank CIS Bad CIS Bad link target C

Flash Card Errors


These are the ash card errors.
Error code Description

10551 10552 10553 10554 10555 10556 10557 10558 10559

Flash card is busy Flash card is not erasing Flash card erase is not suspended Flash card suspend erase error Flash card erase failed Flash card write failed Flash card Vpp is low Flash card error in sleep Flash card does not have enough power

A-5

APPENDIX

Errors

Card Store Errors


These are the card store errors.
Error code Description

10600 10601 10602 10603 10604 10605 10606 10607 10608 10609 10610 10611 10612 10613 10614 10615 10616 10617 10618 10619 10620 10621 10622

Attempt to read or write outside of object bounds Bad buffer pointer Bad card access Bad storage type Store not found The store has been write-protected by the user Object not found Flash card block is full Flash card is not virting Write error (one or more bits failed to assert) No more objects Flash card erase in progress Card is full No more blocks left in search on ash card Flash card log is full Card needs to be formatted Bad or unknown PSSID Card memory is full Missing or low battery on SRAM card Attemp to modify store without a transaction in effect Transaction aborted Card needs recovery, but it is write-protected Object too large for store

A-6

APPENDIX

Errors

Newton Communications Errors


These are the Newton comunications errors

Generic AppleTalk Errors


These are the generic AppleTalk errors.
Error code Description

12001 12002 12003 12004 12005 12006 12007 12008 12009 12010 12011 12012 12013 12014 12015 12016

Buffer too small or corrupted Event is pending Cancelled Attempt to cancel failed No handler for cancel Unknown message receiver Cannot create AppleTalk port Cannot create AppleTalk task Not implemented Data length error No such subject available to open Not opened AppleTalk is not open AppleTalk is already open Duration is too small Duration is too large

A-7

APPENDIX

Errors

LAP Protocol Errors


These are the LAP protocol errors.
Error code Description

12100 12101 12102 12103 12104

LAP read link failed LAP all protocols in use No protocol handler No such command Bad link

DDP Protocol Errors


These are the DDP protocol errors.
Error code Description

12200 12201 12202 12203 12204 12205 12206 12207 12208 12209 12210 12211 12212 12213

No such DDP command Invalid socket Not in static socket range Not in dynamic socket range Socket is already open Socket not open Socket internal socket Socket is in use Unknown LAP type DDP back check sum Bad packet size No listener for socket No such protocol type known External client timed out

A-8

APPENDIX

Errors

NBP Protocol Errors


These are the NBP protocol errors.
Error code Description

12300 12301 12302 12303 12304 12305 12306 12307 12308 12309 12310 12311 12312 12313 12314

Bad form Name is already registered Too many names Name is not registered Too many names requested Too many lookups are pending Not a NBP packet DDP type Unknown NBP function Unknown NBP lookup reply Too many tuples in lookup request NBP lookup is in use NBP index out of range NBP lookup aborted No such command No names found

AEP Protocol Errors


These are the AEP protocol errors.
Error code Description

12400 12401 12402 12403

No such command Not an echo packet DDP type AEP packet size is zero AEP function not requested

A-9

APPENDIX

Errors

RTMP Protocol Errors


These are the RTMP protocol errors.
Error code Description

12500 12501 12502 12503 12504

No such command Packet size is zero RTMP routed RTMP address unresolved RTMP no router available

ATP Protocol Errors


These are theATP protocol errors.
Error code Description

12600 12601 12602 12603 12604 12605 12606 12607 12608 12609 12610 12611 12612

No such command No ATP packet DDP type Unknown ATP function ATP request data length is zero Expected responses are out of range Response buffer is too small ATP retry duration too small ATP transaction timed out Responding socket already open Responding socket not open Response packet length bad Bad number of response packets Socket already has a request on autorequest

A-10

APPENDIX

Errors

PAP Protocol Errors


These are the PAP protocol errors.
Error code Description

12700 12701 12702 12703 12704 12705 12706 12707 12708 12709 12710 12711 12712 12713 12714 12715 12716

No such command Unexpected connection ID Invalid connection ID Invalid responder socket Unexpected function Printer is busy Unexpected connection open result Bad ow quantum requested Connection timed out EOF sent PAP ushed Printer terminated connection Printer not found No status available No data available The buffer that was passed is too small Put data operation timed out

ZIP Protocol Errors


These are the ZIP protocol errors.
Error code Description

12800

No zones

A-11

APPENDIX

Errors

ADSP Protocol Errors


These are the ADSP protocol errors.
Error code Description

12900 12901 12902 12903

Too many ADSP connections ADSP mode invalid ADSP packet size bad ADSP control type bad

Communications Tool Errors


These are the communications tool errors.
Error code Description

16005 16009 16013 16021

Cancelled Phone connection was cut off Cancelled No phone number was provided

Serial Tool Errors


These are the serial tool errors.
Error code Description

18003

Bad connection

FAX Errors
These are the FAX errors.
Error code Description

22001 22002

FAX could not be sent FAX could not be sent


continued

A-12

APPENDIX

Errors

Error code

Description

22003 22004 22005 22006 22007

FAX could not be sent FAX could not be sent FAX machine had a problem printing some pages FAX could not be sent FAX could not be sent

Modem Errors
These are the modem errors.
Error code Description

24000 24003 24004 24002 24001 24005 24007

No modem is connected The phone number is busy There is no answer There is no answer There is no dial tone Your modem is not responding properly The modem is not responding properly

Sharp IR Errors
These are the Sharp infrared errors.
Error code Description

38001 38002 38006 38008

No response Cancelled Bad connection Beaming error

A-13

APPENDIX

Errors

Online Service Errors


These are the online service errors.
Error code Description

40102 40103 40104 40105 40106

Lost connection to host Lost connection to host The host is not responding There is a problem reading from the host Failed to connect to local access number

Printing Errors
These are the printing errors.
Error code Description

44000 44001 44002 44003 44004 44005 44100 44101 44102 44103 44104 44105 44106 44107 44108

Printer problem Newton is unable to print No printer is connected Printer busy Printing stopped Lost contact with the printer The next sheet of paper must be inserted The phone number must be dialed now There is no paper tray The wrong paper tray is attached The printer has no paper The printer has no ink The printer is jammed The printer door is open The printer is off-line

A-14

APPENDIX

Errors

NewtonScript Environment Errors


These are the NewtonScript error codes.

Store and Soup Errors


These errors are related to stores and soups.
Error code Description

48001 48002 48003 48004 48005 48009 48010 48011 48012 48013 48014 48015 48016 48017 48018 48019 48020 48021 48022 48023 48024 48025

The PCMCIA card is not a data storage card Store format is too old to understand Store format is too new to understand Store is corrupted, can't recover Single object is corrupted, can't recover Not a soup entry Tried to remove a store that was not registered Soup index has an unknown type Soup index has an unknown key structure Soup index does not exist A soup with this name already exists Tried to CopyEntries to a union soup Soup is invalid (probably from a removed store) Soup is invalid (probably from a removed store) Entry is invalid (probably from a removed store) Key does not have the type specied in the index Store is in ROM Soup already has an index with this path Internal errorsomething unexpected happened Tried to call RemoveIndex on the _uniqueID index Query type missing or unknown Discovered index inconsistency

A-15

APPENDIX

Errors

Object System Errors


These errors are related to the object system.
Error code Description

48200 48202 48203 48204 48205 48206 48207 48210 48211 48214 48215

Expected a frame, array, or binary object Empty path Invalid segment in path expression Path failed Index out of bounds (string or array) Source and destination must be different objects Long out of range Bad arguments String too big Object is read-only Functionality is unimplemented

Bad Type Errors


These errors are caused by data of the wrong type.
Error code Description

48400 48401 48402 48403 48404 48405 48406 48407 48408

Expected a frame Expected an array Expected a string Expected a pointer Expected a number Expected a real Expected an integer Expected a character Expected a binary object
continued

A-16

APPENDIX

Errors

Error code

Description

48409 48410 48411 48412 48413 48414 48415 48416 48417 48418

Expected a path expression (or a symbol or integer) Expected a symbol Expected a symbol Expected a frame or an array Expected an array or nil Expected a string or nil Expected a binary object or nil Unexpected frame Unexpected binary object Unexpected immediate

Interpreter Errors
These are interpreter errors.
Error code Description

48800 48802 48803 48804 48806 48807 48808 48809 48810 48811 48814

Not in a break loop Too many argumentss for a CFunction Wrong number of arguments FOR loop BY expression has value zero No current exception Undened variable Undened global function Undened method No _proto for inherited send Tried to access slot in nil context Local variables and FOR/WITH loops not allowed at top level

A-17

APPENDIX

The Inside Story on Declare


This appendix describes the technical details of the declare mechanism. Knowing these technical details is not necessary to understanding what declaring a view means; they are provided primarily for completeness. For a basic discussion of the declare mechanism, see the section View Instantiation beginning on page 2-41. You should be familiar with that material before reading this appendix. To serve as an example here, imagine a calculator application whose base view is named Calculator. It has (among others) a child view named Display. The Display view is declared in the Calculator view. See Figure B-1 for an illustration of this example. In the following sections, well explain what happens at compile time and at run time as a result of the declare operation. A number of slots are created, which you may see in the Newton ToolKit (NTK) Inspector if you are examining the view templates.

Compile-Time Results
As a result of the declare operation, at compile time, NTK creates a slot in the place where the view is declaredthat is, in the Calculator template. The name of the slot is the name of the declared view, Display. This slots value is initially set to nil. Another slot, called stepAllocateContext, is also created in the Calculator template. This slot holds an array of values (two for each view declared there). The rst value in each pair is a symbol used by the system at run time to identify the name of the slot in the Calculator view that holds a reference to the declared view. This symbol is simply the name of the declared view, Display. B-1

Compile-Time Results

APPENDIX

The Inside Story on Declare

The second value in each pair is a reference to the template for the declared view. At run time, the system will preallocate a view memory object for the declared view from this template.
Note

Protos built into the system use an analogous slot called allocateContext, that holds the same thing as stepAllocateContext. The allocateContext slot is for declared children from the viewChildren array and the stepAllocateContext slot is for declared children from the stepChildren array. u Also, as a result of the declare operation, NTK creates a slot in the Display template called preallocatedContext. This slot holds a symbol that is the name of the template, in this case 'Display. This symbol will be used by the system when the view is instantiated time to nd the preallocated view memory object for the Display view.

Run-Time Results
When the Calculator view is opened (even before its viewSetupFormScript is executed), a view memory object is preallocated for each view declared in Calculator. (The information required to do this is obtained from the allocateContext and stepAllocateContext slots.) In our example, a view memory object is created for the Display view. The Display slot in the Calculator view is updated so that it points to the newly allocated Display view object. Later in the instantiation process for the Calculator view, its child views are created and shown, including the Display view. At this time, the view system looks at the template for the Display view, sees the preallocatedContext slot, and knows that a view memory object has been preallocated for this view. Using this slot, the system can nd the preallocated view. The value of the preallocatedContext slot is the name of another slot in the Calculator view. The system locates this slot in the Calculator view, and

B-2

Run-Time Results

APPENDIX

The Inside Story on Declare

nds there a reference to the preallocated view object. Instead of creating a new view object for the Display view, the system uses the preallocated view.

Figure B-1

Declare example

Run-Time Results

B-3

APPENDIX

Newton Signature Guidelines


To avoid name conicts with other Newton application, you need to register a single developer signature with PIE DTS. You can then use this signature as the basis for creating unique application symbols, soup names and other global symbols and strings according to the guidelines described in this Appendix. The rst part of this appendix describes the content of a valid signature and tells you how to register it with PIE DTS. The remainder of this appendix describes how to use your registered signature to create various strings and symbols used in Newton applications.

Signature
A signature is an arbitrary sequence of approximately 4 to 10 characters. Any characters except colons (:) and vertical bars(|) can be used in a signature. Case is not signicant. Like a handwritten signature, the developer signature uniquely a Newton application developer. The most important characteristic of a signature is that it is unique to a single developer, which is why PIE DTS maintains a registry of developer signatures. Once you have registered a signature with PIE DTS it is yours, and will not be assigned to any other developer. Examples of valid signatures include PIEDTS Joes Cool Apps 1PIE2DTS What the #$*? SW

Signature

C-1

APPENDIX

Newton Signature Guidelines

How to Register
To register your signature, you need to provide the following information to the PIE Development Information Group at Apple. Name: Contact Person: Mailing Address: Phone: Email Address: Desired Signature 1st choice: Desired Signature 2nd choice: Send this information to the PIESYSOP AppleLink address, or send it via US Mail to: PIESYSOP c/o: Apple Computer, Inc. 20525 Mariani Avenue, M/S 305-2A Cupertino, CA 95014 USA

Application Name
The application name is the string displayed under your application's icon in the Extras drawer. Because it is a string, any characters are allowed. This symbol does not need to be unique, because the system does not use it to identify the application. For example, it is possible for there to be two applications named Chess on the market. The application name is used only to identify the application to the user. If there were in fact two applications

C-2

How to Register

APPENDIX

Newton Signature Guidelines

named Chess installed on the same Newton device, hopefully the user could distinguish one from the other by some other means, perhaps by the display of different icons in the Extras drawer. Examples of valid application names include Llama Good Form 2 Fun 4 U Chess
Note

Its recommended that you keep your application names short so that they dont crowd the names of other applications in the Extras drawer. u

Application Symbol
The application symbol is created by concatenating the application name, a colon(:), and your registered developer signature. This symbol is not normally visible to the end user. It is used to uniquely identify an application to the root view. Because application symbols contain a colon (:), they must be enclosed by vertical bars (|)where they appear explicitly in NewtonScript code Examples of valid application symbols include '|Llama:PIEDTS| '|2 Fun 4 U:Joes Cool Apps|

Application Symbol

C-3

APPENDIX

Newton Signature Guidelines

Package Name
The package name is simply a string version of the application symbol. The package name is visible to the user in the picker displayed when removing software. Package names are limited to 26 characters, so this places a practical limit on the combined length of application names and signatures.

Predened Constants
It is suggested that you dene constants for your application symbol and package name in your applications Project Data le in NTK. For example, constant kAppSymbol := '|Llama:PIEDTS|; constant kPackageName := "Llama:PIEDTS"; Use of these constants throughout your code make it easier to maintain your code. All you need to do is keep your constant denitions consistent with the values in the Settings... dialog box in NTK. A future version of NTK may automatically dene these constants for you. The remaining examples in this appendix assume that the constant denitions described here are in effect.

Soup Names
The soups your application creates need to have unique names. If your application creates only one soup, you can use your package name directly as your applications soup name. If your application creates multiple soups, you can name them by using your application name as a sufx to a descriptive soup name, with a colon (:) used to separate the application name and

C-4

Package Name

APPENDIX

Newton Signature Guidelines

the descriptive soup name. Soup names are not normally visible to the user, except in the Newton Connection application. Examples of valid soup names include Llama:PIEDTS kPackageName soup1:Llama:PIEDTS soup2 & kPackageName

System Soup Tag


Applications are expected to store their preferences data in the system soup. Each application storing preferences data should create a single soup entry with a unique tag slot and other application specic slots. Use your package name as your tag. This tag is not normally visible to the end user. However, if utility software is written to clean up the System soup, this tag may be used to describe the soup when prompting the user regarding its deletion. Here is an example of a valid soup tag: {tag: kPackageName, firstName: "Reg"}

Additional Soup Fields


Applications are encouraged to utilize existing soups, such as the Names soup. To store your own data in the entries of an existing soup, your application should create a single slot using its application symbol as the slot name, as in the following example. entry.(kAppSymbol) := { <AppSpecificData> };

System Soup Tag

C-5

APPENDIX

Newton Signature Guidelines

Routing Formats
Applications need to store their formatting frames in the root view. Each formatting frame stored in the root view must be named. The named formatting frame can then stored in a slot named for the format's name concatenated with a colon and the application symbol, as in the following examples. Examples: GetRoot().('|fmt1:Llama:PIEDTS|) := { <Fmt Frame> }; GetRoot().(Intern("fmt2:" & kPackageName) := { <Fmt Frame> };

Global Variables
Although the use of system-wide global variables is strongly discouraged, its sometimes necessary to use them. To do so, your application should create a single global data repository by adding to the globals frame a single slot named for the application symbol, as in the following example. GetGlobals().(kAppSymbol) := <AppSpecificData>;

C-6

Routing Formats

Glossary

Application base view The topmost parent view in an application. The application base view encloses all other views that make up the application. Array A sequence of numerically indexed slots (also known as the array elements) that contain objects. The rst element is indexed by zero. Like other non-immediate objects, an array can have a user-specied class, and can have its length changed dynamically. Binary object A sequence of bytes that can represent any kind of data, can be adjusted in size dynamically, and can have a user-specied class. Examples of binary objects include strings, real numbers, sounds, and bitmaps. Boolean A special kind of immediate that is called true. Functions and control structures use nil as false and anything else as true. If you dont have anything else to use, use true. Child A frame that references another frame (its parent) from a _parent slot. With regard to views, a child view is enclosed by its parent view.

GL-1

GLOSSARY

Class

Constant

Cursor

A symbol that describes the data referenced by an object. Arrays, frames, and binary objects can have user-dened classes. A value that does not change. In NewtonScript the value of the constant is substituted wherever the constant is used in code. An object returned by the Query function. The cursor contains methods used to iterate over a set of soup entries meeting the criteria specied in the query. The addition or deletion of entries matching the query specication is automatically reected in the set of entries referenced by the cursor, even if the changes occur after the original query was made.

Declaring a template Registering a template in another view (usually its parent) so that the templates view is pre-allocated when the other view is opened. This allows access to methods and slots in the declared view. Entry A frame stored in a soup and accessed through a cursor. An entry frame contains special slots that identify it as belonging to a soup. Enumerated dictionary A list of words that can be recognized when this dictionary is enabled. See also lexical dictionary. Evaluate slot A slot thats evaluated when NTK (Newton ToolKit) compiles the application. Field An area in a view where a user can write information. Flag A value that is set either on or off to enable a feature. Typically ag values are single bits, though they can be groups of bits or a whole byte. Frame An unordered collection of slots, each of which consists of a name and value pair. The value of a slot can be any type of object, and slots can be added or removed from frames dynamically. A frame can have a user-specied class. Frames can be used like records in Pascal and structs in C, but can also be used as objects which respond to messages.

GL-2

GLOSSARY

Function object

Function objects are created by the function constructor: func(args) funcBody . An executable function object includes values for its lexical and message environment, as well as code. This information is captured when the function constructor is evaluated at run time. A handwritten mark that is recognized as having a special meaning in the Newton system, such as tap, scrub, caret, and so on. A variable or function that is accesible from any NewtonScript code. An NTK le named GlobalData, in the same folder as the NTK application, that is compiled once each time you launch NTK. You can place in it NewtonScript code that you want available from any project. A set of rules dening the format of an entity to be recognized, such as a date, time, phone number or currency value. Lexical dictionaries are composed of sets of grammars. A value that is stored directly rather than through an indirect reference to a heap object. Immediates are characters, integers, or Booleans. See also reference. The frame in which a method is dened. See also receiver. The mechanism by which attributes (slots or data) and behaviors (methods) are made available to objects. Parent inheritance allows views of dissimilar types to share slots containing data or methods. Prototype inheritance allows a template to base its denition on that of another template or prototype. To make a run-time object in the NewtonScript heap from a template. Usually this term refers to the process of creating a view from a template. The topmost parent of all other views in a single NTK layout le.

Gesture

Global Global data le

Grammar

Immediate

Implementor Inheritance

Instantiate

Layout view

GL-3

GLOSSARY

Lexical dictionary

Local

Magic pointer

Message

Method Object

Origin

Package

Parent

Part PCMCIA

A list of valid grammars, each specifying the format of an entity to be recognized, such as a date, time, phone number or currency value. See also enumerated dictionary. A variable whose scope is the function within which it is dened. You use the local keyword to explicitly create a local variable within a function. A constant that represents a special kind of reference to an object in the Newton ROM. Magic pointer references are resolved at run time by the operating system, which substitutes the actual address of the ROM object for the magic pointer reference. A symbol with a set of arguments. A message is sent using the message send syntax, frame:messageName(), where the message, messageName, is sent to the receiver, frame. A function object in a frame slot that is invoked in response to a message. A typed piece of data that can be an immediate, array, frame, or binary object. In NewtonScript, only frame objects can hold methods and receive messages. The coordinates of the top-left corner of a view. This is usually (0, 0), however, it can be shifted, for example to scroll the contents of a view. The unit in which software can be installed on and removed from the Newton. A package consists of a header, which contains the package name and other information, and one or more parts, which contain the software. A frame that is referenced through the _parent slot of another frame. With regard to views, a parent view encloses its child views. The code or data portion of a package. A single package can contain multiple parts. Personal Computer Memory Card International Association. This acronym is used to describe the

GL-4

GLOSSARY

Picker

Project

Project data le

Project le Proto

Receiver

Reference Resource

Root view Self

memory cards used by the Newton PDA. Newton memory cards follow the PCMCIA standards. A type of view on the Newton that pops up and contains a list of items. The user can select an item by tapping it in the list. This type of view closes when the user taps an item in the list or taps outside of it without making a selection. The collected les and specications that NTK uses to build a package that can be downloaded and executed on the Newton. An NTK le named Project Data, in the same folder as a project le, that denes an applications InstallScript and RemoveScript and any project-wide, compile-time declarations. The project data le is processed rst when NTK builds an application. An NTK le that contains a list of les to be included in a build and the build specications. A frame that is referenced through another frames _proto slot. With regard to views, a proto is not intended to be directly instantiatedyou reference the proto from a template. The system supplies several view protos, which an application can use to implement user interface elements such as buttons, input elds, and so on. The frame that was sent a message. The receiver for the invocation of a function object is accessible through the pseudo-variable self. See also implementor. A value that indirectly refers to an array, frame, or binary object. See also immediate. Raw datausually bitmaps or soundsstored on the development system and incorporated into a Newton application during the project build. The topmost parent view in the view hierarchy. All other views descend from the root view. A pseudo-variable that is set to the current receiver.

GL-5

GLOSSARY

Siblings Slot Soup

Store

Template

Tick User proto View

View class

Child frames that have the same parent frame. An element of a frame or array that can hold an immediate or reference. A persistently stored object that contains a series of frames called entries. Like a database, a soup has indexes that can be used to access entries in a sorted order. A physical repository that can contain soups and packages. A store is like a volume on a disk on a personal computer. A frame that contains the data description of an object (usually a view). A template is intended to be instantiated at run time. See also proto. A sixtieth of a second. A proto dened by an application developer, not supplied by the system. The object that is instantiated at run time from a template. A view is a frame that represents a visual object on the screen. The _proto slot of a view references its template, which denes its characteristics. A primitive building block on which a view is based. All view protos are based directly or indirectly (through another proto) on a view class. The view class of a view is specied in the viewClass slot of its template or proto.

GL-6

Index
A
Abort 14-33, 14-41 Abs 17-34 Acos 17-38 Acosh 17-38 action button 13-1 action frames 11-8 action template 11-7 structure of 11-10 ADD, native format commands 16-83 Add 7-34 AddArraySlot 17-26 AddDeferredAction 17-59 AddDelayedAction 17-61 AddIndex 7-35 adding assistance to your application 11-30 adding views dynamically 2-54 AddLocale 15-25 AddPowerOffHandler 17-70 AddStepView 2-57, 2-60, 2-62 AddToDefaultStore 7-37 AddToUserDictionary 6-24 AddUndoAction 12-51 AddWithUniqueId 7-37 AddWordToDictionary 6-26 ADSP protocol errors A-12 AEP protocol errors A-9 alphaKeyboard 2-100 animating a view 2-34 animation effect methods Delete 2-80 Effect 2-73 RevealEffect 2-77 SlideEffect 2-75 Annuity 17-54 appearance of view 2-28 AppleTalk ADSP endpoint 14-16 AppleTalk errors A-7 Application 16-3 application, testing whether open 2-46 application base view 2-5, GL-1 application browser, application 16-3 application components, overview 1-15 application errors A-2 Apply 17-59 ApplyCommand, Connection function 16-47 ApplyCommands 16-47 Array 17-27 array GL-1 array functions and methods 17-26 AddArraySlot 17-26 Array 17-27 ArrayMunger 17-27 ArrayPos 17-28 ArrayRemoveCount 17-29 Length 17-29 SetAdd 17-30 SetContains 17-30 SetDifference 17-31 SetLength 17-31 SetOverlaps 17-32 SetRemove 17-32 SetUnion 17-33 Sort 17-33 ArrayMunger 17-27 ArrayPos 17-28 ArrayRemoveCount 17-29 ArrayToPoints 4-19 Asin 17-38

IN-1

INDEX

Asinh 17-38 assistant architectural overview 11-7 intelligent 11-1 overview 1-9 programmer's guide to 11-7 assistant functions and methods, postparse 11-23 Atan 17-38 Atan2 17-39 Atanh 17-39 ATP protocol errors A-10 attribute, Connection terminology 16-2 AttributeFunctions 16-54 meta data items 16-54

GlobalBox 2-71 LocalBox 2-71 PictBounds 2-72 RelBounds 2-70 SetBounds 2-71 BroadcastSoupChange 7-38 browser, data 16-4 BrowserExport 16-19 Connection Function 16-19 BuildContext 2-58 built-in keyboards 2-100 ButtonBounds 2-72 Bxor 17-26

B
bad type errors A-16 Band 17-26 base view 2-5, GL-1 BatteryLevel 17-71 BeginsWith 17-10 behavior of view 2-13 BinaryMunger 17-71 binary object GL-1 bitwise functions and methods 17-25 Band 17-26 Bnot 17-26 Bor 17-26 Bxor 17-26 Bnot 17-26 Book Maker, overview 1-13 Book Reader, overview 1-12 Boolean GL-1 Bor 17-26 bounds nding and setting 2-70 screen-relative 2-18 bounds functions and methods ButtonBounds 2-72

C
Capitalize 17-10 CapitalizeWords 17-11 card store errors A-6 Ceiling 17-35 CheckWriteProtect 7-10 child GL-1 child template 2-2, 2-3 ChildViewFrames 2-46 child views, laying out 2-96 Chr 17-72 class GL-2 view 2-11, GL-6 ClassOf 17-2 clEditView 4-3 clGaugeView 4-28 clipping of view 2-18 clKeyboardView 4-21 clMonthView 4-31 Clone 7-49, 17-3 Close function 2-49 closing a connection 14-32 closing a view 2-45 clOutline 4-34 clParagraphView 4-6

IN-2

INDEX

clPictureView 4-19 clPolygonView 4-16 clRemoteView 4-33 clView 4-1 Column0Width 16-31 meta data items 16-31 CommandFrames, Connection 16-48 commands, native format 16-82 common system errors A-2 communications 14-1 overview 1-10 communications errors A-7 to A-14 communications functions and methods Abort 14-33, 14-41 connect 14-19, 14-40 disconnect 14-33, 14-41 dispose 14-34, 14-41 ExceptionHandler 14-32, 14-41 FlushInput 14-26, 14-41 FlushOutput 14-22, 14-40 FlushPartial 14-27, 14-41 GetOptions 14-30, 14-41 Input 14-25, 14-41 instantiate 14-18, 14-40 options 14-20, 14-40 Output 14-20, 14-40 OutputFrame 14-22, 14-40 PartialScript 14-26 release 14-34, 14-41 SetInputSpec 14-25, 14-41 SetOptions 14-30, 14-41 State 14-29, 14-41 communications tool errors A-12 CompareScripts 16-32 meta data items 16-32 Compile 17-72 Compound 17-55 Conrm 2-66 Connect 14-19, 14-40 Connection 16-1 application browser 16-3 CommandFrames 16-48

data browser 16-16 detail window 16-4, 16-16 ow of control 16-16 meta data 16-2 meta data format 16-7 soup data 16-2 soup indexes 16-92 warnings 16-84 connection closing 14-32 establishing 14-18 soup 16-13 Connection function ApplyCommand 16-47 BrowserExport 16-19 data validation functions 16-69 DockerFlowParagraph 16-65 editExport 16-20 EditImport 16-21 EntryValidation 16-46 Export 16-23 ExportFilter 16-43 GetFolderName 16-66 GetStoresLocale 16-67 Import 16-24 NativeExport 16-39 NativeImport 16-40 StringToParagraphArray 16-67 TabExport 16-36 TabImport 16-37 ValidateNotes 16-73 ValidateSlots 16-69 VerifyParagraph 16-75 VerifyParagraphArray 16-76 VerifyParagraphScript 16-76 Connection terminology attribute 16-2 frame 16-81 item 16-2 label 16-82 constant GL-2 container protos 3-3

IN-3

INDEX

controlling recognition in views 6-2 control protos 3-29 coordinate system 2-7 CopyBits 9-14 CopyEntries 7-38 copy protecting a view 4-8 copyProtection slot 4-8 CopySign 17-39 Cos 17-39 Cosh 17-40 CreateSoup 7-10 creating a state machine 14-27 creating a view 2-43 creating custom proto templates 3-93 CurrentException 17-57 cursor 7-4, GL-2 cursor functions and methods 7-47 Clone 7-49 Entry 7-50, 7-58 Goto 7-50 GotoKey 7-51 MapCursor 7-53 Move 7-53 Next 7-54 Prev 7-54 Query 7-54 Reset 7-58 Custom 2-32

D
Data 16-4, 16-16 data meta 16-2 receiving 14-22 sending 14-20 data browser 16-4 Connection 16-16 data extraction functions and methods 17-62 ExtractByte 17-63

ExtractBytes 17-63 ExtractChar 17-63 ExtractLong 17-64 ExtractPString 17-65 ExtractUniChar 17-66 ExtractWord 17-65 ExtractXLong 17-64 Data Storage 7-1 data storage system, overview 1-6 data stufng functions and methods 17-66 StuffByte 17-67 StuffChar 17-67 StuffLong 17-68 StuffUniChar 17-69 StuffWord 17-70 data validation functions, Connection function 16-69 Date 15-25 date functions and methods 17-26 dateKeyboard 2-100 DateNTime 15-26 Dates soups 8-5 DDP protocol errors A-8 debugging meta data 16-77 declareSelf slot 2-39 declaring a template GL-2 declaring a view 2-42 DeepClone 17-3 DefaultDenitions 16-55 meta data items 16-55 dening, instantiating an endpoint 14-18 Delete 2-80 delete, native format commands 16-83 DeleteWordFromDictionary 6-24 dependent views 2-91 detail window 16-4, 16-5 Connection 16-16 Dial 10-14 dialog view, creating 2-66 dictionary functions AddToUserDictionary 6-24 AddWordToDictionary 6-26

IN-4

INDEX

dictionary functions (continued) DeleteWordFromDictionary 6-24 DisposeDictionary 6-25 GetDictionaryData 6-26 GetRandomWord 6-23 LookupWordInDictionary 6-24 NewDictionary 6-25 SaveUserDictionary 6-25 SetDictionaryData 6-26 Dirty 2-52 dirtying views 2-47 Disconnect 14-33, 14-41 DisplayInfo 16-26 meta data items 16-26 displaying views 2-47 dispose 14-34, 14-41 DisposeDictionary 6-25 DockerFlowParagraph, Connection function 16-65 DoDrawing 9-13 DontCreateSoups 16-51 meta data items 16-51 DoPopup 2-63 Downcase 17-11 Drag 2-81 drawing 9-1 drawing functions and methods CopyBits 9-14 DoDrawing 9-13 DrawShape 9-10 DrawXBitmap 9-15 LockScreen 9-17 MakeLine 9-4 MakeOval 9-5 MakePict 9-8 MakePolygon 9-6 MakeRect 9-4 MakeRegion 9-7 MakeRoundRect 9-5 MakeShape 9-7 MakeText 9-9 MakeWedge 9-6

OffsetShape 9-12 ScaleShape 9-12 ShapeBounds 9-13 drawing-related messages 5-7 drawing views 2-106 DrawShape 9-10 DrawXBitmap 9-15 dynamically adding views 2-54

E
EditExport 16-20 Connection function 16-20 EditImport 16-21 Connection function 16-21 EditInfo 16-29 meta data items 16-29 EditTypes 16-57 meta data items 16-57 EditWith 16-54 meta data items 16-54 Effect 2-73 endpoint AppleTalk ADSP 14-16 IR 14-15 modem 14-9 serial 14-3, 14-4, 14-13 endpoint functions and methods 14-34 endpoints, dening, instantiating 14-18 EndsWith 17-11 EnsureInternal 17-4 entries 7-3 Entry 7-50 entry GL-2 EntryChange 7-61 EntryChangeWithModTime 7-62 EntryCopy 7-62 Entry Functions 7-58 Entry functions 7-58

IN-5

INDEX

entry functions and methods EntryChange 7-61 EntryChangeWithModTime 7-62 EntryCopy 7-62 EntryModTime 7-62 EntryMove 7-62 EntryRemoveFromSoup 7-62 EntryReplace 7-63 EntryReplaceWithModTime 7-63 EntrySize 7-63 EntrySoup 7-63 EntryStore 7-64 EntryTextSize 7-64 EntryUndoChanges 7-64 EntryUnique 7-64 FrameDirty 7-64 EntryModTime 7-62 EntryMove 7-62 EntryRemoveFromSoup 7-62 EntryReplace 7-63 EntryReplaceWithModTime 7-63 EntrySize 7-63 EntrySoup 7-63 EntryStore 7-64 EntryTextSize 7-64 EntryUndoChanges 7-64 EntryUniqueId 7-64 EntryValidation, Connection function 16-46 enumerated dictionary GL-2 Erase 7-12 Erf 17-40 Erfc 17-40 error codes A-1 to A-18 error messages, meta data validation 16-78 errors ADSP protocol A-12 AEP protocol A-9 AppleTalk A-7 application A-2 ATP protocol A-10 bad type A-16 card store A-6

common system A-2 communications A-7 to A-14 communications tool A-12 DDP protocol A-8 FAX A-12 ash card A-5 hardware A-4 to A-6 interpreter A-17 LAP protocol A-8 modem A-13 NBP protocol A-9 NewtonScript A-15 to A-17 object system A-16 online service A-14 package A-3 PAP protocol A-11 PCMCIA card A-4 printing A-14 RTMP protocol A-10 serial tool A-12 Sharp IR A-13 soup A-15 store A-15 system A-2 to A-3 ZIP protocol A-11 establishing a connection 14-18 EvalStringer 17-11 evaluate slot GL-2 exception functions CurrentException 17-57 Rethrow 17-57 Throw 17-56 ExceptionHandler 14-32, 14-41 exceptions handling 14-32 raised by Newton system software A-1 Exp 17-40 Expm1 17-41 Export 16-23 Connection function 16-23 ExportFilter, Connection function 16-43

IN-6

INDEX

ExportInfo 16-34 meta data items 16-34 extending the intelligent assistant 11-1 ExtractByte 17-63 ExtractBytes 17-63 ExtractChar 17-63 ExtractLong 17-64 ExtractPString 17-65 ExtractUniChar 17-66 ExtractWord 17-65 ExtractXLong 17-64

F
Fabs 17-41 FAX errors A-12 FDim 17-41 FeClearExcept 17-51 FeGetEnv 17-52 FeGetExcept 17-52 FeHoldExcept 17-52 FeRaiseExcept 17-52 FeSetEnv 17-53 FeSetExcept 17-53 FeTestExcept 17-53 FeUpdateEnv 17-54 eld GL-2 le, synch 16-2 ling 12-37 ll color 2-30 nancial functions and methods 17-54 Annuity 17-54 Compound 17-55 Find 12-1 Find function 12-7 FindLocale 15-26 FindStringInArray 17-12 FindStringInFrame 17-12 ag GL-2

ags vApplication 2-14 vCalculateBounds 2-14 vClickable 2-15 vClipping 2-14 vFloating 2-14 vNoFlags 2-15 vNoScripts 2-15 vReadOnly 2-14 vVisible 2-14 vWriteProtected 2-15 ash card errors A-5 oating point math functions 17-37 oating point math functions and methods Abs 17-34 Acos 17-38 Acosh 17-38, 17-40 Asin 17-38 Asinh 17-38 Atan 17-38 Atan2 17-39 Atanh 17-39 CopySign 17-39 Cos 17-39 Cosh 17-40 Erfc 17-40 Exp 17-40 Expm1 17-41 Fabs 17-41 FDim 17-41 FeClearExcept 17-51 FeGetEnv 17-52 FeGetExcept 17-52 FeHoldExcept 17-52 FeRaiseExcept 17-52 FeSetEnv 17-53 FeSetExcept 17-53 FeTestExcept 17-53 FeUpdateEnv 17-54 FMax 17-41 FMin 17-42 Fmod 17-40

IN-7

INDEX

oating point math functions and methods (continued) Gamma 17-42 Hypot 17-42 IsFinite 17-43 IsNan 17-43 IsNormal 17-43 LessEqualOrGreater 17-43 LessOrGreater 17-44 LGamma 17-44 Log 17-44 Log10 17-45 Log1p 17-45 Logb 17-44 NearbyInt 17-45 NextAfterD 17-45 Pow 17-46 RandomX 17-46 Remainder 17-46 RemQuo 17-46 Rint 17-47 RintToL 17-47 Round 17-47 Scalb 17-47 Sign 17-48 SignBit 17-48 Sin 17-48 Sinh 17-48 Sqrt 17-48 Tan 17-49 Tanh 17-49 Trunc 17-49 Unordered 17-49 UnorderedGreaterOrEqual 17-49 UnorderedLessOrEqual 17-50 UnorderedOrEqual 17-50 UnorderedOrGreater 17-50 UnorderedOrLess 17-51 Floor 17-35 ow of control, Connection 16-16 Flush 7-39 FlushInput 14-26, 14-41

FlushOutput 14-22, 14-40 FlushPartial 14-27, 14-41 FMax 17-41 FMin 17-42 Fmod 17-40 font, specifying for a view 2-39, 4-11 FontAscent 17-25 FontDescent 17-25 font functions and methods 17-25 FontAscent 17-25 FontDescent 17-25 FontHeight 17-25 FontLeading 17-25 FontHeight 17-25 FontLeading 17-25 format meta data 16-7 native 16-81 Newton text 16-81 FormattedNumberStr 15-27, 17-14 frame 2-2, 7-2, GL-2 color 2-30 Connection terminology, 16-81 inset 2-31 roundedness 2-31 shadow 2-31 thickness 2-31 FrameDirty 7-64 frame functions 17-2 frame functions and methods ClassOf 17-2 Clone 17-3 DeepClone 17-3 EnsureInternal 17-4 GetSlot 17-4 GetVariable 17-4 HasSlot 17-5 HasVariable 17-6 PrimClassOf 17-8 RemoveSlot 17-8 ReplaceObject 17-8 SetClass 17-9 TotalClone 17-10

IN-8

INDEX

function object GL-3 functions and methods 15-26, 17-18 Abort 14-33, 14-41 Abs 17-34 Acos 17-38 Acosh 17-38, 17-40 Add 7-34 AddArraySlot 17-26 AddDeferredAction 17-59 AddDelayedAction 17-61 AddIndex 7-35 AddLocale 15-25 AddPowerOffHandler 17-70 AddStepView 2-57, 2-60, 2-62 AddToDefaultStore 7-37 AddToUserDictionary 6-24 AddUndoAction 12-51 AddWithUnique 7-37 AddWordToDictionary 6-26 Annuity 17-54 Apply 17-59 Array 17-27 ArrayMunger 17-27 ArrayPos 17-28 ArrayRemoveCount 17-29 ArrayToPoints 4-19 Asin 17-38 Asinh 17-38 Atan 17-38 Atan2 17-39 Atanh 17-39 Band 17-26 BatteryLevel 17-71 BeginsWith 17-10 BinaryMunger 17-71 Bnot 17-26 Bor 17-26 BroadcastSoupChange 7-38 BuildContext 2-58 ButtonBounds 2-72 Bxor 17-26 Capitalize 17-10

CapitalizeWords 17-11 Ceiling 17-35 CheckWriteProtect 7-10 ChildViewFrames 2-46 Chr 17-72 ClassOf 17-2 Clone 7-49, 17-3 Close 2-49 Compile 17-72 Compound 17-55 Conrm 2-66 connect 14-19, 14-40 CopyBits 9-14 CopyEntries 7-38 CopySign 17-39 Cos 17-39 Cosh 17-40 CreateSoup 7-10 CurrentException 17-57 Date 15-25 DeepClone 17-3 DeleteWordFromDictionary 6-24 Dial 10-14 Dirty 2-52 disconnect 14-33, 14-41 dispose 14-34, 14-41 DisposeDictionary 6-25 DoDrawing 9-13 DoPopup 2-63 Downcase 17-11 Drag 2-81 DrawShape 9-10 DrawXBitmap 9-15 EndsWith 17-11 EnsureInternal 17-4 Entry 7-50, 7-58 EntryChange 7-61 EntryChangeWithModTime 7-62 EntryCopy 7-62 EntryModTime 7-62 EntryMove 7-62 EntryRemoveFromSoup 7-62

IN-9

INDEX

functions and methods (continued) EntryReplace 7-63 EntryReplaceWithModTime 7-63 EntrySize 7-63 EntrySoup 7-63 EntryStore 7-64 EntryTextSize 7-64 EntryUndoChanges 7-64 EntryUnique 7-64 Erase 7-12 Erfc 17-40 EvalStringer 17-11 ExceptionHandler 14-32, 14-41 Exp 17-40 Expm1 17-41 ExtractByte 17-63 ExtractBytes 17-63 ExtractChar 17-63 ExtractLong 17-64 ExtractPString 17-65 ExtractUniChar 17-66 ExtractWord 17-65 ExtractXLong 17-64 Fabs 17-41 FDim 17-41 FeClearExcept 17-51 FeGetEnv 17-52 FeGetExcept 17-52 FeHoldExcept 17-52 FeRaiseExcept 17-52 FeSetEnv 17-53 FeSetExcept 17-53 FeTestExcept 17-53 FeUpdateEnv 17-54 Find 12-7 FindLocale 15-26 FindStringInArray 17-12 FindStringInFrame 17-12 Floor 17-35 Flush 7-39 FlushInput 14-26, 14-41 FlushOutput 14-22, 14-40

FlushPartial 14-27, 14-41 FMax 17-41 FMin 17-42 Fmod 17-40 FontAscent 17-25 FontDescent 17-25 FontHeight 17-25 FontLeading 17-25 FormattedNumberStr 15-27, 17-14 FrameDirty 7-64 Gamma 17-42 GetAllInfo 7-12, 7-39 GetAppParams 17-74 GetCaretBox 2-102 GetDateStringSpec 15-28 GetDefaultStore 7-65 GetDictionaryData 6-26 GetGlobals 17-74 GetHiliteOffsets 2-89 GetIndexes 7-40 GetInfo 7-12, 7-40 GetKind 7-13 GetLanguageEnvironment 15-29 GetLocale 15-29 GetName 7-13, 7-40 GetNextUid 7-41 GetOptions 14-30, 14-41 GetPackages 7-14 GetPoint 6-19 GetPointsArray 6-21 GetRandomWord 6-23 GetRoot 2-46 GetScoreArray 6-22 GetSignature 7-14, 7-41 GetSlot 17-4 GetSoup 7-14 GetSoupNames 7-15 GetStore 7-41 GetStores 7-15 GetUnionSoup 7-42 GetVariable 17-4 GetView 2-47

IN-10

INDEX

functions and methods (continued) GetViewFlags 2-104 GetVolume 10-11 GetWordArray 6-21 GlobalBox 2-71 Goto 7-50 GotoKey 7-51 HasSlot 17-5 HasSoup 7-16 HasVariable 17-6 Hide 2-51 Hilite 2-88 HiliteOwner 2-89 HiliteUnique 2-88 HitShape 6-22 HourMinute 15-30 Hypot 17-42 IndexSizes 7-42 InkOff 6-18 Input 14-25, 14-41 instantiate 14-18, 14-40 Intern 17-6, 17-7, 17-20 IsAlphaNumeric 17-15 IsArray 17-6 IsBinary 17-7 IsFinite 17-43 IsFrame 17-7 IsImmediate 17-7 IsInstance 17-7 IsNan 17-43 IsNormal 17-43 IsReadOnly 7-16 IsSoupEntry 7-42 IsWhiteSpace 17-15 KeyboardInput 2-102 KeyIn 2-103 LayoutColumn 2-100 LayoutTable 2-96 Length 17-29 LessEqualOrGreater 17-43 LessOrGreater 17-44 LGamma 17-44

LocalBox 2-71 LockScreen 9-17 Log 17-44 Log10 17-45 Log1p 17-45 Logb 17-44 LongDateStr 15-30 LookupWordInDictionary 6-24 MakeLine 9-4 MakeOval 9-5 MakePict 9-8 MakePolygon 9-6 MakeRect 9-4 MakeRegion 9-7 MakeRoundRect 9-5 MakeShape 9-7 MakeText 9-9 MakeWedge 9-6 Map 17-7 MapCursor 7-53 Max 17-35 Min 17-35 ModalDialog 2-68 Move 7-53 MungePhone 17-75 NearbyInt 17-45 NewDictionary 6-25 Next 7-54 NextAfterD 17-45 Notify 12-53 NumberStr 17-15 OffsetShape 9-12 Open 2-48 options 14-20, 14-40 Ord 17-76 Output 14-20, 14-40 OutputFrame 14-22, 14-40 ParamStr 17-16 Parent 2-46 PartialScript 14-26 Perform 17-58 PictBounds 2-72

IN-11

INDEX

functions and methods (continued) PlaySound 10-12 PlaySoundSync 10-12 PointsToArray 4-18 PostKeyString 2-103 postparse 11-23 Pow 17-46 Prev 7-54 PrimClassOf 17-8 PtInPicture 6-23 Query 7-54 Random 17-36 RandomX 17-46 Real 17-35 RedoChildren 2-93 RefreshViews 2-53 RegisterCardSoup 7-42 RelBounds 2-70 release 14-34, 14-41 Remainder 17-46 RemoveAllEntries 7-44 RemoveFromStore 7-44 RemoveIndex 7-44 RemoveLocale 15-30 RemovePackage 7-16 RemovePowerOffHandler 17-71 RemoveSlot 17-8 RemQuo 17-46 ReplaceObject 17-8 Reset 7-58 RestorePackage 7-17 Rethrow 17-57 Rint 17-47 RintToL 17-47 Round 17-47 SaveUserDictionary 6-25 Scalb 17-47 ScaleShape 9-12 SetAdd 12-32, 17-30 SetAllInfo 7-17, 7-45 SetBounds 2-71 SetClass 17-9

SetContains 17-30 SetDefaultStore 7-66 SetDictionaryData 6-26 SetDifference 17-31 SetExtrasInfo 17-77 SetHilite 2-90 SetInfo 7-17, 7-45 SetInkerPenSize 6-18 SetInputSpec 14-25, 14-41 SetKeyView 2-102 SetLength 17-31 SetLocale 15-30 SetLocation 15-31 SetName 7-18, 7-46 SetOptions 14-30, 14-41 SetOrigin 2-83 SetOverlaps 17-32 SetPopup 2-104 SetRandomSeed 17-36 SetRemove 17-32 SetSignature 7-19, 7-46 SetTime 15-31 SetUnion 17-33 SetValue 2-53 SetVolume 10-13 ShortDate 15-31 ShortDateStr 15-31 Show 2-51 ShowFoundItem 12-27 Sign 17-48 SignBit 17-48 Sin 17-48 Sinh 17-48 Sleep 17-78 SmartConcat 17-17 SmartStop 17-18 Sort 17-33 Sqrt 17-48 State 14-29, 14-41 StrCompare 17-19 StrConcat 17-19 StrEqual 17-19

IN-12

INDEX

functions and methods (continued) StrFontWidth 17-20 Stringer 17-20 StringFilter 17-20 StringToDate 15-32 StringToNumber 17-21 StringToTime 15-32 StrLen 17-22 StrMunger 17-22 StrokeBounds 6-20 StrokeDone 6-20 StrPos 17-23 StrReplace 17-23 StrTruncate 17-24 StrWidth 17-24 StuffByte 17-67 StuffChar 17-67 StuffLong 17-68 StuffUniChar 17-69 StuffWord 17-70 SubStr 17-23 SyncChildren 2-95 SyncScroll 2-85 SyncView 2-54 Tan 17-49 Tanh 17-49 Throw 17-56 Ticks 15-33 TieViews 2-91 Time 15-33 TimeInSeconds 15-33 TimeStr 15-33 Toggle 2-50 TotalClone 17-10 TotalMinutes 15-34 TotalSize 7-19 TrackButton 2-89 TrackHilite 2-88 TrimString 17-24 Trunc 17-49 UnionSoupIsNull 7-67 Unordered 17-49

UnorderedGreaterOrEqual 17-49 UnorderedLessOrEqual 17-50 UnorderedOrEqual 17-50 UnorderedOrGreater 17-50 UnorderedOrLess 17-51 UnRegisterCardSoup 7-46 Upcase 17-24 UsedSize 7-20 Visible 2-105

G
Gamma 17-42 gesture GL-3 GetAllInfo 7-12, 7-39 GetAppParams 17-74 GetCaretBox 2-102 GetDateStringSpec 15-28 GetDefaultStore 7-65 GetDictionaryData 6-26 GetFolderName, Connection function 16-66 GetGlobals 17-74 GetHiliteOffsets 2-89 GetIndexes 7-40 GetInfo 7-12, 7-40 GetKind 7-13 GetLanguageEnvironment 15-29 GetLocale 15-29 GetName 7-13, 7-40 GetNextUid 7-41 GetOptions 14-30, 14-41 GetPackages 7-14 GetPoint 6-19 GetPointsArray 6-21 GetRandomWord 6-23 GetRoot 2-46 GetScoreArray 6-22 GetSignature 7-14, 7-41 GetSlot 17-4 GetSoup 7-14

IN-13

INDEX

GetSoupNames 7-15 GetStore 7-41 GetStores 7-15 GetStoresLocale, Connection function 16-67 GetUnionSoup 7-42 GetVariable 17-4 GetView 2-47 GetViewFlags 2-104 GetVolume 10-11 GetWordArray 6-21 global GL-3 GlobalBox 2-71 global data 8-20 global data le GL-3 glossary GL-1 Goto 7-50 GotoKey 7-51 grammer GL-3

HourMinute 15-30 Hypot 17-42

I, J
IA (see intelligent assistant) 11-4 idling 12-54 imaging system, overview 1-11 immediate value GL-3 implementor GL-3 Import 16-24 Connection function 16-24 import les, soup indexes 16-92 in box 13-4 indexes, soup 16-92 IndexSizes 7-42 inheritance GL-3 inheritance links _parent slot 2-40 _proto slot 2-40 stepChildren slot 2-40 viewChildren slot 2-40 initialization and termination messages 5-2 InkOff 6-18 Input 14-25, 14-41 input protos 3-10 input-related messages 5-12 instantiate 14-18, 14-40, GL-3 instantiation, view 2-41, 5-2 intelligent assistance vs. online help 11-2 intelligent assistant 11-1 action frames 11-8 action template 11-7 adding to your application 11-30 lexicon 11-8 overview 1-9 preconditions 11-9 primary action 11-7 signature 11-9 target frames 11-8

H
handling exceptions 14-32 hardware errors A-4 to A-6 HasSlot 17-5 HasSoup 7-16 HasVariable 17-6 heap, NewtonScript 1-4 help, vs intelligent assistant 11-2 hidden view, showing 2-55 Hide 2-51 hidesound 10-3 hiding views 2-47 Highlighting 2-87 Hilite 2-88 HiliteOwner 2-89 HiliteUnique 2-88 HitShape 6-22 hit testing functions HitShape 6-22 PtInPicture 6-23

IN-14

INDEX

intelligent assistant (continued) target template 11-7 task template 11-7 Intern 17-6, 17-7, 17-20 international currency settings 17-55 interpreter errors A-17 IR endpoint 14-15 IsAlphaNumeric 17-15 IsArray 17-6 IsBinary 17-7 IsFinite 17-43 IsFrame 17-7 IsImmediate 17-7 IsInstance 17-7 IsNan 17-43 IsNormal 17-43 IsReadOnly 7-16 IsSoupEntry 7-42 IsWhiteSpace 17-15 item, Connection terminology, 16-2 items meta data 16-9 meta data format 16-7 see meta data items 16-13

L
label, Connection terminology, 16-82 LAP protocol errors A-8 laying out multiple child views 2-96 LayoutColumn 2-100 LayoutTable 2-96 layout view GL-3 Length 17-29 LessEqualOrGreater 17-43 LessOrGreater 17-44 lexical denitions, native form 16-90 lexical dictionary GL-4 lexicon 11-8 LGamma 17-44 lines, in views 2-31 LocalBox 2-71 locale functions and methods AddLocale 15-25 FindLocale 15-26 RemoveLocale 15-30 local variable GL-4 LockScreen 9-17 Log 17-44 Log10 17-45 Log1p 17-45 Logb 17-44 LongDateStr 15-30 LookupWordInDictionary 6-24

K
KeyboardInput 2-102 keyboard key codes 4-27 keyboard proto 3-75 keyboard views built-in types 2-100 working with 2-100, 4-21 KeyIn 2-103 keypad proto 3-76 keyPressScript 3-76, 4-22

M
magic pointer 1-17, GL-4 MakeLine 9-4 MakeOval 9-5 MakePict 9-8 MakePolygon 9-6 MakeRect 9-4 MakeRegion 9-7 MakeRoundRect 9-5

IN-15

INDEX

MakeShape 9-7 MakeText 9-9 MakeWedge 9-6 Map 17-7 MapCursor 7-53 math functions, oating point 17-37 math functions and methods 17-34. See also nancial functions Annuity 17-54 Ceiling 17-35 Compound 17-55 Floor 17-35 Max 17-35 Min 17-35 Random 17-36 Real 17-35 SetRandomSeed 17-36 Max 17-35 meeting frames 8-6 memory system overview 1-4 usage by views 2-107 message GL-4 messages drawing related 5-7 input-related 5-12 intialization and termination 5-2 other 5-19 scrolling and overview 5-10 message sending functions 17-58 message sending functions and methods AddDeferredAction 17-59 AddDelayedAction 17-61 Perform 17-58 Meta 16-7 meta 16-2, 16-7 meta data 16-2 debugging 16-77 format 16-7 meta data format 16-7 meta data frames, writing 16-61

meta data items 16-9 AttributeFunctions 16-54 Column0Width 16-31 ComprareScripts 16-32 meta data items 16-32 DefaultDenitions 16-55 dependents, meta data items 16-53 DisplayInfo 16-26 DontCreateSoups 16-51 EditInfo 16-29 EditTypes 16-57 EditWith 16-54 Name 16-14 NativeExportExceptions 16-42 NewEntry 16-14 soup 16-13 SoupIndicies 16-51 SoupInfo 16-51 version 16-14 meta data scripts, NewtonScript function 16-61 meta data validation error messages 16-78 method 2-2, GL-4 Min 17-35 miscellaneous functions and methods 17-71 Apply 17-59 BinaryMunger 17-71 Chr 17-72 Compile 17-72 FindStringInFrame 17-12 GetAppParams 17-74 GetGlobals 17-74 Intern 17-6, 17-7, 17-20 IsArray 17-6 IsBinary 17-7 IsFrame 17-7 IsImmediate 17-7 IsInstance 17-7 IsWhiteSpace 17-15 Map 17-7 MungePhone 17-75 Ord 17-76 SetExtrasInfo 17-77

IN-16

INDEX

miscellaneous functions and methods (continued) Sleep 17-78 StringFilter 17-20 SysBeep 17-79 miscellaneous protos 3-70 ModalDialog 2-68 modal views 2-66 modem endpoint 14-9 modem errors A-13 modify, native format commands 16-84 Move 7-53 Multi 16-52 multi-soup applications 16-52 MungePhone 17-75

NewtonScript 1-18, 16-61 meta data scripts in 16-61 NewtonScript errors A-15 to A-17 NewtonScript heap 1-4 Newton text format 16-81 Next 7-54 NextAfterD 17-45 Notes soup 8-2 notication 12-52 Notify 12-53 ntryValidation 16-46 NumberStr 17-15 numericKeyboard 2-100

N
Name 16-14 meta data items 16-14 Names soup 8-3 NativeExport 16-39 Connection function 16-39 NativeExportExceptions 16-42 meta data items 16-42 native format 16-81 commands 16-82 native format commands 16-84 ADD 16-83 delete 16-83 modify 16-84 replace 16-84 native format lexical denitions 16-90 native format syntax 16-88 NativeImport, Connection function 16-40 NBP protocol errors A-9 NearbyInt 17-45 NewDictionary 6-25 NewEntry, meta data items 16-14 Newton 16-1 Newton Connection. See Connection

O
object GL-4 object storage system, overview 1-6 object system errors A-16 OffsetShape 9-12 ommand 16-48 online service errors A-14 Open 2-48 operating system, overview 1-3 options, setting 14-20, 14-40 Ord 17-76 origin GL-4 out box 13-4 Output 14-20, 14-40 OutputFrame 14-22, 14-40

P
package 1-5, GL-4 package errors A-3 package functions and methods GetPackages 7-14 RemovePackage 7-16

IN-17

INDEX

PAP protocol errors A-11 ParamStr 17-16 parent 2-2, GL-4 Parent function 2-46 parent slot 2-5, 2-40 parent template 2-2, 2-3 parsing example 11-24 part GL-4 PartialScript 14-26 PCMCIA GL-4 PCMCIA card errors A-4 Perform 17-58 performance optimization 2-105 persistent storage 1-4 phoneKeyboard 2-100 picker GL-5 PictBounds 2-72 pixel 2-8 PlaySound 10-12 PlaySoundSync 10-12 PointsToArray 4-18 pop-up views 2-59 PostKeyString 2-103 postparse 11-23 Pow 17-46 power handler functions and methods 17-70 AddPowerOffHandler 17-70 RemovePowerOffHandler 17-71 powerOffScript 5-19 pplyCommands 16-47 preconditions 11-9 preferences creating for an application 8-19 system soup 8-11 Prev 7-54 primary action 11-7 PrimClassOf 17-8 printing, overview 1-11 printing errors A-14 printNextPageScript 5-20 programmer's guide to the assistant 11-7 project GL-5

project data le GL-5 project le GL-5 proto 2-5, GL-5 protoActionButton 3-29 protoApp 3-3 protoBorder 3-70 protoCheckbox 3-30 protoCloseBox 3-32 protoDateExpando 3-10 protoDivider 3-70 protoDrawer 3-5 protoExpandoShell 3-12 protoFilingButton 3-34 protoFloater 3-6 protoFloatNGo 3-8 protoFolderTab 3-35 protoGauge 3-72 protoGlance 3-73 protoInputLine 3-17 protoKeyboard 3-75 protoKeypad 3-76 protoLabeledBatteryGauge 3-77 protoLabelInputLine 3-19 protoLabelPicker 3-36 protoLargeCloseBox 3-39 protoPhoneExpando 3-23 protoPicker 3-40 protoPictIndexer 3-46 protoPictRadioButton 3-48 protoPictureButton 3-50 protoPrintFormat 3-78 protoRadioButton 3-51 protoRadioCluster 3-53 protoRCheckbox 3-55 protoRecToggle 3-57 protoRoll 3-62 protoRollBrowser 3-66 protoRollItem 3-68 protos 3-1 protoSetClock 3-79 protoSlider 3-58 proto slot 2-5, 2-40

IN-18

INDEX

protoStaticText 3-81 protoStatus 3-82 protoStatusBar 3-83 protoTable 3-84 proto templates container protos 3-3 control protos 3-29 custom 3-93 input protos 3-10 miscellaneous protos 3-70 protoActionButton 3-29 protoApp 3-3 protoBorder 3-70 protoCheckbox 3-30 protoCloseBox 3-32 protoDateExpando 3-10 protoDivider 3-70 protoDrawer 3-5 protoExpandoShell 3-12 protoFilingButton 3-34 protoFloater 3-6 protoFloatNGo 3-8 protoFolderTab 3-35 protoGauge 3-72 protoGlance 3-73 protoInputLine 3-17 protoKeyboard 3-75 protoKeypad 3-76 protoLabeledBatteryGauge 3-77 protoLabelInputLine 3-19 protoLabelPicker 3-36 protoLargeCloseBox 3-39 protoPhoneExpando 3-23 protoPicker 3-40 protoPictIndexer 3-46 protoPictRadioButton 3-48 protoPictureButton 3-50 protoPrintFormat 3-78 protoRadioButton 3-51 protoRadioCluster 3-53 protoRCheckbox 3-55 protoRecToggle 3-57

protoRoll 3-62 protoRollBrowser 3-66 protoRollItem 3-68 protoSetClock 3-79 protoSlider 3-58 protoStaticText 3-81 protoStatus 3-82 protoStatusBar 3-83 protoTable 3-84 protoTextButton 3-60 protoTextExpando 3-26 protoTextList 3-90 protoTitle 3-92 roll protos 3-62 summary 3-95 protoTextButton 3-60 protoTextExpando 3-26 protoTextList 3-90 protoTitle 3-92 PtInPicture 6-23

Q
Query 7-54

R
Random 17-36 RandomX 17-46 Real 17-35 receiver GL-5 receiving data 14-22 recognition 6-1 recognition ags vAnythingAllowed 6-3 vCapsRequired 6-7 vClickable 6-3 vClickableAllowed 6-5

IN-19

INDEX

recognition ags (continued) vCustomDictionaries 6-6 vDateField 6-7 vlettersAllowed 6-6 vMathAllowed 6-6 vNameField 6-6 vNothingAllowed 6-3 vNumbersAllowed 6-7 vPhoneField 6-7 vPunctuationAllowed 6-6 vShapesAllowed 6-5 vSingleUnit 6-5 vStrokesAllowed 6-4 vTimeField 6-7 recognition functions 6-18 GetPoint 6-19 GetPointsArray 6-21 GetScoreArray 6-22 GetWordArray 6-21 InkOff 6-18 SetInkerPenSize 6-18 StrokeBounds 6-20 StrokeDone 6-20 recognition system, overview 1-8 RedoChildren 2-93 redrawing views 2-106 reference GL-5 RefreshViews 2-53 RegisterCardSoup 7-42 registering the task template 11-27 RelBounds 2-70 Release 14-34, 14-41 Remainder 17-46 RemoveAllEntries 7-44 RemoveFromStore 7-44 RemoveIndex 7-44 RemoveLocale 15-30 RemovePackage 7-16 RemovePowerOffHandler 17-71 RemoveSlot 17-8 RemoveView 2-61 RemQuo 17-46

replace 16-84 ReplaceObject 17-8 Reset 7-58 resource GL-5 RestorePackage 7-17 Rethrow 17-57 Retrieval 7-1 RevealEffect 2-77 Rint 17-47 RintToL 17-47 roll protos 3-62 root view 2-7, GL-5 Round 17-47 routing 13-1 action button 13-1 in box 13-4 out box 13-4 RTMP protocol errors A-10

S
SaveUserDictionary 6-25 Scalb 17-47 ScaleShape 9-12 scripts, meta data 16-61 scrolldownsound 10-3 scrolling, speeding up 2-108 scrolling and overview messages 5-10 scrollupsound 10-3 self GL-5 sending data 14-20 serial endpoint 14-3, 14-4, 14-13 serial tool errors A-12 SetAdd 17-30 SetAllInfo 7-17, 7-45 SetBounds 2-71 SetClass 17-9 SetContains 17-30 SetDefaultStore 7-66 SetDictionaryData 6-26

IN-20

INDEX

SetDifference 17-31 SetExtrasInfo 17-77 SetHilite 2-90 SetInfo 7-17, 7-45 SetInkerPenSize 6-18 SetInputSpec 14-25, 14-41 SetKeyView 2-102 SetLength 17-31 SetLocale 15-30 SetLocation 15-31 SetName 7-18, 7-46 SetOptions 14-30, 14-41 SetOrigin 2-83 SetOverlaps 17-32 SetPopup 2-104 SetRandomSeed 17-36 SetRemove 17-32 SetSignature 7-19, 7-46 SetTime 15-31 SetUnion 17-33 SetupIdle 12-54 SetValue 2-53 SetVolume 10-13 ShapeBounds 9-13 Sharp IR errors A-13 ShortDate 15-31 ShortDateStr 15-31 Show 2-51 ShowFoundItem Method 12-27 showing a hidden view 2-55 showsound 10-3 siblings GL-6 sibling views 2-20 Sign 17-48 signature 11-9 SignBit 17-48 Sin 17-48 Sinh 17-48 Sleep 17-78 SlideEffect 2-75 slot GL-6 global GL-3

SmartConcat 17-17 SmartStop 17-18 Sort 17-33 sound, overview 1-12 sound functions and methods Dial 10-14 GetVolume 10-11 PlaySound 10-12 PlaySoundSync 10-12 SetVolume 10-13 sound slots hidesound 10-3 scrolldownsound 10-3 scrollupsound 10-3 showsound 10-3 Soup 16-13 soup 7-1, 7-2, GL-6 connection use of 16-13 Dates 8-5 meta data item 16-13 multi-soup applications 16-52 Names 8-3 Notes 8-2 System 8-11 union soup 7-3 user preferences 8-11 soupChanged 5-21 soup data, Connection 16-2 soup functions and methods 7-20 Add 7-34 AddIndex 7-35 AddToDefaultStore 7-37 AddWithUnique 7-37 BroadcastSoupChange 7-38 CopyEntries 7-38 Flush 7-39 GetAllInfo 7-39 GetIndexes 7-40 GetInfo 7-40 GetName 7-40 GetNextUid 7-41 GetSignature 7-41

IN-21

INDEX

soup functions and methods (continued) GetStore 7-41 GetUnionSoup 7-42 IndexSizes 7-42 IsSoupEntry 7-42 RegisterCardSoup 7-42 RemoveAllEntries 7-44 RemoveFromStore 7-44 RemoveIndex 7-44 SetAllInfo 7-45 SetInfo 7-45 SetName 7-46 SetSignature 7-46 UnionSoupIsNull 7-67 UnRegisterCardSoup 7-46 soup indexes 16-92 SoupIndicies 16-51 meta data items 16-51 SoupInfo 16-51 meta data items 16-51 sour errors A-15 SPrintObject 17-18 Sqrt 17-48 State 14-29, 14-41 state machine 14-27 stepChildren array, adding to at run time 2-55 stepChildren slot 2-40 storage, persistent 1-4 storage system, overview 1-6 store 7-1, 7-3, 7-9, GL-6 store errors A-15 store functions and methods 7-9 CheckWriteProtect 7-10 CreateSoup 7-10 Erase 7-12 GetAllInfo 7-12 GetDefaultStore 7-65 GetInfo 7-12 GetKind 7-13 GetName 7-13 GetSignature 7-14 GetSoup 7-14

GetSoupNames 7-15 GetStores 7-15 HasSoup 7-16 IsReadOnly 7-16 RestorePackage 7-17 SetAllInfo 7-17 SetDefaultStore 7-66 SetInfo 7-17 SetName 7-18 SetSignature 7-19 TotalSize 7-19 UsedSize 7-20 StrCompare 17-19 StrConcat 17-19 StrEqual 17-19 StrFontWidth 17-20 Stringer 17-20 StringFilter 17-20 string functions 17-10 string functions and methods BeginsWith 17-10 Capitalize 17-10 CapitalizeWords 17-11 Downcase 17-11 EndsWith 17-11 EvalStringer 17-11 FindStringInArray 17-12 FormattedNumberStr 15-27, 17-14 IsAlphaNumeric 17-15 NumberStr 17-15 ParamStr 17-16 SmartConcat 17-17 SmartStop 17-18 SPrintObject 17-18 StrCompare 17-19 StrConcat 17-19 StrEqual 17-19 StrFontWidth 17-20 Stringer 17-20 StringToNumber 17-21 StrLen 17-22 StrMunger 17-22

IN-22

INDEX

string functions and methods (continued) StrPos 17-23 StrReplace 17-23 StrTruncate 17-24 StrWidth 17-24 SubStr 17-23 TrimString 17-24 Upcase 17-24 StringToDate 15-32 StringToNumber 17-21 StringToParagraphArray, Connection function 16-67 StringToTime 15-32 StrLen 17-22 StrMunger 17-22 StrokeBounds 6-20 StrokeDone 6-20 StrPos 17-23 StrReplace 17-23 StrTruncate 17-24 structure of the action template 11-10 structure of the task template 11-15 StrWidth 17-24 StuffByte 17-67 StuffChar 17-67 StuffLong 17-68 StuffUniChar 17-69 StuffWord 17-70 SubStr 17-23 SyncChildren 2-95 synch 16-2 synch le 16-2 synchronization, view 2-93 SyncScroll 2-85 SyncView 2-54 syntax, native format 16-88 SysBeep 17-79 system errors A-2 to A-3 system exceptions A-1 system messages 5-1 during view instantiation 5-2 powerOffScript 5-19

printNextPageScript 5-20 soupChanged 5-21 viewAddChildScript 5-21 viewChangedScript 5-22 viewClickScript 5-13 viewDrawScript 5-8 viewDropChildScript 5-23 viewGestureScript 5-15 viewHideScript 5-7 viewHiliteScript 5-9 viewIdleScript 5-23 viewOverviewScript 5-11 viewQuitScript 5-6 viewScrollDownScript 5-10 viewScrollUpScript 5-10 viewSetupChildrenScript 5-4 viewSetupDoneScript 5-5 viewSetupFormScript 5-4 viewShowScript 5-7 viewStrokeScript 5-14 viewWordScript 5-17 system preferences 8-11 system services 12-1 ling 12-37 Find 12-1 idling 12-54 notication 12-52 Undo 12-51 system soup 8-11

T
TabExport, Connection function 16-36 TabImport, Connection function 16-37 tag slot 8-11 Tan 17-49 Tanh 17-49 target frames 11-8 target template 11-7

IN-23

INDEX

task template 11-7 registering unregistering 11-27 structure of 11-15 template 2-2, GL-6 child 2-2 declaring GL-2 parent 2-2 proto 2-5 textFlags slot 4-8 Throw 17-56 tick GL-6 Ticks 15-33 TieViews 2-91 Time 15-33 time and date functions and methods 17-26 Date 15-25 DateNTime 15-26 GetDateStringSpec 15-28 HourMinute 15-30 LongDateStr 15-30 SetLocale 15-30 SetLocation 15-31 SetTime 15-31 ShortDate 15-31 ShortDateStr 15-31 StringToDate 15-32 StringToTime 15-32 Ticks 15-33 Time 15-33 TimeInSeconds 15-33 TimeStr 15-33 TotalMinutes 15-34 TimeInSeconds 15-33 TimeStr 15-33 to-do frames 8-10 Toggle 2-50 TotalClone 17-10 TotalMinutes 15-34 TotalSize 7-19 TrackButton 2-89 TrackHilite 2-88

transfer mode 2-32 TrimString 17-24 Trunc 17-49

U
Undo 12-51 union soup 7-3, 7-21 UnionSoupIsNull 7-67 Unordered 17-49 UnorderedGreaterOrEqual 17-49 UnorderedLessOrEqual 17-50 UnorderedOrEqual 17-50 UnorderedOrGreater 17-50 UnorderedOrLess 17-51 UnRegisterCardSoup 7-46 unregistering the task template 11-27 Upcase 17-24 UsedSize 7-20 user preferences soup 8-11 user proto GL-6 utility functions 17-1

V
ValidateNotes, Connection function 16-73 ValidateSlots, Connection function 16-69 value, immediate GL-3 vAnythingAllowed 6-3 vApplication ag 2-14 variable, local GL-4 vCalculateBounds ag 2-14 vCapsRequired 6-7 vCharsAllowed 6-5 vClickable 6-3 vClickableAllowed 6-5 vClickable ag 2-15 vClipping ag 2-14

IN-24

INDEX

vCustomDictionaries 6-6 vDateField 6-7 VerifyParagraph, Connection function 16-75 VerifyParagraphArray, Connection function 16-76 VerifyParagraphScript, Connection function 16-76 Version 16-14 meta data items 16-14 vFloating ag 2-14 view 2-3, GL-6 adding dynamically 2-54 alignment 2-20 animating 2-34 base 2-5 behavior 2-13 closing 2-45 controlling recognition in 6-2, 6-8 coordinate system 2-7 copyProtection slot 4-8 creating 2-43 custom ll pattern 2-32 custom frame pattern 2-32 declareSelf slot 2-39 declaring 2-42 dening characteristics of 2-9 dependencies between 2-91 dirtying 2-47 displaying 2-47 drawing messages 5-7 ll color 2-30 nding bounds 2-70 frame color 2-30 frame inset 2-31 frame roundedness 2-31 frame shadow 2-31 frame thickness 2-31 hiding 2-47 highlighting 2-87 initialization messages 5-2 input messages 5-12 instantiation 5-2

keyboards built-in 2-100 laying out multiple children 2-96 limiting text in 2-24 lines in 2-31 memory usage 2-107 modal 2-66 optimizing performance 2-105 origin offset 2-28 other messages 5-19 overview message 5-10 pop-up views 2-59 redrawing 2-106 root 2-7, GL-5 screen-relative bounds 2-18 scrolling messages 5-10 showing hidden 2-55 sibling views 2-20 size relative to parent 2-18 speeding up scrolling 2-108 synchronization 2-93 termination messages 5-2 testing whether open 2-49 textFlags slot 4-8 viewBounds slot 2-16 viewClass slot 2-11 viewFlags slot 2-13 viewFont slot 2-39, 4-11 viewFormat slot 2-28 viewFrontKey 2-47 viewFrontMost 2-47 viewFrontMostApp 2-47 viewJustify slot 2-20 viewOriginX slot 2-28 viewOriginY slot 2-28 viewTransferMode slot 2-32 viewAddChildScript 5-21 view alignment 2-16, 2-20 view bounds nding 2-70 setting 2-70 slot 2-16 viewBounds slot 2-16

IN-25

INDEX

viewChangedScript 5-22 viewChildren slot 2-40 view class 2-11, GL-6 view classes clEditView 4-3 clGaugeView 4-28 clKeyboardView 4-21 clMonthView 4-31 clOutline 4-34 clParagraphView 4-6 clPictureView 4-19 clPolygonView 4-16 clRemoteView 4-33 clView 4-1 summary 4-37, 5-25 viewClass slot 2-11, 5-2 viewClickScript 5-13 viewDrawScript 5-8 viewDropChildScript 5-23 view effects 2-34 viewEffect slot 2-34 viewFlags vAnythingAllowed 6-3 vApplication 2-14 vCalculateBounds 2-14 vCapsRequired 6-7 vClickable 2-15, 6-3 vClickableAllowed 6-5 vClipping 2-14 vCustomDictionaries 6-6 vDateField 6-7 vFloating 2-14 vLettersAllowed 6-6 vMathAllowed 6-6 vNameField 6-6 vNoFlags 2-15 vNoScripts 2-15 vNothingAllowed 6-3 vNumbersAllowed 6-7 vPhoneField 6-7 vPunctuationAllowed 6-6 vReadOnly 2-14

vShapesAllowed 6-5 vSingleUnit 6-5 vStrokesAllowed 6-4 vTimeField 6-7 vVisible 2-14 vWriteProtected 2-15 viewFlags slot 2-13, 6-2, 6-8 viewFont slot 2-39, 4-11 viewFormat slot 2-28 viewFramePattern 2-32 viewFrontKey 2-47 viewFrontMost 2-47 viewFrontMostApp 2-47 view functions and methods AddStepView 2-57, 2-60, 2-62 ArrayToPoints 4-19 BuildContext 2-58 ButtonBounds 2-72 ChildViewFrames 2-46 Close 2-49 Conrm 2-66 Delete 2-80 Dirty 2-52 DoPopup 2-63 Drag 2-81 Effect 2-73 GetCaretBox 2-102 GetHiliteOffsets 2-89 GetRoot 2-46 GetView 2-47 GetViewFlags 2-104 GlobalBox 2-71 Hide 2-51 Hilite 2-88 HiliteOwner 2-89 HiliteUnique 2-88 KeyboardInput 2-102 KeyIn 2-103 LayoutColumn 2-100 LayoutTable 2-96 LocalBox 2-71 ModalDialog 2-68

IN-26

INDEX

view functions and methods (continued) Open 2-48 Parent 2-46 PictBounds 2-72 PointsToArray 4-18 PostKeyString 2-103 RedoChildren 2-93 RefreshViews 2-53 RelBounds 2-70 RevealEffect 2-77 SetBounds 2-71 SetHilite 2-90 SetKeyView 2-102 SetOrigin 2-83 SetPopup 2-104 SetValue 2-53 Show 2-51 SlideEffect 2-75 SyncChildren 2-95 SyncScroll 2-85 SyncView 2-54 TieViews 2-91 Toggle 2-50 TrackButton 2-89 TrackHilite 2-88 Visible 2-105 viewGestureScript 5-15 viewHideScript 2-51, 5-7 viewHiliteScript 5-9 viewIdleScript 5-23 view instantiation description 2-41 system messages 5-2 system messages during 5-2 viewJustify slot 2-20, 5-3 view location 2-16 viewOriginX 2-28 viewOriginX slot 2-28 viewOriginY slot 2-28 viewOverviewScript 5-11 viewQuitScript 5-6 viewScrollDownScript 5-10

viewScrollUpScript 5-10 viewSetupChildrenScript 5-2, 5-4 viewSetupDoneScript 5-3, 5-5 viewSetupFormScript 5-2, 5-4 viewShowScript 2-51, 5-7 view size 2-16 viewStrokeScript 5-14 view system, overview 1-7 viewTransferMode slot 2-32 viewWordScript 5-17 Visible 2-105 vLettersAllowed 6-6 vlettersAllowed 6-6 vMathAllowed 6-6 vNameField 6-6 vNoFlags ag 2-15 vNoScripts ag 2-15 vNoSpaces 6-8 vNothingAllowed 6-3 vNumbersAllowed 6-7 vPhoneField 6-7 vPunctuationAllowed 6-6 vReadOnly ag 2-14 vShapesAllowed 6-5 vSingleUnit 6-5 vStrokesAllowed 6-4 vTimeField 6-7 vVisible ag 2-14, 5-3 vWriteProtected ag 2-15

W, X, Y
warnings, Connection 16-84 writing meta data frames 16-61 written input and recognition 6-1

Z
ZIP protocol errors A-11

IN-27

THE

APPLE

PUBLISHING

SYSTEM

This Apple manual was written, edited, and composed on a desktop publishing system using Apple Macintosh computers and FrameMaker software. Proof pages were created on an Apple LaserWriter Pro 630 printer. Final page negatives were output directly from the text and graphics les. Line art was created using Adobe Illustrator. PostScript, the page-description language for the LaserWriter, was developed by Adobe Systems Incorporated. Text type is Palatino and display type is Helvetica. Bullets are ITC Zapf Dingbats. Some elements, such as program listings, are set in Apple Courier.
LEAD WRITER

Christopher Bey
WRITERS

Bob Anders, Christopher Bey, John Perry, Jonathan Simonoff


PROJECT LEADER

Christopher Bey
ILLUSTRATOR

Peggy Kunz
EDITOR

David Schneider
PRODUCTION EDITOR

Rex Wolf
PROJECT MANAGER

Gerry Kane Special thanks to Bob Ebert, Mike Engber, Martin Gannholm, Kent Sandvik, Maurice Sharp, Walter Smith, and Scott ZZ Zimmerman.

You might also like