From: Niels Mayer
Subject: Winterp: A Rapid Prototyping and Customizable Delivery Environment for Applications Using Widgets (was Re: GWM and Other things)
Date: 
Message-ID: <3510@hplabsz.HPL.HP.COM>
In article <··················@wscad4.local> ·······@wscad4.crd.ge.COM writes:
>I just swa the announcement and it sounds interesting - a window manager on the
>X Window System with a built in LISP Interpreter.   But how about a server 
>with a LISP Interpreter?

The beauty of X w/r/t NeWS is that it gives you a simple, small, reliable.
server. I don't have to worry about a rogue program running in the server
blowing all my applications out of the water. I don't want to have to
try to debug programs downloaded into a global resource like a  server.

So howsabout the next best thing to NeWS' capabilities, a rapid prototyping
and delivery environment that allows you to interactively create a user
interface using a mini-lisp interpreter ON THE CLIENT SIDE? Think of it as
a graphical gnuemacs that replaces operations on text buffers and windows
with operations on graphical widgets. I've created just such an application
environment, and it's called WINTERP.

(Note: A full description of WINTERP is included at the end of this posting
in LaTeX format.)

Although my WINTERP application is not yet available for public release
(i'm hoping my management to let me release it on the X11r4 contrib tape),
I wanted to see what people's reactions are to this sort of environment.

In particular, I would like to see some comments on how WINTERP might
compare to UIL as a prototyping environment, and also as a customization
language for a delivered application. Is OSF interested in supporting an
environment like WINTERP in addition to UIL?

It is my beleif that that WINTERP competes directly with the OSF's UIL, and
is infact a much more useful prototyping and delivery environment than UIL,
for the following reasons:

	1) WINTERP is interpreted rather than compiled, thereby allowing for
	interactive modifications of both the layout and functionality of
	an application's interface. Motif still forces you to bring down
	your application, recompile the UIL specification, and reload a UID
	file. Anybody who has tried to alter the appearance of an X
	application by modifyiung .Xdefaults and rerunniung the application
	should realize that customizing via UIL will be painful!

	2) When embedded in an application, UIL only allows for the layout of
	the UI to be changed. If a user desires to customize the user
	interface beyond the set of possibilities predicted by the
	application's designer,	the user is out of luck because UIL is 
	ONLY a layout language.	WINTERP, on the other hand, is a full blown
	customization language that allows for changes in the semantics of 
	the UI as well as the layout. UIL seems to have been designed from the
	perspective that the semantics of an application can be cleanly
	separated from the UI. I don't think that is possible in a
	real-world system (though it has made for a variety of interesting
	academicaly oriented conference papers...)
	
	3) An application using WINTERP as an embedded customization
	language has a flexible toolkit architecture. Primitive operations
	in the application are implemented in C and made available to the 
	top-level lisp interpreter. Peeling back the "top layer" of an
	application and allowing the user to customize the look and
	functionality with WINTERP's mini-lisp language allows designers
	to concentrate on the functionality underlying the system, while
	allowing users to customize to their own particular needs.
	Since WINTERP's mini-lisp is accessble to other processes through
	a server interface, these primitives also become callable from
	other applications. That makes for applications that can talk to
	each other, which is a first step towards getting all our separate
	Unix applications to talk to each other.
	
	4) UIL is a completely new language for people to learn.
	Unfortunately, i find it to be less compact of a specifcation that
	writing	widget code in C! And winterp-lisp is more compact and
	expressive than	either of these. Winterp's mini-lisp is certainly
	more of a language standard. This is especially true when you
	consider applications like gnuemacs and autoCAD which use embedded
	lisp interpreters as customization languages.  I'm currently thinking
	about whether I can cobble up a UIL--> winterp-lisp translator for
	those that don't like parentheses (i love em!). THis might enable
	an interactiveUIL-compatible system to be created.

------------------------------------------------------------------------------

I'll be at Xhibition incase anybody wants to talk about WINTERP.

Here's a blurb on winterp in LaTeX format:

------------------------------------------------------------------------------

\documentstyle [] {article}
\title  {{\it Winterp}: A Rapid Prototyping and \\
        Customizable Delivery Environment \\
        for Applications Using Widgets}
\author {Niels P. Mayer \\ ·····@hplabs.hp.com}
\date   {Human-Computer Interaction Department \\ Hewlett-Packard Laboratories}

\raggedbottom
\textwidth=6.5in
\textheight=8.5in
\oddsidemargin=0in
\topmargin=0in

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin {document}
\maketitle
\section* {Introduction}

{\it Winterp} is a mini-Lisp interpreter which allows programmers to
rapidly prototype graphical applications through interactive programmatic
manipulation of Xwidgets\footnote {An Xwidget is a graphical object that
can be manipulated by mouse or keyboard input: examples of Xwidgets include
scrollbars, pushbuttons, menus, editors, etc.}. The interpreter provides an
interface to the Xtoolkit Intrinsics, the HP Xwidgets, primitives for
collecting data from UN*X processes and facilities for interacting with
other UN*X processes.  Winterp thus supports multi window application
prototyping, allowing the user to interactively change both the appearance
and functionality of an application.

{\it Winterp} application writers will rapidly prototype new functionality
by using the mini-Lisp interpreter to interactively refine the user
interface.  Once functionality has stabilized, a programmer will be able to
improve the application's efficiency by reimplementing the functionality in
C while maintaining the same Lisp programmatic interface. This hybrid
Lisp/C approach to programming allows for highly customizable applications
to be developed and delivered without incurring the costs of having a
full-blown Common Lisp system. {\it Winterp's} Lisp interpreter is fast,
but it doesn't run at compiled speeds: it is designed to allow high-level
C-implemented Lisp primitives to be ``tied together'' via interpreted Lisp,
giving both the efficiency and small size of a C program with the
interactiveness and configurability of a full-blown Lisp system.

{\it Winterp} is designed to accommodate the full lifecycle of a program
from prototype to delivery. A deliverable, customizable application is
created through successive cycles of Lisp prototyping and C
reimplementation. The deliverable application is actually composed of a set
of C-implemented Lisp primitives which are ``tied together'' by a top-level
mini-Lisp program. Users can customize the appearance and functionality of
the application by customizing the top-level program.  Unconstrained
customization might take place by allowing the user to rewrite the
top-level program. More constrained customizations are possible by
providing ``hooks'' within the top-level program that can call the user's
customization code.

\section* {Background}

An environment similar to that provided by {\it Winterp} already exists in
the {\it GNU Emacs} editor. {\it Winterp} was in fact inspired from {\it
GNU Emacs}' success --- {\it GNU Emacs}' mini-Lisp interpreter has been
used to turn the editor into a complete programming environment.  Whereas
{\it GNU Emacs}-Lisp allows programmers to tie together C-implemented
primitives that operate on first-class types providing textual interfaces
(buffers, windows), {\it Winterp's} Lisp ties together operations on the
graphical ``first-class'' types, Xwidgets. Both achieve a high degree of
customizability that is common for systems implemented in Lisp, while still
attaining the speed of execution and (relatively) small size of a system
implemented in C.

{\it Winterp} was created as the platform on top of which the Structured
Discourse Project will develop {\it Strudel}, a highly configurable
mail/calendar/information management system to enable computer supported
cooperative work.  We intend for {\it Strudel} to become the ``{\it GNU
Emacs} of groupware systems''.  The Lisp interpreter will permit the system
to be customized to support special modes of communication for particular
workgroup environments much in the same way that {\it GNU Emacs} Lisp is
used to customize the editor to support special editing modes for
particular programming environments.

{\it Winterp's} mini-Lisp and Xwidget primitives will be used as a
description language for creating and processing active/graphical e-mail
forms within {\it Strudel} --- these forms can be sent (as textual
programs) through standard e-mail channels (see fig. 1).  The receiving
{\it Strudel} system will interpret the program and display a form letter
containing a user interface built from arbitrary combinations of Xwidgets
and bitmaps, (and in the future, voice and video ``widgets'').  Users will
be able to choose from a library of email forms that are designed to track
specific types of conversations --- scheduling meetings and resources,
software defect tracking, fleshing out design issues, etc.  Workgroups can
extend the library of forms to help capture and manage recurrent
conversations that are not covered by {\it Strudel}'s standard forms
library.

\section* {{\it Winterp} Implementation and Usage Details}

The {\it Winterp} distribution contains a number of example programs that
show people how {\it Winterp} can be used to build applications --- these
examples include a simple file browser, a mail browser, a bitmap browser,
etc. The examples cover the important aspects of Xwidget programming, such
as writing a callback\footnote {A callback is a programmatic action that
occurs when a widget is activated via mouse or keyboard.} in Lisp, setting
and getting widget parameters, and laying out a widget hierarchy.

The programmer's interface to {\it Winterp} occurs directly within the {\it
GNU Emacs} editor --- mouse the expression to be interpreted by {\it
Winterp}, give the {\it GNU Emacs}-standard Lisp-send-defun (C-M-X) command
and the expression will be evaluated. The programmer can see the graphical
results of changes to a program without having to exit the editor to
compile, run, and test the program: {\it Winterp} gives a truly interactive
``what you program is what you see'' environment. The editor interface uses
the Lisp-subshell capabilities of the {\it GNU Emacs} editor which allows a
Lisp s-expression from a Lisp-mode buffer can be sent to {\it Winterp} via
simple commands. Note that {\it Winterp} is architecturally separate from
the {\it GNU Emacs} editor --- interfaces to other editors are possible,
but are not provided in the standard {\it Winterp} distribution.

{\it Winterp} is implemented as a Lisp server. {\it Winterp's} clients are
an editor such as {\it GNU Emacs}, and any other program running on other
UN*X machines on a network. Such capabilities are extremely useful in
allowing remote procedure calls to a {\it Winterp}-based application, thus
enabling better tool integration --- different tools in one's environment
can easily communicate with an application built upon {\it Winterp}.  The
{\it Winterp} distribution contains a simple client program 'wl' that sends
the Lisp s-expression given on its command line to the Lisp server for
evaluation.

The Lisp interpreter in the alpha version of {\it Winterp} is based on ELI,
the {\bf E}mbedded {\bf L}isp {\bf I}nterpreter that came on the X11r3
``contrib'' distribution (in contrib/toolkits/andrew/overhead/eli). I had
originally planned to construct my own mini-Lisp interpreter based on ideas
from {\it GNU Emacs'} customization language. Fortunately, I came across
ELI and thus managed to avoid a major duplication of effort in the {\it
Strudel} project. Bob Glickstein of Carnegie Mellon University built ELI to
fulfill a need similar to that of the {\it Strudel} project -- to embed a
small lisp interpreter into a C program so that highly customizable
applications may be built. The version of ELI in {\it Winterp} has been
modified in a number of ways: all references to other portions of Andrew
were removed; Andrew's nonstandard "preferences" files were replaced with
the emerging standard of X11 resources; bugs were fixed; and new functions
added allowing data to be collected from UN*X files and subprocesses.

The alpha version of {\it Winterp}, based on X11r2 and the HP Xwidgets, has
been in use since 12/15/88. A beta version of {\it Winterp} is being worked
on right now.  The beta version is far more reliable than the alpha version
because it is based on X11r3, and will allow the use of the Motif widgets
as well as the public domain X11r3 HP Widgets.  Furthermore, the beta
version of Winterp will use an extended XLISP as it's built in mini-lisp
interpreter, which is a smaller, faster, more complete, more robust, and
better-established mini-lisp with a syntax that approximates that of common
lisp.  This {\it Winterp} will allows programmers to access to the
commonly-used Xtoolkit functionality, and all the HP/Motif Xwidget classes.

Further enhancements that may be added to {\it Winterp}, time permitting,
include (1) a facility that will allow you to point at a {\it Winterp}
widget and interactively edit it's resources through a browser interface;
(2), a symbolic state transition machine that should make the design of
event driven applications easier, more expressive, and more modular. With
some simpce"builder-like" enhancements, {\it Winterp} could even be turned
into a Unix/X11 "Hypercard", using the mini-lisp instead of hypertalk.

\pagebreak
\section*{{\it Winterp} Example Program 1 --- A bitmap browser}
\begin{small}
\begin{verbatim}
;; This function will put up a two column scrollable r/c widget. the static
;; text widgets on the left column show the name of the bitmap file in the
;; given bitmap directory <dir>. The static raster widgets in the right column
;; show the actual bitmap. Mousing the bitmap will cause it to become the
;; root window pattern.
;;
;; usage: (browse-bitmap-directory "/usr/local/mayer/src/bitmaps")
;;

(defun browse-bitmap-directory (dir)
  (progn
    (setq top_w (XT_CREATE_APPLICATION_SHELL "top" TOP_LEVEL_SHELL_WIDGET_CLASS nil))

    (setq rc_w (XT_CREATE_MANAGED_WIDGET "rc" XW_ROW_COL_WIDGET_CLASS 
                                         (XT_CREATE_MANAGED_WIDGET 
                                          "scroller" 
                                          XW_SWINDOW_WIDGET_CLASS 
                                          top_w nil
                                          )
                                         '(("hSpace" 2)
                                           ("vSpace" 2)
                                           ("columns" 2)
                                           ("layoutType" 0) ;XwREQUESTED_COLUMNS
                                           ("forceSize" 1)
                                           ("singleRow" 0)
                                           ("mode" 0))))

    (do*
     (                                  ;initialize do-loop variables and set up incrementors
      (fp (popen (strcat "/bin/ls " dir) "r"))
      (line (fgets fp) (fgets fp))
      )
     (                                  ;test and exit
      (null line) 
      (progn
        (xt_realize_widget top_w)
        (pclose fp)))
                                        ;body
     (progn
       (xt_create_managed_widget "stext" XW_STATIC_TEXT_WIDGET_CLASS rc_w
                                 (list (list "string" line)))
       (xt_add_callback
        (xt_create_managed_widget "sraster" XW_SRASTER_WIDGET_CLASS rc_w
                                  (list (list "rasterImage" 
                                              (get_ximage_from_file
                                               (strcat dir "/" line)
                                               "black" "white"))))
        "select"
        (list 'system (strcat "xsetroot -bitmap " dir "/" line " -fg Black -bg DimGray"))
        )
       )
     )
    )
  )
\end{verbatim}
\end{small}
\section* {{\it Winterp} Example Program 2 --- using Lisp callbacks.}
\begin{small}
\begin{verbatim}
;;
;; This fn puts up a static text widget which inverts its foreground and
;; background colors every time it is selected. 
;;
(defun make-toggle-text (parent_w text)
  (let*
      ((st_w 
        (xt_create_managed_widget "c3" XW_STATIC_TEXT_WIDGET_CLASS parent_w
                                  (list
                                   (list "string" text)
                                   '("traversalType" 1)
                                   '("highlightThickness" 5)
                                   '("highlightTile" 8))))
       )
    (xt_add_callback st_w "select"
                     '(let ((fg-bg (xt_get_values CALLBACK_WIDGET 
                                                  '(("foreground" integer)
                                                    ("background" integer))))
                            )
                        (xt_set_values CALLBACK_WIDGET 
                                       (list 
                                        (list "foreground" (car (cdr fg-bg)))
                                        (list "background" (car fg-bg))))))
    )
  )

;;
;; this puts up a 10 by 10 array of toggling text widgets in a scrolled row
;; column window
;;
(let* 
    (
     (top_w 
      (xt_create_application_shell "top" TOP_LEVEL_SHELL_WIDGET_CLASS nil))
     (scroller_w
      (xt_create_managed_widget "scroller" XW_SWINDOW_WIDGET_CLASS top_w nil))
     (rc_w 
      (xt_create_managed_widget "rc" XW_ROW_COL_WIDGET_CLASS scroller_w 
                                '(("hSpace" 2)
                                  ("vSpace" 2)
                                  ("columns" 10)
                                  ("layoutType" 0) ;XwREQUESTED_COLUMNS
                                  ("forceSize" 1)
                                  ("singleRow" 0)
                                  ("mode" 0))))
     )

  (do*
   ((i 0 (+ i 1))
    )
   ((equal i 100)
    (xt_realize_widget top_w)
    )
   (make-toggle-text rc_w  (int-to-str i))
   )
  )
\end{verbatim}
\end{small}
\end {document}

-------------------------------------------------------------------------------
	    Niels Mayer -- hplabs!mayer -- ·····@hplabs.hp.com
		  Human-Computer Interaction Department
		       Hewlett-Packard Laboratories
			      Palo Alto, CA.
				   *