The Machines · Runtime stack

seedscribbler

A reckoner seed: scribbler, a window held by name — machines/seeds/seedscribbler.shoddy

the seedscribbler machine's icon

Summary

A session can draw. SCRIBOPEN opens a window and keeps it open under a name. SCRIBFILL, SCRIBPIXEL, SCRIBTEXT and SCRIBBLIT draw on it. SCRIBSAVE writes a PNG — an ordinary image file. CLOSE shuts it.

That sentence was refused for a long time. The grounds turned out to be three different things wearing one coat, and each was answered differently.

The objectionWhat answered it
The handle. A live resource must not reach the stack, because UNDO restores the stack and the thing naming the window would go with it.reckoner's named-resource table. SCRIBOPEN binds under a name; nothing ever pushes the window.
The main thread. A window must be created and pumped on the process's main thread, which a shell's read loop looked to own.Nothing. It never did. The mill already runs the Shoddy program on a background thread and keeps the main one pumping windows — handling their events. So a window opened mid-session is the supported path, and it stays live while the prompt waits.
The aborts. ScribblerOpen dies when there is no window backend — which is every way of running a program except mill run.The runtime. TryScribblerOpen reports it instead, so a session in a woven binary or under the debugger is told rather than ended.

Why It's Useful

A slot, not a value, and this is the one place scribbler differs from seedrecio. A file handle is a number, so RECOPEN puts it straight in the binding. A Scribbler is its own value kind, and the binding has no room for one. So TryScribblerOpen answers a slot number instead. ScribblerOf turns that number back into the window, and ScribblerShut lets it go. The seed holds an integer, and the ordinary drawing builtins do the work, untouched.

The words are SCRIB*, not SCRIBBLER*. The builtins keep their names and stay out of the dictionary. A session's SCRIBPIXEL takes a name where the builtin takes a window. They are different words, and a shared spelling would be a lie about which one you had.

The drawing words answer nothing, which is where they part company with the builtins. A builtin threads the window through so a program can chain. A session already has the name, and would only have to DROP what came back. SCRIBSAVE is the one exception, because whether it wrote is a real question.

What is not here, and is not forgotten. The event words — ScribblerPoll, ScribblerWait, ScribblerSetInterval — are left out on purpose. They exist for a frame loop, a program that redraws the window over and over. A reckoner line is a transaction that answers and ends. A word that blocked for the next event would hold the session inside one line with no way back. Reading the mouse from a calculator prompt is a different design and not this one.

Quitting closes it. halifax shuts every bound resource on the way out. For a file that is good manners — the process exit would have closed it anyway. For a window it is not optional. The mill's pump loop keeps running while any window is open, so a session that opened one and quit would leave the mill alive with no prompt.

User's Guide

> 200 120 "w" SCRIBOPEN
ok: opened w
[ empty ]

> "w" 10 40 90 SCRIBFILL
[ empty ]

> "w" 20 20 2 255 220 90 "SHODDY" SCRIBTEXT
[ empty ]

> "w" 60 70 255 80 80 SCRIBPIXEL
[ empty ]

> "w" 60 70 SCRIBGETPIXEL
x: { 255 80 80 }

> "w" SCRIBBLIT
[ empty ]

> "w" "shoddy.png" SCRIBSAVE
x: True

> "w" CLOSE
ok: closed w

Nothing appears until SCRIBBLIT, which is what makes a whole picture arrive at once rather than a pixel at a time. And the window survives UNDO: wind the stack all the way back and "w" SCRIBWIDTH still answers. UNDO restores a stack and does not un-draw a picture.

Word Reference

WordDescription
SCRIBOPEN ( w h name -- )Open a drawing window w by h pixels and keep it open under that name. Needs a mill started with mill run — anything else has no window backend and is told so.
SCRIBWIDTH ( name -- n )How many pixels wide that window is.
SCRIBHEIGHT ( name -- n )How many pixels tall that window is.
SCRIBTITLE ( name s -- )Put s in that window's title bar.
SCRIBFILL ( name r g b -- )Fill the whole window with one colour.
SCRIBPIXEL ( name x y r g b -- )Set one pixel. Coordinates count from 0 and are clamped to the window; colours are 0 to 255.
SCRIBGETPIXEL ( name x y -- list )The colour at x, y as a list of red, green and blue.
SCRIBTEXT ( name x y scale r g b s -- )Draw s at x, y in the built-in 8×8 font, scale times its own size. A scale of 1 is eight pixels tall; below 1 is refused.
SCRIBBLIT ( name -- )Show what has been drawn. Nothing appears until this is called.
SCRIBSAVE ( name path -- ok )Write the window to a PNG file; True on success, False on a path it cannot write. The one drawing word that answers something.

CLOSE and BOUND are reckoner's own and work here without this seed saying anything about them. There is deliberately no SCRIBCLOSE: one way to shut a resource is the whole reason the table is uniform.

Who Uses It

UserHow
halifaxThe calculator's drawing words — a window opened from the prompt, drawn on across lines, and shut by CLOSE or by quitting.
sparkySparky folds it too, onto a pixel buffer with no window — a drawing comes back to the client as a PNG.

A mill claims this seed by folding RckSeedScribbler over its reckoner state, which is all halifax does.

The Machines It Uses

MachineWhy
cuttleThe Cell type coordinates and colours cross the bridge as.
reckonerRckReg and the argument readers, and the named-resource table — RckBind, RckBoundTo, RckResOf — that makes an open window reachable after UNDO.
scribblerThe domain this seed bridges: the Scribbler type and the drawing words the seed calls behind each name.
seqList plumbing under the argument readers.