Keyboard, Print: Sloup Inspector

Although this was added primarily to support Newt development, you can also use it just for keyboard entry to any text field. When you check Inspect?, the Sloup view shrinks to a smaller size (and leaves the connection open (if already open). When connected, keyboard input (& desktop Paste) will be directed to the current Newton "key view". If Newt is installed (its icon will be visible below Inspect?), the output from the global Print function, Newt's :print method, GetRoot's :Notify method, and Newt's :notify & :error methods will be directed to the terminal emulator while Sloup is connected (in both Inspect and regular transfer modes).

Tap the Paste button to send the current highlighted selection or entire field to the desktop.

For keyboard entry, just tap in a field on the Newton and start to type. Different terminal emulator programs may map characters differently, but the basic alphanumerics and punctuation keystrokes should work fine (check your configuration settings). On the Macintosh (at least), the left and right arrow keys should work. Backspace seems to work, though it doesn't erase the first character in Notepad. If you are connected and a view is selected, you should hear a keyclick sound.

Pasting large strings can be inefficient/slow since it posts/pastes a single character at a time. However, if you're in Inspect mode, in a "regular" input field/paragraph (not the Notepad), have a range selected or an empty field, and then enter a series of complete lines (usually via a Paste from the desktop or a Send Text File), text will appear 3-6x faster than before. This bypasses the usual entry mechanism which uses P-o-s-t-K-e-y-S-t-r-i-n-g. As it inserts lines, Sloup keeps an extra last space highlighted for the next line. When you type single characters or partial lines (no Return), this uses the usual PostKeyString method (and eliminates any selected range). This particular trade-off (kludge) allows much faster input, while still allowing special keystrokes like backspace/ delete, arrow keys, etc. to work.

Newt using Sloup

Here is a potential scenario for how to make effective use of Sloup for developing and testing Newt-based applications. (I've used it for Newt's many application examples, plus associated bitmap, sound and IR resources). Because of coordination between Sloup and Newt, you should obtain the latest version of each.

On the desktop, prepare application and resource files using a simple text editor, e.g., BBEdit Lite on Mac; Notepad on Windows.

Start Sloup. You can do this by tapping the Sloup icon in Extras, or from Newt, select Sloup from Newt's overview list.

Transfer any .bit, .snd, .cmd resources with Sloup. Check bitmaps and sounds using bitsound.nwt (example utility); if any are wrong, remove manually with bitsound (or other soup utility like StewPot); or make sure your resource file uses REPLACE!name. Re-transfer.

For the program source (.nwt) file, check/pick a folder for development. Add an ERASE! command so that everything will be removed before new entries are added, or REPLACE!title. Otherwise, you may clutter up your Newton with duplicate entries, though Newt will warn about these while using the most recent. To speed up transfer (and minimize storage), you may want to remove "readme comments" in your copy of original source.

{labels: 'Test, viewFont: 10241}

Transfer the .nwt file using Sloup. Alternatively, if you have a relatively static source file, you can convert the .nwt file into a Paperback application, and download this as a package; then Select it as a Library and Copy All into a folder (this can be a convenient way to manage multiple project sources without cluttering up folders, especially for large or relatively static source objects).

When finished, tap on Newt's icon from Sloup (or open Extras and open Newt from there).

Newt automatically checks objects and methods in its current folder (you may need to change folders, e.g., Test, for your current application. If there are any Newt structure or NewtonScript syntax errors, these are reported to both Newt's Eval Log and the desktop terminal emulator. For syntax errors, Newt will provide the line of source referred to in the error message.

If you plan to edit locally, check the Inspect? box. This keeps the serial connection open, but changes input modes (see Inspector). Fix any syntax errors, either directly in Newt (you can use the Inspector for keyboard input and to Save entries) [possibly, making changes in parallel in your text editor], or if there are many changes to be made, you could make the edits in the desktop editor, uncheck Inspect? and re-transfer the file with Sloup.

Build your application: "Build(App)" action command, or :doObj('build,'myApp).

Start using/testing your app.

If Inspect? is on, any Print expressions or errors will output to the terminal emulator. Of course, if you are developing an application involving serial or IR communication, you will have to Disconnect Sloup before attempting to initialize a new protoEndPoint. (See inspterm.nwt example for other debugging strategies).

Continue editing, testing...

Tap Save to save current running application as a package.

To transfer the package to the desktop, see tools page: ExtractPackage and Newton Connection Kit for 1.x; Package Buddy for 2.x; Sloup and NewtonLink for 2.x and Unix.

If you have made many changes in your Newton and wish to keep a backup copy on your desktop system, you can do a DUMP! and capture the current folder as a log file. (Or, if you want to save the source on the Newton as a library, see the Newt documentation for how to build a "folder library")

Newt's Cape using Sloup

You can use Sloup to

You can also use Newt's Cape to transfer a Sloup-format file via TCP/IP (if you have NIE installed on a 2.x Newton), and give it to Sloup for processing. For example, helpslpi.htm provides an HTML form that allows you to select some standard Sloup file extensions (.nwt, .bit, ...) and register these with Newt's Cape. When you access a URL for one of these files, Sloup will receive the file via Newt's Cape. This helper app stays in effect until you de-install via the page (or reboot). See addFile API (next).

You could also do this installation of extensions directly via a Sloup spec, e.g.,

{dummy: GetRoot().|Newtscape:Newtscape|:installHelperApp(\
"text/plain", '|Sloup:TKnollSys|, {extensions: [".tab", ".nwt", ".slp"]})}	// install

And to deinstall:

{dummy: GetRoot().|Newtscape:Newtscape|:installHelperApp(\
"text/plain", '|Sloup:TKnollSys|, NIL)}	// de-install

Enter a URL into Newt's Cape and tap Open:Location. Two demo URLs you can try (assumes you installed .tab and .nwt extensions):

addFile API

the :addFile API is compatible with Newt's Cape helperApp mechanism, but Newt's Cape does not have to be installed for it to be accessed directly by another application. addFile has the following 4 parameters:

MIME type
usually "text/plain". ignored for now
file name
a string. ignored for now
lines of Sloup commands. be sure to quote any " with \
usually nil or {}. ignored for now

NTK Inspector using Sloup

Generally, you cannot use NTK Inspector and Sloup at the same time since NTK Inspector is using the serial or ADSP port. However, if you do not Connect Sloup, but access it via addFile API, you can send "small" Sloup files directly from the NTK Inspector window.

DUMPed results are Printed. (This has advantage that if you use Inspector and get Sloup errors, you can do a stack trace and help me track them down!). For example,

GetRoot().|Sloup:TKnollSys|:addFile("text/plain", "foo.slp",
{labels: 'Personal}
DUMP!", nil)

General Soup Description

Some additional "types" to simplify the documentation (though these are not Sloup types)

strings containing ink data (unrecognized chars) mixed with regular text
{left: int, top: int, right: int, bottom: int}
an integer or font frame

I need to look more closely at soups to determine exact types, especially on strings. In 2.0, there are more options and Sloup may have to use the application API for each soup to ensure that these are set correctly.

In the abbreviated descriptions below (I hope I am consistent), I use the following notation:

Common Slots: All Soups

All soups have several slots in common. In general, you should not try to set these slots. However, there might be situations where it might be useful to DUMP! these, or to use with REPLACE!

[int] unique identifier for entry within the soup (caution: this would probably be different on a different store or on a different Newton)
[time] date and time that entry was last modified (not present for new entries?).

Notes: Structure

[symbol] = 'paperroll
class [NOS 2.x only]
[int] height (in pixels) of the note
[nil] for list or checkList; [array] frames containing text objects, polygons or ink objects

text object:

[symbol] = 'para
[bounds] the bounds of the text object
[string] text contained in the paragraph
[array] tab stops [int]
[array] alternating lengths [int] and font [font] run-codes
[font] -- defaults to current setting in Style palette

polygon object:

[symbol] = 'poly
[bounds] the bounds of the polygon object
[binary] binary data structure containing polygon data***

ink object:

[binary] ink data
[bounds] the bounds of the ink object
topics [NOS 2.x list or checkList only]
[array] of topic frames (note: data = nil)
[array] alternating lengths [int] and font [font] run-codes
[int] how many items are hidden at level 'level'
mtgDone (checkList only)
[boolean] true if the check box is checked; nil if it is unchecked
[int] indent level (starting at 1)
[time] creation date and time
[symbol] file folder -- defaults to nil (Unfiled)

Sloup currently recognizes just labels, height, and viewFont, and creates a single para object.

Names: Import Examples

In addition to and, here are several Names examples, followed by documentation on Names fields.Note use of line continuations to make entryspec and data more readable. There are 19 top-level fields in this example -- you can have only 20 before ordering is lost. Other possible fields to add: addresses[array], companies[array], emailAddresses[array]; you can add more specific-type info on things like email addresses, e.g., One way to learn by example is to modify the very first soup entry (check StewPot on Internal Names -- it's probably Royce Walthrop); add the kind of info that you'd like your entries to have; do a DUMP! on Names and look at the entrySpec info printed out -- match up spec and first entry.

{labels: 'symbol,\
name: {class: 'person, honorific: "string", first: "string", last: "string", },\
title: "string", company: "string",\
address: "string", address2: "string", city: "string",\
	region: "string", country: "string", postal_code: "string",\
phones: ["homePhone", "workPhone", "mobilePhone", "faxPhone"],\
pagers: [{pagerNum: "string.pager", pagerPin: "string"}, ],\
email: "", anniversary: "date", bday: "date",\
names: [{honorific: "string", first: "string", last: "string", title: "string",}],\
notes: ["para"], cardType: 0, sortOn: "stringWithClass"}

Business	person	Dr.	Royce	Walthroop	\
Grand VIP	Amalgamated Consolidated	\
217 Crocker Lane		Hillsdale	OH		44704	\
(419)555-3543	(419)555-3544	(419)555-3545	(419)555-3546	\
(123)456-7890	6666	8/25/76	12/12/46	\
Ms.	Grace	Mertins	Relative	\
hi, this is a note	0	name


The following example leaves out some of the other fields, but adds a second address:

{labels: 'symbol,\
name: {class: 'person, last: "string", first: "string", },\
address: "string", address2: "string", city: "string",\
	region: "string", postal_code: "string",\
company: "string",\
addresses: [{\
	address: "string", address2: "string", city: "string",\
	region: "string", postal_code: "string", }],\
phones: ["homePhone", "mobilePhone", "workPhone", "faxPhone"],\
cardType: 0, sortOn: "stringWithClass"}

Business	person	Walthump	Royce	\
227 Clunker Lane		Hallsdale	OH	44704	\
Amalgamated Unlimited	\
217 Clacker St.		Hellsdale	OH	44704	\
(419)555-3543	(419)555-3544	(419)555-3545	(419)555-3546	\
0	name
Business	person	Walthrip	Royce	\
217 Crisper Ave.	Apt. 3B	Hollsdale	OH	44704	\
Aggregated Mergers	\
217 Crimper Lane		Hullsdale	OH	44704	\
(419)555-3543	(419)555-3544	(419)555-3545	(419)555-3546	\
0	name


Names: Structure

The following slots are common to all Names objects. Each class may have additional slots.

Common Slots: Names

[int] 0 (Squiggle), 1 (Plain), 2 (Separate), 3 (Cross)
class (NOS 2.x)
[symbol]: 'person, 'company, 'owner, 'worksite, 'group
[string] same as contents of slot:
[array, string, nil] card note frames (see, text string or nil (to clear notes).

There are additional slots depending on the class. For 1.x, the slots are for Person, and the "class" could be inferred from context (whether name or company is optional).


name (required if no company for 1.x)
[string (rich)] person's first name
[string: 'Name] person's last name
[string (rich)] Mr., Ms., Dr., etc.
[string (rich)] person's title
(names) (NOS 2.x only)
[array] affiliated names (company contacts, family members, etc.) [frame: 'Person]. title refers to relationship to the main name.
company (required if no name for 1.x)
[string: 'Company] [string (rich)] for NOS 2.x
(companies) (NOS 2.x only)
[array] of frames
[string (rich)] street address
[string (rich)] 2nd line of address
[string] state or province
[string] postal or zip code
[array] up to four(?) phone numbers [string: 'phone, 'homePhone, 'faxPhone, 'workPhone, 'carPhone, 'mobilePhone, 'homeFaxPhone, 'otherPhone, ]
[date] birthday
[] e-mail address. If address is of specific type, use one of the following classes:,,,,,,,,,, For more than 1 address, see emailAddrs.

Person [NOS 2.x]

Additional slots for 2.x only

[array] additional addresses [frame]: address, address2, city, region, country, postal_code
[array] additional e-mail addresses [frame]
[] -- see more specific classes under email slot
[string] only for cards of type 'owner only
[string] owner's e-mail password (only for cards of type 'owner only). This goes with top-level email slot
[array] pager information frames
[string.pager] pager number
[string] pager PIN
[alias] to a calendar meeting
[date] anniversary date
[alias] to a calendar meeting

Company (NOS 2.x)

Very similar to Person

[nameRef] (same as Person)
[string] (same as Person)
[array] of [nameRefs]. in addition, a nameRef can contain
[string (rich)] company affiliation
emailAddrs (NOS 2.x)

Owner (NOS 2.x)

Same as Person, but in addition:

[array] frames
[string] the account number
[phone] phone number string for the bank account contact
[array] frames
[string] credit card user's name
[string] the account number
[string] the expiration date
[phone] phone number string for the credit card account contact
[signature] text and ink that user entered on signature slip

Worksite (NOS 2.x)

[string] the place name
[string] dialing prefix needed to get an outside line from this worksite
[string] area code of this worksite
[string] the printer the user has chosen from among network printers
[array] of frames
[symbol] e.g., 'concert
[int] e.g., 1200
[phone] phone number string to access e-mail at this site
[string] the network zone and machine name. The parameters are currentSelection, which returns the selected entity and currentZone, which returns the currently selected AppleTalk zone
[alias] to the closest city entry in the worldData soup
[symbol] representing the country
[string] representing the country
[array, string, nil]

Group (NOS 2.x)

[string] group's name
[array] of [nameref] representing the members of the group

Calendar: Dump Example (2.x)

{viewStationery: 'Meeting, mtgStartDate: "time", mtgDuration: "int",\
mtgText: "rich", mtgStopDate: "time", repeatType: "int", mtgInfo: "int",\
mtgAlarm: "time", mtgIconType: "int",\
mtgInvitees: [{name: {first: "string", last: "string"},}], version: "int",}

To Do: Dump Example (2.x)

To Do List
{class: 'todo, Date: "time", repeatInfo: {mtgStartDate: "time",\
mtgStopDate: "time", repeatType: "int", mtgInfo: "int",},\
topics: [{level: "int", mtgDone: "boolean", mtgPriority: "int",\
hideCount: "int", text: "string"}],}