Paolo Amoroso's Journal

Tech projects, hobby programming, and geeky thoughts of Paolo Amoroso

I started working on GravityLoops, a software that simulates a collection of bodies interacting under the mutual gravity. I develop it on Medley in Interlisp and its object extension LOOPS, the Lisp Object-Oriented Programming System.

GravityLoops will show an animation of the bodies and their motions, along with facilities for defining the parameters of the system and controlling the simulation.

Motivation

I've been meaning to do a LOOPS learning project but none of the ideas I initially came up with clicked.

I wanted something more complex than a toy but easy enough to implement with reasonable effort. The project should also incorporate naturally the features of LOOPS, such as the gauges library of graphical meters and dials for displaying quantities.

I finally stumbled upon the gravity simulator described in the article Force-Based Simulations by Todd King in the September, 1989 issue of Dr. Dobbs Journal. It's just perfect.

I'm adapting to LOOPS the design of the sample C++ code that comes with the article. It's nice as it reads like an object-oriented domain specific language for simulation. The code is so short and clean I can fully understand it despite my minimal C++. I never thought I would say that of C++.

There is much to like of King's program starting from its domain, astronomy and physics, which overlaps with some of my passions.

The project is period accurate too as when Dr. Dobb's Journal published the article LOOPS was still under development. And, along with window systems, simulation was among the killer applications object-oriented programming proponents pointed to.

The program comprises only two, hierarchically unrelated classes, a shallow inheritance design more in line with the later evolution of object-oriented programming. But the application does offer other potential classes that are a good fit for LOOPS. For example, I plan to specialize the LOOPS class Window to represent the simulaton window. I will likely need more classes for the GUI, such as dialogs for entering the simulation parameters.

LOOPS is one of the subsystems best integrated with the Interlisp environment and comes with good documentation. I want to experience this high integration, the ability of combining tools designed to work together that comes natural once you're familiar with the environment.

Adapting King's program to the Interlisp environment is also an opportunity to employ useful programming techniques like screen buffering to improve animation fluidity. Plus, anything that draws pretty graphics is fun.

Design

To adapt Todd's design to LOOPS I create matching classes with similar instance variables and methods, named according to the LOOPS style. I will rename a few confusing methods, such as UNIVERSE::service() to register a body with a universe which I'll call Universe.Register, and UNIVERSE::big_bang() to run the simulation which will become Universe.Simulate.

The C++ code represents a 2D vector as a struct that I map to an Interlisp record. A class seems overkill.

Todd's program outputs to the MS-DOS text console via the conio library. GravityLoops instead will draw graphics in a window.

So far the code implements the Body class that represents a body. I'm about to start working on the Universe class that holds a collection of bodies and manages the parameters and state of the simulation.

Once the core classes are in place I will turn to implementing the animated simulation.

#GravityLoops #Interlisp #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

Insphex adds the Hexdump item to the File Browser menu to view the hex dump of the selected files. The initial implementation called the public API for adding commands at the top level of the menu.

In order to move the item to the See sumbenu that groups various file viewing commands I later resorted to list surgery, as the API doesn't support submenus. The problem is internal system details can and do change, which happened to the File Browser menu and led to an Insphex load error.

I fixed the issue by reverting the public API call and now the item is back at the top level of the menu.

Insphex is a hex dump tool similar to the Linux command hexdump. I wrote it in Common Lisp on Medley Interlisp.

#insphex #CommonLisp #Interlisp #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

My ILsee program for viewing Interlisp source files is written in Common Lisp with a McCLIM GUI. It is the first of the ILtools collection of tools for viewing and accessing Interlisp data.

Although ILsee is good at its core functionality of displaying Interlisp code, entering full, absolute pathnames as command arguments involved a lot of typing.

The new directory navigation commands Cd and Pwd work like the analogous Unix shell commands and address the inconvenience. Once you set the current directory with Cd the See File command can take file names relative to the directory. This is handy when you want to view several files in the same directory.

Here I executed the new commands in the interactor pane. They print status messages in which directories are presentations, not just static text.

Screenshot of the ILsee Interlisp file viewer with a few a few commands executed at an interactor pane.

Thanks to the functionality of CLIM presentation types, previously output directories are accepted as input in contexts in which a command expects an argument of matching type. Clicking on a directory fulfills the required argument. In the screenshot the last Cd is prompting for a directory and the outlined, mouse sensitive path /home/paolo/il/ is ready for clicking.

Cd and Pwd accept and print presentations of type dirname, which inherits from the predefined type pathname and restricts input to valid directories. Via the functionality of the pathname type the program gets path completion for free from CLIM when typing directory names at the interactor.

The Cd command has a couple more tricks up its sleeve. A blank argument switches to the user's home directory, a double dot .. to the parent directory.

#ILtools #CommonLisp #Interlisp #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

I wrote ILsee, an Interlisp source file viewer. It is the first of the ILtools collection of tools for viewing and accessing Interlisp data.

I developed ILsee in Common Lisp on Linux with SBCL and the McCLIM implementation of the CLIM GUI toolkit. SLY for Emacs completed my Lisp tooling and, as for infrastructure, ILtools is the first new project I host at Codeberg.

This is ILsee showing the code of an Interlisp file:

Screenshot of the ILsee GUI program displaying the code of an Interlisp source file.

Motivation

The concepts and features of CLIM, such as stream-oriented I/O and presentation types, blend well with Lisp and feel natural to me. McCLIM has come a long way since I last used it a couple of decades ago and I have been meaning to play with it again for some time.

I wanted to do a McCLIM project related to Medley Interlisp, as well as try out SLY and Codeberg. A suite of tools for visualising and processing Interlisp data seemed the perfect fit.

The Interlisp file viewer ILsee is the first such tool.

Interlisp source files

Why an Interlisp file viewer instead of less or an editor?

In the managed residential environment of Medley Interlisp you don't edit text files of Lisp code. You edit the code in the running image and the system keeps track of and saves the code to “symbolic files”, i.e. databases that contain code and metadata.

Medley maintains symbolic files automatically and you aren't supposed to edit them. These databases have a textual format with control codes that change the text style.

When displaying the code of a symbolic file with, say, the SEdit structure editor, Medley interprets the control codes to perform syntax highlighting of the Lisp code. For example, the names of functions in definitions are in large bold text, some function names and symbols are in bold, and the system also performs a few character substitutions like rendering the underscore _ as the left arrow and the caret ^ as the up arrow .

This is what the same Interlisp code of the above screenshot looks like in the TEdit WYSIWYG editor on Medley:

Screenshot of the code of an Interlisp source file displayed by the TEdit editor on Medley Interlisp.

Medley comes with the shell script lsee, an Interlisp file viewer for Unix systems. The script interprets the control codes to appropriately render text styles as colors in a terminal. lsee shows the above code like this:

Screenshot of the lsee shell script displaying the code of an Interlisp source file in a Linux terminal.

The file viewer

ILsee is like lsee but displays files in a GUI instead of a terminal.

The GUI comprises a main pane that displays the current Interlisp file, a label with the file name, a command line processor that executes commands (also available as items of the menu bar), and the standard CLIM pointer documentation pane.

There are two commands, See File to display an Interlisp file and Quit to terminate the program.

Since ILsee is a CLIM application it supports the usual facilities of the toolkit such as input completion and presentation types. This means that, in the command processor pane, the presentations of commands and file names become mouse sensitive in input contexts in which a command can be executed or a file name is requested as an argument.

The ILtools repository provides basic instructions for installing and using the application.

Application design and GUI

I initially used McCLIM a couple of decades ago but mostly left it after that and, when I picked it back up for ILtools, I was a bit rusty.

The McCLIM documentation, the CLIM specification, and the research literature are more than enough to get started and put together simple applications. The code of the many example programs of McCLIM help me fill in the details and understand features I'm not familiar with. Still, I would have appreciated the CLIM specification to provide more examples, the near lack of which makes the many concepts and features harder to grasp.

The design of ILsee mirrors the typical structure of CLIM programs such as the definitions of application frames and commands. The slots of the application frame hold application specific data: the name of the currently displayed file and a list of text lines read from the file.

The function display-file does most of the work and displays the code of a file in the application pane.

It processes the text lines one by one character by character, dispatching on the control codes to activate the relevant text attributes or perform character substitution. display-file does incremental redisplay to reduce flicker when repainting the pane, for example after it is scrolled or obscured.

The code has some minor and easy to isolate SBCL dependencies.

Next steps

I'm pleased at how ILsee turned out. The program serves as a useful tool and writing it was a good learning experience. I'm also pleased at CLIM and its nearly complete implementation McCLIM. It takes little CLIM code to provide a lot of advanced functionality.

But I have some more work to do and ideas for ILsee and ILtools. Aside from small fixes, a few additional features can make the program more practical and flexible.

The pane layout may need tweaking to better adapt to different window sizes and shapes. Typing file names becomes tedious quickly, so I may add a simple browser pane with a list of clickable files and directories to display the code or navigate the file system.

And, of course, I will write more tools for the ILtools collection.

#ILtools #CommonLisp #Interlisp #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

RetroChallenge announced the results of RC2024/10 and I'm honored to be among the winners.

Written in Interlisp, the WebCard project I entered the competition with extends the NoteCards hypermedia system to visit web sites. It defines a new type of hypertext node, the Web card, which holds a URL of a web site. Clicking a NoteCards link to a Web card directs the web browser of the host operating system to visits the URL.

In the final comments on my project the judges wrote:

Paolo implemented custom icons, improved URL handling, and provided documentation and demos on his WebCards digital Rolodex. The project is finished, works as intended, and was delivered on schedule... What a feat!

I owe meeting the deadline to two circumstances. The first is I was already familiar with the Lisp API of NoteCards from another project, which gave me a good understanding of how to control and extend NoteCards.

The other circumstance is a fundamental property of Lisp and interactive Lisp systems: the very fine granularity of execution.

At the Lisp REPL I can evaluate expressions spanning a wide spectrum of complexity. From short, elementary expressions such as variable lookups and individual function calls, to arbitrary combinations of function calls and accesses to data structures. To experiment with and learn about a specific feature I don't need to write a full program or build scaffolding. I can just construct suitable expressions that exercise the feature, run them, and immediately see the results.

When researching WebCard I evaluated expressions to validate the key pieces of the intended solution, such as controlling a web browser from Lisp and storing data in NoteCards cards. It's a more fundamental approach than building a prototype, it's like making sure the building blocks of a prototype work as intended.

This, and the rich toolbox of the Medley environment, gave the confidence I could fill in the details and deliver the project on time. It also accommodated for some margin I ended up needing because of unexpected issues and the inevitable yak shaving.

#WebCard #Interlisp #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

I'm exploring another corner of the Interlisp ecosystem and history: the Interlisp-10 implementation for DEC PDP-10 mainframes, a 1970s character based environment that predated the graphical Interlisp-D system.

I approached this corner when I set out to learn and experiment with a tool I initially checked out only superficially, the TTY editor. This command line structure editor for Lisp code and expressions was the only one of Interlisp-10. The oldest of the Interlisp editors, it came before graphical interfaces and SEdit.

On Medley Interlisp the TTY editor is still useful for specialized tasks. For example, its extensive set of commands with macro support is effectively a little language for batch editing and list structure manipulation. Think Unix sed for s-exps. The language even provides the variable EDITMACROS (wink wink). Evaluating (PRINTDEF EDITMACROS) gives a flavor for the language.

For an experience closer to 1970s Interlisp I'm using the editor in its original environment, Interlisp-10 on TWENEX. SDF provides a publicly accessible TWENEX system running on a PDP-10 setup. With the product name TOPS-20, TWENEX was a DEC operating system for DECSYSTEM-20/PDP-10 mainframes derived from TENEX originally developed by BBN.

SDF's TWENEX system comes with Interlisp-10 and other languages. This is Interlisp-10 in a TWENEX session accessed from my Linux box:

A screenshot of a Linux terminal showing Interlisp-10 running under TWENEX in a SSH session.

Creating a TWENEX account is straightforward but I didn't receive the initial password via email as expected. After reporting this to the twenex-l mailing list I was soon emailed the password which I changed with the TWENEX command CHANGE DIRECTORY PASSWORD.

Interacting with TWENEX is less alien or arcane than I thought.

I recognize the influence of TENEX and TWENEX on Interlisp terminology and notation. For example, the Interlisp REPL is called Exec after the Exec command processor of the TENEX operating system. And, like TENEX, Interlisp uses angle brackets as part of directory names. It's clear the influence of these operating systems also on the design of CP/M and hence MS-DOS, for example the commands DIR and TYPE.

SDF's TWENEX system provides a complete Interlisp-10 implementation with only one notable omission: HELPSYS, the interactive facility for consulting the online documentation of Interlisp. The SDF wiki describes the basics of using Interlisp-10 and editing Lisp code with the TTY editor.

After a couple of years of experience with Medley Interlisp the Interlisp-10 environment feels familiar. Most of the same functions and commands control the development tools and facilities.

My first impression of the TTY editor is it's reasonably efficient and intuitive to edit Lisp code, at least using the basic commands. One thing that's not immediately apparent is that EDITF, the entry point for editing a function, works only with existing functions and can't create new ones. The workaround is to define a stub from the Exec like this:

(DEFINEQ (NEW.FUNCTION () T))

and then call (EDITF NEW.FUNCTION) to flesh it out.

Transferring files between TWENEX and the external world, such as my Linux box, involves two steps because the TWENEX system is not accessible outside of SDF.

First, I log into Unix on sdf.org with my SDF account and from there ftp to kankan.twenex.org (172.16.36.36) with my TWENEX account. Once the TWENEX files are on Unix I access them from Linux with scp or sftp to sdf.org. This may require the ARPA tier of SDF membership.

Everything is ready for a small Interlisp-10 programming project.

#Interlisp #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

It has been a year since I set up my System76 Merkaat with Linux Mint. In July of 2024 I migrated from ChromeOS and the Merkaat has been my daily driver on the desktop.

A year later I have nothing major to report, which is the point.

Despite the occasional unplanned reinstallation I have been enjoying the stability of Linux and just using the PC. This stability finally enabled me to burn bridges with mainstream operating systems and fully embrace Linux and open systems. I'm ready to handle the worst and get back to work.

Just a few years ago the frustration of troubleshooting a broken system would have made me seriously consider the switch to a proprietary solution. But a year of regular use, with an ordinary mix of quiet moments and glitches, gave me the confidence to stop worrying and learn to love Linux.

#linux

Discuss... Email | Reply @amoroso@oldbytes.space

DandeGUI now does graphics and this is what it looks like.

Some text and graphics output windows created with DandeGUI on Medley Interlisp.

In addition to the square root table text output demo, I created the other graphics windows with the newly implemented functionality. For example, this code draws the random circles of the top window:

(DEFUN RANDOM-CIRCLES (&KEY (N 200)
                            (MAX-R 50)
                            (WIDTH 640)
                            (HEIGHT 480))
       (LET ((RANGE-X (- WIDTH (* 2 MAX-R)))
             (RANGE-Y (- HEIGHT (* 2 MAX-R)))
             (SHADES (LIST IL:BLACKSHADE IL:GRAYSHADE (RANDOM 65536))))
            (DANDEGUI:WITH-GRAPHICS-WINDOW (STREAM :TITLE "Random Circles")
					   (DOTIMES (I N)
						    (DECLARE (IGNORE I))
						    (IL:FILLCIRCLE (+ MAX-R (RANDOM RANGE-X))
								   (+ MAX-R (RANDOM RANGE-Y))
								   (RANDOM MAX-R)
								   (ELT SHADES (RANDOM 3))
								   STREAM)))))

GUI:WITH-GRAPHICS-WINDOW, GUI:OPEN-GRAPHICS-STREAM, and GUI:WITH-GRAPHICS-STREAM are the main additions. These functions and macros are the equivalent for graphics of what GUI:WITH-OUTPUT-TO-WINDOW, GUI:OPEN-WINDOW-STREAM, and GUI:WITH-WINDOW-STREAM, respectively, do for text. The difference is the text facilities send output to TEXTSTREAM streams whereas the graphics facilities to IMAGESTREAM, a type of device-independent graphics streams.

Under the hood DandeGUI text windows are customized TEdit windows with an associated TEXTSTREAM. TEdit is the rich text editor of Medley Interlisp.

Similarly, the graphics windows of DandeGUI run the Sketch line drawing editor under the hood. Sketch windows have an IMAGESTREAM which Interlisp graphics primitives like IL:DRAWLINE and IL:DRAWPOINT accept as an output destination. DandeGUI creates and manages Sketch windows with the type of stream the graphics primitives require. In other words, IMAGESTREAM is to Sketch what TEXTSTREAM is to TEdit.

The benefits of programmatically using Sketch for graphics are the same as TEdit windows for text: automatic window repainting, scrolling, and resizing. The downside is overhead. Scrolling more than a few thousand graphics elements is slow and adding even more may crash the system. However, this is an acceptable tradeoff.

The new graphics functions and macros work similarly to the text ones, with a few differences. First, DandeGUI now depends on the SKETCH and SKETCH-STREAM library modules which it automatically loads.

Since Sketch has no notion of a read-only drawing area GUI:OPEN-GRAPHICS-STREAM achieves the same effect by other means:

(DEFUN OPEN-GRAPHICS-STREAM (&KEY (TITLE "Untitled"))
   "Open a new window and return the associated IMAGESTREAM to send graphics output to.
Sets the window title to TITLE if supplied."
   (LET* ((STREAM (IL:OPENIMAGESTREAM '|Untitled| 'IL:SKETCH '(IL:FONTS ,*DEFAULT-FONT*)))
          (WINDOW (IL:\\SKSTRM.WINDOW.FROM.STREAM STREAM)))
         (IL:WINDOWPROP WINDOW 'IL:TITLE TITLE)
         ;; Disable left and middle-click title bar menu
         (IL:WINDOWPROP WINDOW 'IL:BUTTONEVENTFN NIL)
         ;; Disable sketch editing via right-click actions
         (IL:WINDOWPROP WINDOW 'IL:RIGHTBUTTONFN NIL)
         ;; Disable querying the user whether to save changes
         (IL:WINDOWPROP WINDOW 'IL:DONTQUERYCHANGES T)
         STREAM))

Only the mouse gestures and commands of the middle-click title bar menu and the right-click menu change the drawing area interactively. To disable these actions GUI:OPEN-GRAPHICS-STREAM removes their menu handlers by setting to NIL the window properties IL:BUTTONEVENTFN and IL:RIGHTBUTTONFN. This way only programmatic output can change the drawing area.

The function also sets IL:DONTQUERYCHANGES to T to prevent querying whether to save the changes at window close. By design output to DandeGUI windows is not permanent, so saving isn't necessary.

GUI:WITH-GRAPHICS-STREAM and GUI:WITH-GRAPHICS-WINDOW are straightforward:

(DEFMACRO WITH-GRAPHICS-STREAM ((VAR STREAM)
                                &BODY BODY)
   "Perform the operations in BODY with VAR bound to the graphics window STREAM.
Evaluates the forms in BODY in a context in which VAR is bound to STREAM which must already exist, then returns the value of the last form of BODY."
   `(LET ((,VAR ,STREAM))
         ,@BODY))

(DEFMACRO WITH-GRAPHICS-WINDOW ((VAR &KEY TITLE)
                                &BODY BODY)
   "Perform the operations in BODY with VAR bound to a new graphics window stream.
Creates a new window titled TITLE if supplied, binds VAR to the IMAGESTREAM associated with the window, and executes BODY in this context. Returns the value of the last form of BODY."
   `(WITH-GRAPHICS-STREAM (,VAR (OPEN-GRAPHICS-STREAM :TITLE (OR ,TITLE "Untitled")))
           ,@BODY))

Unlike GUI:WITH-TEXT-STREAM and GUI:WITH-TEXT-WINDOW, which need to call GUI::WITH-WRITE-ENABLED to establish a read-only environment after every output operation, GUI:OPEN-GRAPHICS-STREAM can do this only once at window creation.

GUI:CLEAR-WINDOW, GUI:WINDOW-TITLE, and GUI:PRINT-MESSAGE now work with graphics streams in addition to text streams. For IMAGESTREAM arguments GUI:PRINT-MESSAGE prints to the system prompt window as Sketch stream windows have no prompt area.

The random circles and fractal triangles graphics demos round up the latest additions.

#DandeGUI #CommonLisp #Interlisp #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

Printing rich text to windows is one of the planned features of DandeGUI, the GUI library for Medley Interlisp I'm developing in Common Lisp. I finally got around to this and implemented the GUI:WITH-TEXT-STYLE macro which controls the attributes of text printed to a window, such as the font family and face.

GUI:WITH-TEXT-STYLE establishes a context in which text printed to the stream associated with a TEdit window is rendered in the style specified by the arguments. The call to GUI:WITH-TEXT-STYLE here extends the square root table example by printing the heading in a 12-point bold sans serif font:

(GUI:WITH-OUTPUT-TO-WINDOW (STREAM :TITLE "Table of square roots")
  (GUI:WITH-TEXT-STYLE STREAM :FAMILY :SANS :SIZE 12 :FACE :BOLD)
    (FORMAT STREAM "~&Number~40TSquare Root~2%"))
  (LOOP
    FOR N FROM 1 TO 30
    DO (FORMAT STREAM "~&~4D~40T~8,4F~%" N (SQRT N))))

The code produces this window in which the styled column headings stand out:

Medley Interlisp window of a square root table generated by the DandeGUI GUI library.

The :FAMILY, :SIZE, and :FACE arguments determine the corresponding text attributes. :FAMILY may be a generic family such as :SERIF for an unspecified serif font; :SANS for a sans serif font; :FIX for a fixed width font; or a keyword denoting a specific family like :TIMESROMAN.

At the heart of GUI:WITH-TEXT-STYLE is a pair of calls to the Interlisp function PRINTOUT that wrap the macro body, the first for setting the font of the stream to the specified style and the other for restoring the default:

(DEFMACRO WITH-TEXT-STYLE ((STREAM &KEY FAMILY SIZE FACE)
                           &BODY BODY)
   (ONCE-ONLY (STREAM)
          `(UNWIND-PROTECT
               (PROGN (IL:PRINTOUT ,STREAM IL:.FONT (TEXT-STYLE-TO-FD ,FAMILY ,SIZE ,FACE))
                      ,@BODY)
               (IL:PRINTOUT ,STREAM IL:.FONT *DEFAULT-FONT*))))

PRINTOUT is an Interlisp function for formatted output similar to Common Lisp's FORMAT but with additional font control via the .FONT directive. The symbols of PRINTOUT, i.e. its directives and arguments, are in the Interlisp package.

In turn GUI:WITH-TEXT-STYLE calls GUI::TEXT-STYLE-TO-FD, an internal DandeGUI function which passes to .FONT a font descriptor matching the required text attributes. GUI::TEXT-STYLE-TO-FD calls IL:FONTCOPY to build a descriptor that merges the specified attributes with any unspecified ones copied from the default font.

The font descriptor is an Interlisp data structure that represents a font on the Medley environment.

#DandeGUI #CommonLisp #Interlisp #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

I continued working on DandeGUI, a GUI library for Medley Interlisp I'm writing in Common Lisp. I added two new short public functions, GUI:CLEAR-WINDOW and GUI:PRINT-MESSAGE, and fixed a bug in some internal code.

GUI:CLEAR-WINDOW deletes the text of the window associated with the Interlisp TEXTSTREAM passed as the argument:

(DEFUN CLEAR-WINDOW (STREAM)
   "Delete all the text of the window associated with STREAM. Returns STREAM"
   (WITH-WRITE-ENABLED (STR STREAM)
          (IL:TEDIT.DELETE STR 1 (IL:TEDIT.NCHARS STR)))
   STREAM)

It's little more than a call to the TEdit API function IL:TEDIT.DELETE for deleting text in the editor buffer, wrapped in the internal macro GUI::WITH-WRITE-ENABLED that establishes a context for write access to a window.

I also wrote GUI:PRINT-MESSAGE. This function prints a message to the prompt area of the window associated with the TEXTSTREAM passed as an argument, optionally clearing the area prior to printing. The prompt area is a one-line Interlisp prompt window attached above the title bar of the TEdit window where the editor displays errors and status messages.

(DEFUN PRINT-MESSAGE (STREAM MESSAGE &OPTIONAL DONT-CLEAR-P)
   "Print MESSAGE to the prompt area of the window associated with STREAM. If DONT-CLEAR-P is non NIL the area will be cleared first. Returns STREAM."
   (IL:TEDIT.PROMPTPRINT STREAM MESSAGE (NOT DONT-CLEAR-P))
   STREAM)

GUI:PRINT-MESSAGE just passes the appropriate arguments to the TEdit API function IL:TEDIT.PROMPTPRINT which does the actual printing.

The documentation of both functions is in the API reference on the project repo.

Testing DandeGUI revealed that sometimes text wasn't appended to the end but inserted at the beginning of windows. To address the issue I changed GUI::WITH-WRITE-ENABLED to ensure the file pointer of the stream is set to the end of the file (i.e -1) prior to passing control to output functions. The fix was to add a call to the Interlisp function IL:SETFILEPTR:

(IL:SETFILEPTR ,STREAM -1)

#DandeGUI #CommonLisp #Interlisp #Lisp

Discuss... Email | Reply @amoroso@oldbytes.space

Enter your email to subscribe to updates.