Mottek: 2010-11-23

Fun with NEWT/0

One of my long standing pet peeves is the problem of not being able to use Mac OS X anymore for Newton development since the Leopard days. Basilisk II is of course an option, but it's quite cumbersome. For that reason, I've been trying to put together simple compiler based on NEWT/0 and the DCL to allow at least some sort of text based development.

So far my experiments are actually quite successful, and it seems that developing Newton applications with just a text editor is not that impractical. It is in fact easier when it comes down to version control management. Some things are still missing for developing larger apps, like the ability to split the code into multiple source files, and a way to embed resources into the final package, but for simple applications (and even auto parts), we might have a way forward.

This is nowhere as ambitious as Matthias Melcher's DyneTK project, but maybe good enough to get people interested in a bit of Newton hacking. Unfortunately I haven't gotten around to packaging the code nicely yet, so far it's part of the SVN repository at SourceForge under tntk. I also uploaded the Mac OS X binary itself, but there are guarantees that it would actually to something useful. It has a couple of non-functional parts, but compilation should be as simple as

tntk -c ProjectFile.nprj

Below is how a simple NewtApp would look like, first the project file which describes basic app parameters, and also points to the NTK platform file which contains common definitions needed for development (this would be saved as e.g. ProjectFile.nprj):

{
    parts: [
        {
            main: "Main.newt",
            files: [],
        }
    ],
    name: "MiniNewtApp:40hz",
    platform: "/Applications/Newton/NTK 1.6.4/Platforms/Newton 2.1"
}

And this is the main file, according to the project file above it would need to be saved as Main.newt:

kAppSymbol := '|MiniNewtApp:40Hz|;
kAppTitle := "MiniNewtApp";
kVersion := "1.0";

defaultLayout := {
    _proto: newtLayout,
    masterSoupSlot: 'MiniNewtAppSoup,
    name: "Default",

    viewJustify: vjParentFullH + vjParentFullV,
    viewBounds: {left: 0, top: 20, right: 0, bottom: -25},

    stepChildren: [
        {
            _proto: newtEntryView,

            viewJustify: vjParentFullH + vjParentFullV,
            viewBounds: {left: 0, top: 0, right: 0, bottom: 0},

            stepChildren: [
                {
                    _proto: newtLabelInputLine,
                    path: 'title,
                    label: "Title",
                    labelFont: ROM_fontSystem10Bold,
                    viewJustify: vjParentFullH + vjParentTopV,
                    viewBounds: {left: 0, top: 4, right: -8, bottom: 32},
                },
            ]
        }
    ]
};

overviewLayout := {
    _proto: newtOverLayout,
    masterSoupSlot: 'MiniNewtAppSoup,
    name: "Overview",

    viewJustify: vjParentFullH + vjParentFullV,
    viewBounds: {left: 0, top: 20, right: 0, bottom: -25},

    Abstract: func(target, bbox) begin
        return MakeText(target.title, bbox.left + 2, bbox.top, bbox.right, bbox.bottom - 18);
    end
};

mainView := {
    _proto: newtApplication,
    title: kAppTitle,
    appSymbol: kAppSymbol,
    appObject: ["Task", "Tasks"],
    appAll: "All Tasks",
    allLayouts: {
        default: defaultLayout,
        overview: overviewLayout
    },
    aboutInfo: {
        tagLine: "MiniNewtApp - a NewtApp demo",
        copyright: "(c) Eckhart Koeppen, all rights reserved",
        version: kVersion
    },
    allSoups: {
        miniNewtAppSoup: {
            _proto: newtSoup,
            soupName: "MiniNewtApp",
            soupIndices: [],
            soupQuery: {},

            CreateBlankEntry: func() begin
                return Clone({title: "Title"});
            end
        }
    },
    stepChildren: [
        {
            _proto: newtClockFolderTab
        },
        {
            _proto: newtStatusBar,
            menuLeftButtons: [newtInfoButton],
            menuRightButtons: [newtActionButton, newtFilingButton, newtCheckAllButton]
        },
    ],

    viewJustify: vjParentFullH + vjParentFullV,
    viewBounds: {left: 16, top: 16, right: -16, bottom: -16},
};

{
    app: kAppSymbol,
    text: kAppTitle,
    theForm: mainView,

    devInstallScript: func (partFrame) begin
        partFrame.removeFrame := partFrame.theForm:NewtInstallScript(partFrame.theForm);
    end,
    RemoveScript: func(partFrame) begin
        partFrame.removeFrame:NewtRemoveScript(removeFrame);
    end,

    InstallScript: func (partFrame) begin
        partFrame:?devInstallScript(partFrame);
        if HasSlot(partFrame, 'devInstallScript) then RemoveSlot(partFrame, 'devInstallScript);
        partFrame.InstallScript := nil;
    end,
}