home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / Programming / Source / winterp-1.13 / doc / papers / winterp.ms < prev    next >
Encoding:
Text File  |  1991-10-06  |  113.3 KB  |  2,533 lines

  1. .RP no
  2. .\"-*-nroff-*-
  3. .\"##############################################################################
  4. .\"
  5. .\" File:         winterp.ms
  6. .\" RCS:          $Header: $
  7. .\" Description:  WINTERP paper...
  8. .\"          Translated from LaTeX to braindamaged 'troff -ms' format
  9. .\"               via "typesetting by example" based on the formatting of
  10. .\"               /nfs/X11r4/mit/doc/config/usenixws/paper.ms and
  11. .\"          /nfs/X11r4/mit/doc/tutorials/HelloWorld/xhw.ms
  12. .\" Author:       Niels Mayer, HPLabs
  13. .\" Created:
  14. .\" Modified:
  15. .\" Language:     rtroff -ms
  16. .\"          nroff -ms -Tlp winterp.ms | lp -oduplex
  17. .\" Package:      N/A
  18. .\" Status:       X11r5 contrib tape
  19.  
  20. .\" WINTERP Copyright 1989, 1990, 1991 Hewlett-Packard Company (by Niels Mayer).
  21. .\" XLISP version 2.1, Copyright (c) 1989, by David Betz.
  22. .\"
  23. .\" Permission to use, copy, modify, distribute, and sell this software and
  24. .\" documentation for any purpose is hereby granted without fee, provided that
  25. .\" the above copyright notice appear in all copies and that both that copyright
  26. .\" notice and this permission notice appear in supporting documentation, and that
  27. .\" the name of Hewlett-Packard, Niels Mayer, and David Betz not be used in
  28. .\" advertising or publicity pertaining to distribution of the software and
  29. .\" documentation without specific, written prior permission. Hewlett-Packard,
  30. .\" Niels Mayer, and David Betz make no representations about the suitability of
  31. .\" this software and documentation for any purpose. It is provided "as is"
  32. .\" without express or implied warranty.
  33. .\"
  34. .\" HEWLETT-PACKARD AND DAVID BETZ DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  35. .\" SOFTWARE AND DOCUMENTATION, INCLUDING ALL IMPLIED WARRANTIES OF
  36. .\" MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL HEWLETT-PACKARD, NIELS
  37. .\" MAYER, NOR DAVID BETZ BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
  38. .\" DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  39. .\" PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  40. .\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
  41. .\" THIS SOFTWARE AND DOCUMENTATION.
  42. .\"
  43. .\"##############################################################################
  44. .\" macros ripped off from Rosenthal and Lemke's paper
  45. .\.EQ
  46. .\delim $$
  47. .\.EN
  48. .ds CH
  49. .de Ip
  50. .IP \(bu 3
  51. ..
  52. .de Qp
  53. .nr PS -2
  54. .nr VS -2
  55. .QP
  56. ..
  57. .de Qe
  58. .nr PS +2
  59. .nr VS +2
  60. ..
  61. .de RQ
  62. .br
  63. .di
  64. .nr NF 0
  65. .if \\n(dn-\\n(.t .nr NF 1
  66. .if \\n(TC .nr NF 1
  67. .if !\\n(NF .if \\n(TB .nr TB 0
  68. .nf
  69. .rs
  70. .nr TC 5
  71. .in 0
  72. .ls 1
  73. .if !\\n(TB \{\
  74. .    ev
  75. .    br
  76. .    ev 2
  77. .    KK
  78. .\}
  79. .ls
  80. .ce 0
  81. .if !\\n(TB .rm KK
  82. .if \\n(TB .da KJ
  83. .if \\n(TB \!.KD \\n(dn
  84. .if \\n(TB .KK
  85. .if \\n(TB .di
  86. .nr TC \\n(TB
  87. .if \\n(KN .fi
  88. .in
  89. .ev
  90. ..
  91. .\"    These macros should select a typewriter font if you have one.
  92. .de LS
  93. .KS
  94. .LD
  95. .ft CW
  96. .ta .6i 1.2i 1.8i 2.4i 3i 3.6i 4.2i
  97. ..
  98. .de LE
  99. .ft P
  100. .DE
  101. .KE
  102. ..
  103. .de Ls
  104. .nr PS -4
  105. .nr VS -6
  106. .LS
  107. ..
  108. .de Le
  109. .LE
  110. .nr PS +4
  111. .nr VS +6
  112. .LP
  113. ..
  114. .nr PO 1.25i
  115. .OF "' '% '"
  116. .EF "' '% '"
  117. .ND
  118. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  119. .\"TITLE
  120. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  121. .TL
  122. The WINTERP Widget INTERPreter \*- An application prototyping and
  123. extension environment for OSF/Motif.
  124. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  125. .\"AUTHOR
  126. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  127. .AU
  128. Niels P. Mayer (mayer@hplabs.hp.com)
  129. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  130. .\"AUTHOR's INSTITUTION
  131. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  132. .AI
  133. Hewlett-Packard Laboratories
  134. Human-Computer Interaction Department
  135. 1501 Page Mill Road
  136. Palo Alto, CA. 94304-1126
  137. USA
  138. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  139. .\"ABSTRACT
  140. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  141. .AB
  142. .LP
  143. \fIWinterp\fP is an interactive, language-based user-interface and
  144. application-construction environment enabling rapid prototyping of
  145. applications with graphical user interfaces based on the OSF/Motif UI
  146. Toolkit. \fIWinterp\fP also serves as a customization environment for
  147. delivered applications by providing a real programming language as an
  148. extension language. Many existing user-interface languages only have the
  149. expressive power to describe static layout of user interface forms; by
  150. using a high-level language for extensions and prototyping, \fIWinterp\fP
  151. also handles the dynamic aspects of UI presentation, e.g. the use of direct
  152. manipulation, browsers, and dialog.  \fIWinterp\fP makes rapid prototyping
  153. possible because its language is based on an interpreter, thereby enabling
  154. interactive construction of application functionality and giving immediate
  155. feedback on incremental changes.
  156. .LP
  157. \fIWinterp\fP's language is based on David Betz's public domain \fIXlisp\fP
  158. interpreter which features a subset of Common Lisp's functionality. The
  159. language is extensible, permitting new Lisp primitives to be added in the C
  160. language and allowing hybrid implementations constructed from interpreted
  161. Lisp and compiled C. Hybrid implementation gives \fIWinterp\fP-based
  162. applications the successful extension and rapid-prototyping capabilities of
  163. Lisp-based environments, while delivering the multiprocessing performance
  164. of C applications running on personal \fIUnix\fP workstations.
  165. .AE
  166. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  167. .\"section{}
  168. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  169. .NH 1
  170. Introduction
  171. .LP
  172. \fIWinterp\fP\**
  173. .FS
  174. \fIWinterp\fP is pronounced WIN-TERP, not
  175. WINTER-P.
  176. .FE
  177. is a \fBW\fPidget\**
  178. .FS
  179. A Widget is a graphical object that can be manipulated by mouse or keyboard
  180. input: examples of OSF/Motif widgets include scrollbars, pushbuttons,
  181. menus, text editors, etc.
  182. .FE
  183. \fBInterp\fPreter, an application development environment enabling rapid
  184. prototyping of graphical user-interfaces (UI) through the interactive
  185. programmatic manipulation of user interface objects and their attached
  186. actions. The interpreter, based on David Betz's \fIXlisp\fP [Betz89],
  187. provides an interface to the X11 toolkit Intrinsics (Xt), the OSF/Motif\**
  188. .FS
  189. Motif is a trademark of the Open Software Foundation.
  190. .FE
  191. widget set [OSF90] [Young90], primitives for collecting data from
  192. \fIUnix\fP\**
  193. .FS
  194. \fIUnix\fP is a trademark of American Telephone and Telegraph, Bell
  195. Laboratories.
  196. .FE
  197. processes, and facilities for interacting with other \fIUnix\fP processes.
  198. These features enable \fIWinterp\fP to support rapid prototyping of
  199. applications using multi-window graphical user-interfaces by allowing the
  200. user to interactively change both the appearance and functionality.
  201. .LP
  202. In addition to prototyping applications and experimenting with UI layout,
  203. \fIWinterp\fP may be embedded in applications requiring an extension
  204. language for customization or systems integration. Traditional X
  205. applications based on the Xtoolkit allow users to alter X resources to
  206. tailor application UI parameters such as fonts, colors, window sizes, etc.
  207. Motif's User Interface Language (\fIUIL\fP) [OSF90] [Bourne90] extends that
  208. level of customization by allowing the layout of the application's UI
  209. widgets to be tailored. As a language, \fIUIL\fP has the expressive power
  210. to describe the layout of static UI forms, but has none of the control flow
  211. and data handling constructs associated with real programming languages.  A
  212. programming language is needed to support the full range of requirements
  213. needed by User Interface Management Systems (UIMS) [Myers89]; to describe
  214. dynamic, data-driven UI forms, and to model user/application dialog.
  215. \fIWinterp\fP provides such an embedded programming language allowing
  216. tailoring of the UI's static and dynamic layout, UI-to-application dialog,
  217. and application functionality.
  218. .LP
  219. \fIWinterp\fP is thus an interactive \*Qlanguage based\*U user-interface
  220. development environment (UIDE). \fIWinterp\fP is not a UIMS \*- it
  221. provides UI primitives and a high-level language to support a wide variety
  222. of UI-to-application partitionings\**
  223. .FS
  224. Examples of such UI-to-application partitioning that can be implemented in
  225. \fIWinterp\fP include Smalltalk's Model-View-Controller paradigm, state
  226. transition machines, event grammars, etc.
  227. .FE
  228. that are characteristic of the UIMS approach. \fIWinterp\fP is designed to
  229. allow the programmer to \fIevolve\fP a suitable UIMS model that is
  230. appropriate for extending and customizing a particular application.
  231. \fIWinterp\fP is also designed to support direct manipulation UI building.
  232. The current version contains a useful primitive for \*Qdirect manipulation
  233. programming\*U with widget-objects.
  234. .LP
  235. An environment similar to \fIWinterp\fP's already exists in the \fIGNU
  236. Emacs\fP [Stallman87] text editor \*- in fact, \fIWinterp\fP is strongly
  237. influenced by \fIGNU Emacs\fP' successful design. In \fIGNU Emacs\fP, a
  238. mini-Lisp interpreter is used to extend the editor to provide text-browser
  239. style interfaces to a number of \fIUnix\fP applications (e.g.  e-mail user
  240. agents, directory browsers, debuggers, etc). Whereas \fIEmacs-Lisp\fP
  241. enables programmers to create new applications by tying together
  242. C-implemented primitives that operate on first-class types providing
  243. textual interfaces (buffers, windows), \fIWinterp-Lisp\fP ties together
  244. operations on graphical user-interface objects implemented by the Motif
  245. widgets. Both application construction environments achieve the
  246. flexibility, expressiveness, and rapid-prototyping capabilities common for
  247. systems implemented in Lisp, while still attaining the speed of execution
  248. and (relatively) small size associated with C-implemented applications.
  249. .LP
  250. \fIWinterp\fP was initially made public on the MIT X Consortium's X11r4
  251. \*Qcontrib\*U distribution; up-to-date versions are available via anonymous
  252. ftp from a number of Internet sites including export.lcs.mit.edu.
  253. \fIWinterp\fP is quite robust and bug-free, it is in active use by a number
  254. of research projects at HP Labs, and is also being used by companies and
  255. universities worldwide. \fIWinterp\fP was designed to be portable \*- it
  256. runs on \*Qstandards-oriented\*U \fIUnix\fP platforms without porting. A
  257. number of improvements have already been contributed by \fIWinterp\fP's
  258. user group since \fIWinterp\fP's initial public release; submitted
  259. improvements will be included in publicly available updates of
  260. \fIWinterp\fP.
  261. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  262. .\"section{}
  263. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  264. .NH 1
  265. Background
  266. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  267. .\"subsection{}
  268. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  269. .NH 2
  270. Design Constraints
  271. .LP
  272. \fIWinterp\fP was created as the platform on top of which the
  273. \*QCollaborative Interaction Tools\*U project at Hewlett-Packard Laboratories
  274. is developing \fIStrudel\fP [Shepherd90], an extensible
  275. electronic conversation toolkit enabling computer supported cooperative
  276. work. The design of \fIStrudel\fP has resulted in strong constraints on
  277. \fIWinterp\fP: for development, we required an environment supporting rapid
  278. prototyping and exploratory programming; for delivery to end-users,
  279. \fIStrudel\fP had to allow extensive customization in order to fit in to a
  280. particular group's computer-based work environment; finally, to allow us to
  281. validate our groupware design, the platform must be acceptable to \*Qearly
  282. adopters\*U wanting to use \fIStrudel\fP in real work situations.  Unlike
  283. traditional software, groupware cannot be evaluated by individual
  284. beta-testers \*- the power of groupware comes from having a number of
  285. people using it to work together.  In order to gain this wide experimental
  286. user base, we found it necessary to place additional constraints on the
  287. platform: it needs to be freely distributable, easy to install, and it must
  288. have good performance when running alongside other applications on a
  289. standard \fIUnix\fP workstation. In this paper, we discuss the design of
  290. \fIWinterp\fP with such constraints in mind, pointing out the advantages of
  291. \fIWinterp\fP as a general platform for application prototyping and
  292. delivery.
  293. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  294. .\"subsection{}
  295. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  296. .NH 2
  297. Strudel \*- A Customizable Application Based on Winterp
  298. .LP
  299. \fIStrudel\fP is a generic framework for interlinking group e-mail
  300. conversations and group or individual tasks.  Strudel consists of
  301. \fIWinterp\fP's interpreter and user interface primitives, combined with
  302. primitives implementing a distributed hypertext-like system using
  303. replicated e-mail messages as nodes, and high-level operators that will
  304. allow the nodes to be viewed-by and linked-to a variety of browsers (e.g.
  305. conversation presenters, task and to-do lists, calendars).  \fIStrudel\fP's
  306. flexible architecture makes it akin to a \*Q\fIGNU Emacs\fP for groupware\*U
  307. \*- the specialized primitives permit the system to be customized to
  308. support special modes of communication for particular workgroup
  309. environments much in the same way that \fIGNU Emacs\fP Lisp is used to
  310. customize the editor to support special editing modes for particular
  311. programming environments.
  312. .LP
  313. Users will be able to choose from a library of e-mail forms that are
  314. designed to track specific types of conversations \*- scheduling meetings
  315. and resources, software defect tracking, group design deliberation, etc.
  316. Workgroups can extend the library of forms to help capture and manage
  317. recurrent conversations that are not covered by \fIStrudel\fP's standard
  318. forms library. The kinds of interface customizations can range from adding
  319. new menu entries for often-used functions to designing new e-mail forms and
  320. associated browsers for their data.  We are working closely with a few HP
  321. entities to provide \fIWinterp\fP-Lisp \*Qscripts\*U\**
  322. .FS
  323. In analogy to \*Qshell scripts\*U running under \fIUnix\fP shell programs.
  324. .FE
  325. implementing specific scenarios involving conversations arising in the
  326. domain of team software and hardware production: group design deliberation,
  327. software maintenance, defect tracking, etc. See Figure 1 for a snapshot of
  328. the \fIStrudel\fP prototype; for further information on \fIStrudel\fP, see
  329. [Shepherd90].
  330. .LP
  331. Research related to \fIStrudel\fP includes speech act and dialog theory
  332. [Searle76] [Reichman85], commitment-based software frameworks [Fikes82]
  333. [Winograd86], \fIThe Coordinator\fP\**
  334. .FS
  335. \fIThe Coordinator\fP is a registered trademark of Action Technologies,
  336. Inc.
  337. .FE
  338. and the language/action perspective [Fikes82] [Winograd87], e-mail message
  339. filtering [Rose86] [Borenstein88] semi-structured message systems
  340. [Malone86], the Object-Lens [Lai88], conversation management [Comer86]
  341. [Dollimore89] [Sulonen90] [Kaplan90], office procedure and coordination
  342. models [Holt81], collaborative hypertext systems [Trigg86], and Issue-Based
  343. Information Systems [Conk87].
  344. .\"%%%%%%%%%%%%%
  345. .\"begin{figure}
  346. .\"label{strudel_snapshot}
  347. .\"%%%%%%%%%%%%%
  348. .KF
  349. .sp 8.25i
  350. .sp
  351. .QP
  352. Figure 1. The \fIStrudel\fP prototype, showing the e-mail browser and some
  353. active e-mail forms used in conversations arising during team software
  354. production.
  355. .\"%%%%%%%%%%%%%
  356. .\"end{figure}
  357. .\"%%%%%%%%%%%%%
  358. .KE
  359. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  360. .\"section{}
  361. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  362. .NH 1
  363. Interpreting User Interfaces?
  364. .LP
  365. \fIWinterp\fP differs from many other UI languages in that it is
  366. interpretive rather than compiled. We believe that interpretation of UI
  367. specifications offers a number of practical advantages over the compilation
  368. approach taken by \fIUIL\fP, traditional C programming with the Xtoolkit,
  369. or compiled UIMSs.
  370. .LP
  371. Neither traditional C Xtoolkit applications, nor \fIUIL\fP applications
  372. take advantage of the interpretive nature of the Xtoolkit. When programming
  373. in C, one is forced to go through tedious edit/compile/test cycles even for
  374. trivial program changes. The Xtoolkit provides a resource manager (Xrm)
  375. that allows one to shorten the edit/compile/test cycle for simple
  376. application tailoring such as selecting fonts, colors, label names, or
  377. choosing from an enumerated set of application-defined customization
  378. choices. This is implemented by having the application load
  379. (non-interactive interpretation) the appropriate resource settings from the
  380. resource data base at application initialization time.  While this
  381. mechanism eliminates a compilation stage for a number of simple
  382. customizations, the result is still a cycle consisting of repeated edits of
  383. the resource database followed by running the application to test the
  384. results.  \fIUIL\fP expands on the type of customizations possible via Xrm
  385. by reading a compiled, structured description of the widget hierarchy,
  386. along with associated resources and callback names.  Rather than
  387. \*Qinterpreting\*U the data from a resource database, as is done with Xrm,
  388. \fIUIL\fP uses an additional compilation stage. While \fIUIL\fP compilation
  389. is quicker than C compilation, it still makes rapid prototyping impractical
  390. because of the edit/compile/test cycle.
  391. .LP
  392. In contrast to the batch approach provided by \fIUIL\fP or C, \fIWinterp\fP
  393. allows interactive programmatic manipulation of the UI via a
  394. message-passing mechanism that takes full advantage of the interpretive,
  395. object-oriented nature of the Xtoolkit. The Motif widgets are
  396. \*Qinterpretive\*U in that one can give programmatic commands to the Motif
  397. library to create new widgets, and the Xt intrinsics will create the new
  398. widget on-the-fly.  One can also send messages to created widget objects
  399. via the \*Qmethods\*U implemented by widget-class specific functions in Motif
  400. or the Xt Intrinsics (such as \f(CWXtSetValues()\fP) \*- the effects of
  401. these messages are interpreted by the toolkit and result in an eventual
  402. updating of the graphics and actions associated with the widget.
  403. .LP
  404. \fIWinterp\fP provides access to the \*Qinterpretive\*U nature of the Motif
  405. widgets through its built-in \fIXlisp\fP interpreter. The interpretive
  406. approach enables rapid prototyping because one receives immediate feedback
  407. on changes \*- one can incrementally build up a user interface,
  408. piece-by-piece, and one can play \*Qwhat if\*U games by modifying both the
  409. layout and functionality of the application. \fIWinterp\fP even includes a
  410. \*Qdirect manipulation\*U primitive that allows changing widget resources,
  411. callbacks and event-handlers by designating a widget with the mouse. One
  412. need not rerun or recompile the application in order to see the results of
  413. a change to a \fIUIL\fP or X resource \*- with \fIWinterp\fP, incremental
  414. changes to an application can be tested interactively.
  415. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  416. .\"section{}
  417. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  418. .NH 1
  419. The Role of a Programming Language in a UIMS.
  420. .LP
  421. The UIMS approach requires the power of an embedded programming language to
  422. allow abstractions to be derived from complex changes in application state
  423. and data. Such abstractions provide the separation between application
  424. semantics and the user-interface that UIMSs strive for. This separation is
  425. really nothing other than an extension of the notion of encapsulation to
  426. the architecture of applications based on graphical user-interfaces. Such
  427. encapsulation makes it easier to experiment with the \*Qlook and feel\*U of
  428. an application without side-effects, enabling designers to more easily
  429. refine their applications via rapid prototyping. A well architected system
  430. will also provide end-users with a means of customizing the UI without
  431. adverse effects on the application's functionality. By embedding full
  432. programming language capabilities in a user-interface language,
  433. \fIWinterp\fP allows designers to develop the appropriate language-based UI
  434. abstractions for the particular kind of application and extension
  435. architecture.
  436. .LP
  437. In contrast to \fIWinterp\fP, many of the problems in developing and
  438. extending applications based on Motif's User Interface Language (\fIUIL\fP)
  439. stem from the lack of full programming language support \*- \fIUIL\fP only
  440. provides a language supporting a module system, a static widget description
  441. language, and simple expression arithmetic.  In non-trivial applications,
  442. one must write, compile, and link C code which calls hooks into \fIUIL\fP
  443. in order to control dynamic dialog components that make up the UI of a real
  444. application. Such an architecture imposes strong constraints on the amount
  445. of customization possible without modifying the C source code. Ultimately,
  446. the lack of a programming language in \fIUIL\fP limits the usefulness of
  447. separating the UI description from the application's functionality:
  448. .\"-----------------
  449. .\"begin{quotation}
  450. .\"-----------------
  451. .QP
  452. For a complex interface, fetching widgets from UID\**
  453. .FS
  454. A UID file is a User Interface Description file that is produced by
  455. compiling a UIL file.
  456. .FE
  457. files won't satisfy all of a programmer's needs. Thus, XUI comes with a
  458. complete C language library of calls through which the DECwindows\**
  459. .FS
  460. DECwindows is a trademark of Digital Equipment Corporation.
  461. .FE
  462. widgets can be defined and controlled. These calls are useful, but by using
  463. the C language libraries, the correspondence between program structure and
  464. program function given by UIL may be lost. [Bourne90 \*- p. 40]\**
  465. .FS
  466. This quote from [Bourne90 \*- p. 40] comes from an article on programming
  467. with DECwindows, focusing on the use of \fIUIL\fP.  Although the \fIUIL\fP
  468. in DECwindows is not the same as Motif's \fIUIL\fP, both versions provide
  469. essentially the same functionality.
  470. .FE
  471. .\"---------------
  472. .\"end{quotation}
  473. .\"---------------
  474. .LP
  475. With \fIWinterp\fP, programmers can use language constructs to represent
  476. and manipulate the state of the application and the UI.  \fIWinterp\fP
  477. makes an effective prototyping environment because one can use \fIXlisp\fP
  478. to build the user interface, prototype the \*Qdialog\*U aspects of the
  479. working application, and use \fIXlisp\fP's object system to evolve
  480. language-based abstractions. Depending on the kind of UI style and
  481. application architecture, one may use \fIWinterp\fP's features to
  482. encapsulate and separate application functionality from the UI representing
  483. that functionality; alternately one may find it advantageous to build
  484. higher level UI constructs which use class-inheritance to specialize
  485. generic UI objects provided by Motif into application-specific objects.
  486. Because \fIWinterp\fP's language-base is interpretive, it can be used to
  487. describe dynamic, data-driven user-interfaces such as those found in
  488. \fIStrudel\fP.
  489. .LP
  490. Traditional UIMSs are based on an abstract model for separating application
  491. functionality from its associated user interface \*- e.g Smalltalk's Model
  492. View Controller, the Seeheim UIMS model, transition networks, event
  493. grammars, etc. [Myers89]. \fIWinterp\fP is not a UIMS; it provides little
  494. policy for separating the application semantics from the UI.  However,
  495. \fIWinterp\fP's language base enables the design and development of a
  496. variety of UI-to-application modularization policies.
  497. .LP
  498. The lack of a particular UIMS policy in \fIWinterp\fP is in accordance with
  499. the current view that traditional UIMS models are problematic; that it is
  500. difficult to separate UI from application semantics in a general way:
  501. .\"-----------------
  502. .\"begin{quotation}
  503. .\"-----------------
  504. .QP
  505.  ... in recent years, as UIMSs are built to handle more sophisticated user
  506. interfaces with direct manipulation ... there has been concern that the
  507. separation between user interface and application raises more problems than
  508. it solves. Perhaps the prototypical problem arising from this separation is
  509. that of whether to handle the semantics of an interaction in the UIMS or
  510. the application program. For example, feedback is a task typically handled
  511. by the UIMS, but the semantically rich feedback required by direct
  512. manipulation user interfaces (e.g. highlighting while moving the mouse) is
  513. difficult to do without involving the underlying application. If the
  514. application and the UIMS thus need to frequently interact, their separation
  515. becomes a hindrance rather than a help.... [Rosenberg88]
  516. .\"---------------
  517. .\"end{quotation}
  518. .\"---------------
  519. .LP
  520. In developing applications with \fIWinterp\fP we have found that for
  521. certain classes of applications, such as instrumentation controllers, a
  522. simple recursive, event-driven state machine\**
  523. .FS
  524. Lisp's list and symbol manipulation features make it especially easy to
  525. implement such state machines.
  526. .FE
  527. is an appropriate abstraction separating application semantics from the UI.
  528. In dynamic, data-driven UI's (browsers, graph editors, CAD drawing tools),
  529. separating the UI from the application objects has proven to create messy
  530. architectures; a better solution is to use Motif widgets subclassed\**
  531. .FS
  532. Note that \fIWinterp\fP-Lisp allows subclassing of widgets without
  533. resorting to the complexities and tedium of widget subclassing in C with
  534. the X toolkit.
  535. .FE
  536. into application-specific UI objects handling their own state and actions.
  537. We believe that it is best to give programmers the full capabilities of the
  538. Motif toolkit, augmented by \fIWinterp\fP's interpretive, language-based
  539. interface.  Application programmers can use these features to evolve the
  540. appropriate UIMS to do the job.
  541. .LP
  542. \fIWinterp\fP's policy-free UIMS architecture makes \fIWinterp\fP-based
  543. applications far more customizable than applications based on UIL or the
  544. Widget Creation Library (WCL). Both UIL and WCL enforce an architecture
  545. which strongly separates the dynamics of the application from the static
  546. presentation of the panels comprising the application's UI. Such an
  547. architecture will only allow trivial customization of applications
  548. employing state-based dynamics.  A simple example of such a problem: one
  549. wants to add a button to an application that does the same thing as a
  550. menu-entry (because one selects this entry often).  The application
  551. designer had the menu entry \*Qgrey out\*U to indicate that it is not a
  552. suitable choice given a particular application state. With UIL or WCL,
  553. special code must be written at the C-language level to handle such
  554. state-based changes; this code is tied to assumptions about the static
  555. interface described by the user interface language. In the case of the
  556. customization just described, the appropriate state-based inactivation of
  557. the button may not occur \*- this can result in the application entering a
  558. disallowed state if the user selects it without knowing the choice was
  559. invalid.  Even if the error can be trapped in the button's callback, the
  560. user is not being given the kind of state-based feedback that is the
  561. hallmark of good UI design.  The problem here is that application state
  562. cannot be described in the UI language. The lack of programming language
  563. features make it impossible to propagate even the simplest state changes to
  564. state-dependent UI components and this creates an inelegant architecture
  565. for both application designers and application customizers.
  566. .LP
  567. UIL and WCL force application architectures which hard-code application
  568. dialog in C for certain expected UI presentations described in the
  569. user-interface language. The assumption, that dialog and presentation are
  570. separate, limits the kinds of UI customizations that are possible to
  571. trivial layout modifications. Applications use dialog to prompt the user
  572. for information needed to complete a previously executed command.  Dialog
  573. is also used to limit the amount of screen real estate used by an
  574. application \*- selection choices and input fields that are not of primary
  575. concern are hidden until needed. Personal preference, screen real estate
  576. usage and application usage patterns should dictate whether one elects to
  577. select a choice directly, or via dialog. Thus, the customization of
  578. dialog versus direct-presentation may be a useful feature for certain
  579. applications. For example, some electronic mail (e-mail) interfaces support
  580. multiple folders for filing/copying information that is received in one's
  581. \*Qin-box\*U. Some e-mail UI's will use dialog for folder selection when
  582. a \*Qcopy\*U or \*Qmove\*U operation is invoked. People doing a lot of
  583. filing may prefer to have direct control over the selected folder\**,
  584. .FS
  585. An example of a e-mail UI that does not utilize dialog for folder selection
  586. is the MIT X Consortium client \fIxmh\fP. A common complaint about
  587. \fIxmh\fP is that the folder selection area takes up too much real estate.
  588. This is yet another example where dialog versus presentation
  589. customization would solve an existing problem.
  590. .FE
  591. rather than having the system prompt for a folder each time. With UIL or
  592. WCL, customization of the tradeoffs between presentation and dialog is not
  593. possible within the user interface language due to lack of programming
  594. language constructs. With \fIWinterp\fP, such customizations are possible.
  595. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  596. .\"section{}
  597. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  598. .NH 1
  599. Advantages of Lisp as a UIMS Language
  600. .LP
  601. Programming language features are present in UIMSs such as \fIOpen
  602. Dialogue\fP [Schulert88], and \fISerpent\fP [SEI89].  \fIWinterp\fP differs
  603. from such UIMSs because it does not attempt to define a new user interface
  604. language into which programming language constructs need to be introduced.
  605. Rather, \fIWinterp\fP uses a subset of a standard language \*- Common Lisp
  606. \*- and extends this language to describe UI layout and dialog. The choice
  607. of Lisp as the widget layout and prototyping language in \fIWinterp\fP
  608. provides important advantages:
  609. .\"---------------
  610. .\"begin{itemize}
  611. .\"---------------
  612. .RS .5in
  613. .\"-----
  614. .\"\item
  615. .\"-----
  616. .Ip
  617. Highly expressive:
  618. .LP
  619. Lisp allows new functionality to be expressed quickly using less code than
  620. an equivalent C program because it is a high-level language featuring
  621. symbol and list manipulation [Creech87b] [Creech87a], first class
  622. procedures [Creech87b] [Creech87a], object-oriented programming [Betz89],
  623. and automatic memory management via garbage collection [Creech87b]
  624. [Creech87a]. Lisp's features for manipulating lists and trees of arbitrary
  625. objects are used to represent UI layout structures and \fIWinterp\fP
  626. introduces new objects (widget-objects) to represent UI components.
  627. .\"-----
  628. .\"\item
  629. .\"-----
  630. .Ip
  631. Designed to be interactive, interpretive:
  632. .LP
  633. Lisp makes a good environment to drive an interactive interface to the
  634. Motif widgets because the language was designed to be interpreted.
  635. Interpretation can also be accomplished in traditionally compiled languages
  636. (such as C), but in Lisp, small one-off changes can be made with reduced
  637. effort due to dynamic typing. Such changes are typical in rapid
  638. prototyping.
  639. .LP
  640. Lisp's interactive error handling and debugging allows for programming
  641. errors to be caught, debugged, and fixed interactively. Debugging occurs
  642. within the environment that caused the error to arise, and the full power
  643. of the language interpreter is available to allow programmers to inspect,
  644. alter, or fix the environment. After fixing a bug, one may be able to
  645. resume execution of ones code from the point that caused the error without
  646. having to restart the program. These debugging features are essential for
  647. rapid prototyping.
  648. .\"-----
  649. .\"\item
  650. .\"-----
  651. .Ip
  652. Code-Data equivalence:
  653. .LP
  654. Lisp data is represented in the same form as Lisp programs [Creech87b]
  655. [Creech87a], which means that programs can perform computations to
  656. create/alter data structures representing programs.  Such meta-programming
  657. allows the creation of high-level data-driven abstractions for user
  658. interfaces created programmatically via Motif and Xt Intrinsics calls.
  659. .LP
  660. \fIWinterp\fP-Lisp can thus be used to create dynamic widget layouts
  661. through computations that create and mutate data structures representing
  662. user-interfaces. For example, in our \fIStrudel\fP groupware toolkit,
  663. \fIWinterp\fP's interpreter and Motif UI primitives are used as a
  664. description language for creating and processing active/graphical forms.
  665. Such forms can be sent (as textual programs) through standard e-mail
  666. channels.  The receiving \fIStrudel\fP system interprets the message and
  667. displays a form containing a user interface built from arbitrary
  668. combinations of widgets and bitmaps. These \*Qforms\*U can even be whole
  669. user-interfaces and associated programs that can be passed around from
  670. user-to-user as Lisp \*Qcontinuations.\*U\**
  671. .FS
  672. One of our research issues is how to provide security for systems that
  673. \*Qopen\*U to programmatic manipulation from outside \*- they can easily be
  674. infected with viruses.
  675. .FE
  676. See Figure 1 for an example of a \fIStrudel\fP form.
  677. .\"-------------
  678. .\"end{itemize}
  679. .\"-------------
  680. .RE
  681. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  682. .\"section{}
  683. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  684. .NH 1
  685. Implementation Issues in Embedding a Lisp Interpreter
  686. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  687. .\"subsection{}
  688. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  689. .NH 2
  690. Problems with Traditional Lisp Systems
  691. .LP
  692. Despite its advantages, Lisp is traditionally associated with large, slow
  693. and expensive systems\**
  694. .FS
  695. One solution to the \*Qlarge\*U and \*Qslow\*U problems has been to create
  696. special operating systems and hardware for Lisp \*- Lisp machines.  Such
  697. specialized computers are being priced out of the market by general purpose
  698. \fIUnix\fP workstations using the X Window System and running software that
  699. is portable across a number of vendor platforms.
  700. .FE
  701. \*- Lisp's flexibility has its costs.  Attempts at building Lisp-based
  702. applications that are good citizens on \fIUnix\fP workstations have been
  703. problematic because systems such as Common Lisp (CL) create huge,
  704. resource-hungry processes that swap out all other applications and cause
  705. memory thrashing [Creech87b] [Creech87a].  This results in unacceptable
  706. overall system performance if the CL process is but one of many processes
  707. competing for resources on a \fIUnix\fP box.
  708. .LP
  709. While CL continues to be an excellent prototyping platform, few acceptable
  710. solutions to the \*Qdelivery problem\*U have been found for applications
  711. embedded in a CL environment. One unacceptably drastic solution is to
  712. recode the completed CL-based prototype into C \*- an approach often used
  713. to create deliverable versions of expert systems and other complex
  714. applications. This approach is time consuming, error prone, and changes the
  715. feel and the flexibility of the delivered application: applications
  716. prototyped with CL assume and make use of the underlying features of the
  717. Lisp system; these assumptions must be removed from the design or be
  718. recoded in the delivery language.
  719. .LP
  720. In the past, we have also experienced problems in interfacing large Common
  721. Lisp systems to other C-implemented libraries and low-level device drivers
  722. \*- the problem stems from the difficulties in importing, exporting and
  723. translating arbitrary Lisp data structures to/from the C level; problems
  724. also arise from the explicit control requirements of the CL interpreter's
  725. evaluator which make it difficult to interface to event-driven programs
  726. such as the X toolkit.
  727. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  728. .\"subsection{}
  729. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  730. .NH 2
  731. Solution: a Hybrid Implementation
  732. .LP
  733. Fortunately, another class of Lisp application has been successful in a
  734. general purpose computational environment \*- a hybrid architecture of
  735. Lisp and C giving the flexibility of a Lisp system while allowing delivery
  736. of a relatively small and efficient process. Under \fIUnix\fP, Richard
  737. Stallman has created a highly-customizable editor-based programming
  738. environment called \fIGNU Emacs\fP [Stallman87] \*- this is a system that
  739. delivers to the \fIUnix\fP user a text-editor oriented UI that is the
  740. foundation of the Lisp Machine programming environment. Under
  741. \fIMS-DOS\fP\**,
  742. .FS
  743. \fIMS-DOS\fP is a trademark of Microsoft Corporation.
  744. .FE
  745. successful programs like \fIAutoCAD\fP\**
  746. .FS
  747. \fIAutoCAD\fP is a trademark of Autodesk Corporation.
  748. .FE
  749. contain a Lisp customization language embedded in a CAD program.
  750. .LP
  751. The approach taken by such hybrid applications is that a small mini-Lisp
  752. interpreter serves to \*Qglue\*U together efficient C-implemented primitives
  753. that make up an application.  User-customization and prototyping under such
  754. a hybrid system amounts to using the Lisp interpreter to reconfigure
  755. C-implemented building blocks in order to change, modify, or improve the
  756. functionality of the system. Such an application architecture follows the
  757. \*Q80/20 heuristics\*U for program execution \*- low level routines that
  758. take up most of the computational resources are coded in C, and are
  759. therefore fast and efficient in memory use (no garbage collections caused
  760. by low-level code).  The Lisp interpreter is relatively slow in comparison
  761. to a compiled C program, but it only serves to flexibly glue together
  762. components of the \*Qouter loop\*U of a program. For an illustration of this
  763. hybrid architecture, see Figure 2.
  764. .LP
  765. \fIWinterp\fP solves the problems traditionally associated with Lisp
  766. delivery by using this hybrid approach \*- a small, fast, lightweight Lisp
  767. interpreter based on David Betz's \fIXlisp\fP serves as an interactive,
  768. configurable mechanism tying together high-level C-implemented
  769. application-specific primitives.  Because \fIXlisp\fP is implemented
  770. entirely in C, one can simply use \fIXlisp\fP's C library to directly
  771. recode any Lisp code into a C-implemented primitive.
  772. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  773. .\"subsection{}
  774. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  775. .NH 2
  776. Evolving from Prototype to Deliverable with Hybrid Programming
  777. .LP
  778. \fIWinterp\fP supports an evolutionary program lifecycle: \fIWinterp\fP
  779. application writers rapidly prototype new functionality by using the
  780. interpreter to interactively refine the layout, looks, and functionality of
  781. the application.  Once functionality has stabilized, a programmer can
  782. improve the application's efficiency by reimplementing the functionality in
  783. C while maintaining the same programmatic interface to the rest of the
  784. system. The new primitives will then serve as the building blocks for the
  785. next layer of prototyping and customization. The end result, if designed
  786. carefully, is a relatively small and fast application that provides the
  787. right set of building blocks and hooks to permit end-users to customize the
  788. look and feel of the application.
  789. .LP
  790. \fIWinterp\fP is also useful for rapid prototyping applications that do not
  791. need to be delivered with an embedded customization language. Systems with
  792. such delivery goals may still use the aforementioned application lifecycle.
  793. As the application matures and Lisp prototype code stabilizes, the program
  794. can gradually be recoded entirely into C. Eventually, this process will
  795. allow a standard C-implemented Motif program to be delivered.
  796. .LP
  797. Contrast this stepwise refinement from prototype to deliverable with the
  798. approach of throwing out the entire CL-based prototype and starting from
  799. scratch in a language like C or C++. The advantages of creating
  800. deliverables incrementally via hybrid programming are: (1) Existing
  801. regression tests may be applied to the deliverable under construction, such
  802. that the effects of each reimplementation can be tested; (2) Developers and
  803. alpha-testers can use the application being recoded for further development
  804. and further work, thereby checking the impact of the changes on the
  805. usability, customizability, and functionality of the application.
  806. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  807. .\"section{}
  808. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  809. .NH 1
  810. An Architecture for Extensible UIs and Applications
  811. .LP
  812. The architecture of an application built on top of \fIWinterp\fP allows for
  813. applications to be delivered with a variety of UI styles. Such
  814. customizability is important because it is difficult to please everyone
  815. with a single UI style, and because system designers cannot foresee all
  816. possible needs of all users. With \fIWinterp\fP, UI styles can be specified
  817. via \fIWinterp\fP-Lisp \*Qscripts\*U which are loaded into the application at
  818. run-time. Inexperienced users can customize the UI or application's
  819. functionality by using \*Qprogramming by example\*U based on existing
  820. scripts. Application \*Qgurus\*U may come up with new styles, merge features
  821. of existing styles, add shortcuts and accelerators, or come up with new
  822. functionality. Such customizations are often distributed to others within
  823. the organization. Extensible applications like AutoCAD and Hypercard\**
  824. .FS
  825. Hypercard is a trademark of Apple Computer.
  826. .FE
  827. have even created an \*Qaftermarket\*U of scripts that create new
  828. applications within the environment provided by the extensible application.
  829. .LP
  830. Figure 2 shows the architecture of an extensible application in which
  831. \fIWinterp\fP-Lisp serves as a customization script and \*Qglue language\*U
  832. between C-implemented application and user-interface primitives.
  833. .\"%%%%%%%%%%%%%
  834. .\"begin{figure}
  835. .\"label{winterp_cust_architecture}
  836. .\"%%%%%%%%%%%%%
  837. .KF
  838. .sp 2.5i
  839. .sp
  840. .CD
  841. Figure 2. Architecture of an extensible application based on \fIWinterp\fP.
  842. .DE
  843. .\"%%%%%%%%%%%%%
  844. .\"end{figure}
  845. .\"%%%%%%%%%%%%%
  846. .KE
  847. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  848. .\"section{}
  849. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  850. .NH 1
  851. Winterp Features
  852. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  853. .\"subsection{}
  854. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  855. .NH 2
  856. Xlisp
  857. .LP
  858. \fIWinterp\fP uses \fIXlisp\fP [Betz89] because it is reliable, small,
  859. fast, and free.  \fIXlisp\fP has been around since 1985, and has evolved
  860. considerably since it first appeared publicly. Because it has been in
  861. widespread use for some time, most bugs have been shaken out of the system.
  862. Also, the newsgroup comp.lang.lisp.x has been an effective public channel
  863. for exchanging information and patches.  \fIXlisp\fP was designed to be run
  864. on PCs; because it was designed with a limited environment in mind, it has
  865. turned out to be quite fast and memory-efficient while remaining portable
  866. across a variety of architectures ranging from 16 bit PC's to workstations.
  867. \fIXlisp\fP's simple object system has enabled an elegant interface to the
  868. object oriented structure of the Xtoolkit and the Motif widgets.  Finally,
  869. \fIXlisp\fP is free, thanks to the generosity of David Betz.
  870. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  871. .\"subsection{}
  872. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  873. .NH 2
  874. Motif Widgets are First-Class Objects
  875. .LP
  876. \fIWinterp\fP uses \fIXlisp\fP's Smalltalk-like object system [Betz89] as
  877. its interface to the class hierarchy of widgets provided by Motif.
  878. Specifically, each Motif widget class is represented by one or more object
  879. classes in \fIWinterp\fP.  A wide range of UI objects are provided. Simple
  880. widgets include text or pixmap labels, pushbuttons, toggle buttons as well
  881. as scrollbars and scale valuators. More complex widgets include a text
  882. editor, a file browser, and a list browser. Motif includes manager widgets
  883. that manage the geometries of other widgets via constraints, row/column
  884. placement, or menu layout.  Shell and dialog widgets provide top-level
  885. windows that talk to the window manager. Other widgets that are or will be
  886. available in the public domain or through various software suppliers
  887. include table layout managers, directed-graph layout managers, graphical
  888. gauges, plotting and line graphics widgets, etc.
  889. .LP
  890. \fIXlisp\fP classes describe the type of a particular object by declaring a
  891. set of variables held in each object. These \fIinstance variables\fP may
  892. only be accessed by \fImethods\fP that respond to \fImessages\fP sent to
  893. the object.  Methods are defined for particular classes, and functionality
  894. of other classes may be incorporated into new classes via
  895. \fIinheritance\fP.  From \fIXlisp\fP, Motif widget classes and instances
  896. look just like normal \fIXlisp\fP classes and instances, meaning that one
  897. can add new methods or override old ones, possibly using polymorphism to
  898. exploit similarities between types despite different implementations. Type
  899. inheritance and subclassing are available to specialize existing widget
  900. classes.  The result is that \fIWinterp\fP provides a very clean way to
  901. interactively rapid-prototype an application, while also providing
  902. mechanisms for code structuring and reuse.  The latter is necessary in
  903. evolving from prototype to a structured, maintainable, and customizable
  904. deliverable.
  905. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  906. .\"subsection{}
  907. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  908. .NH 2
  909. Open Application Architecture
  910. .LP
  911. \fIWinterp\fP promotes an open, extensible architecture for applications
  912. because designers cannot foresee all the possible needs of the end-user. In
  913. addition to being open to the application customizer, \fIWinterp\fP is also
  914. open to systems integration in which applications must work together with
  915. other applications running on the network. \fIWinterp\fP enables such
  916. integration because its language interpreter is implemented as a server.
  917. .LP
  918. Thus, all \fIWinterp\fP-based applications have a built-in, extensible
  919. remote procedure call (RPC) mechanism which allows other applications,
  920. possibly running non-locally, to send commands to execute application
  921. functionality.  Such an architecture allows applications to talk to each
  922. other, share data, etc. The server configuration can be specified via
  923. Xresources, allowing the user of WINTERP or a WINTERP-based application to
  924. enable/disable Unix-Domain or Inet-Domain server sockets.
  925. .LP
  926. Figure 3 shows a diagram of \fIWinterp\fP's server architecture. Both local
  927. and remote applications can invoke remote procedure calls in
  928. \fIWinterp\fP-based applications. Programmatic changes can be sent to
  929. \fIWinterp\fP from the \fIUnix\fP command shell and shell scripts via a
  930. simple client program, \f(CWwl\fP, which is included with the \fIWinterp\fP
  931. distribution.  For example, a user-defined function
  932. \f(CWstart-application\fP may be called within \fIWinterp\fP by executing
  933. the following \fIUnix\fP command:
  934. .\"%%%%%%%%%%%%%%%
  935. .\"begin{verbatim}
  936. .\"%%%%%%%%%%%%%%%
  937. .LS
  938.         wl '(start-application)'
  939. .\"%%%%%%%%%%%%%%%
  940. .\"end{verbatim}
  941. .\"%%%%%%%%%%%%%%%
  942. .LE
  943. .\"%%%%%%%%%%%%%
  944. .\"begin{figure}
  945. .\"label{winterp_architecture}
  946. .\"%%%%%%%%%%%%%
  947. .KF
  948. .sp 12.5c
  949. .sp
  950. .CD
  951. Figure 3. Inter-application communications via \fIWinterp\fP's \fIXlisp\fP server.
  952. .DE
  953. .\"%%%%%%%%%%%%%
  954. .\"end{figure}
  955. .\"%%%%%%%%%%%%%
  956. .KE
  957. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  958. .\"subsection{}
  959. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  960. .NH 2
  961. \*QWhat you program is what you see\*U
  962. .LP
  963. The \fIGNU Emacs\fP editor provides an elegant environment for writing and
  964. formatting\**
  965. .FS
  966. Emacs' Lisp-mode will automatically indent one's code and help catch
  967. unmatched parentheses.
  968. .FE
  969. \fIWinterp\fP programs. The \fIWinterp\fP distribution contains an
  970. extension to Emacs' Lisp-mode whereby an Emacs command will send the
  971. current Lisp form being edited to \fIWinterp\fP for evaluation.  This
  972. allows truly interactive programming because one need not exit the editor
  973. to see the results of evaluating a code fragment; with \fIWinterp\fP, one
  974. can see the graphical results of interactive changes to a program
  975. immediately. Note that \fIWinterp\fP is architecturally separate from the
  976. \fIGNU Emacs\fP editor (see Figure 3) \*- interfaces to other editors are
  977. possible, but are not provided in the current \fIWinterp\fP distribution.
  978. .LP
  979. Non-Emacs users may find an example program in the \fIWinterp\fP
  980. distribution useful for interactively editing and evaluating code with the
  981. Motif text editor widget. By loading \f(CWwinterp/examples/w_ctrlpnl.lsp\fP
  982. into \fIWinterp\fP, a window will pop up providing a rudimentary editor,
  983. file browser, and control panel for the system. The control panel contains
  984. buttons that control \fIXlisp\fP's debugger and error backtrace, as well as
  985. controls to load files, edit files, and evaluate the Lisp form being
  986. edited.
  987. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  988. .\"subsection{}
  989. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  990. .NH 2
  991. Automatic Resource Conversions
  992. .LP
  993. In \fIWinterp\fP, any Motif resource that can be represented in the X
  994. resource manager (i.e. one can set the resource via .Xdefaults) can be
  995. specified as a Lisp string, and it will automatically be converted to the
  996. appropriate type. This is especially useful for automatically converting
  997. strings to XmStrings. Other useful conversions include converting color
  998. names to type \f(CWPixel\fP, and converting bitmap file names to type
  999. \f(CWPixmap\fP.
  1000. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1001. .\"subsection{}
  1002. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1003. .NH 2
  1004. Interpreted Callbacks
  1005. .LP
  1006. Xtoolkit callbacks, event-handlers, timeouts, translations, and
  1007. accelerators are seamlessly integrated with \fIWinterp\fP \*- Xevents can
  1008. cause arbitrary code (both Lisp and C) to be executed. (See the example
  1009. code in the next section for details.)
  1010. .LP
  1011. For Xtoolkit translations and accelerators, \fIWinterp\fP includes a
  1012. special action procedure \f(CWLisp()\fP whose arguments are evaluated as a
  1013. Lisp function call. For example, the following Xtoolkit translation- or
  1014. accelerator-table entry\**
  1015. .FS
  1016. A translation/accelerator entry may be specified in an X resource file,
  1017. e.g. .Xdefaults, or may be set directly within \fIWinterp\fP.
  1018. .FE
  1019. will cause the application-defined function \f(CWctrl-A-hit\fP to be called
  1020. when the key sequence CTRL-A is entered on the widget:
  1021. .\"%%%%%%%%%%%%%%%
  1022. .\"begin{verbatim}
  1023. .\"%%%%%%%%%%%%%%%
  1024. .LS
  1025.         "Ctrl<Key>A: Lisp(ctrl-A-hit ACTION_WIDGET ACTION_XEVENT)"
  1026. .\"%%%%%%%%%%%%%%%
  1027. .\"end{verbatim}
  1028. .\"%%%%%%%%%%%%%%%
  1029. .LE
  1030. .LP
  1031. The symbol \f(CWACTION_WIDGET\fP above is bound to the widget-object that
  1032. caused the action procedure to fire, and \f(CWACTION_XEVENT\fP is bound to
  1033. the XEvent-object that matched the translation or accelerator entry.  These
  1034. values are then passed as arguments to function \f(CWctrl-A-hit\fP.
  1035. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1036. .\"subsection{}
  1037. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1038. .NH 2
  1039. Automatic Memory Management
  1040. .LP
  1041. \fIXlisp\fP's garbage collector has been extended to reclaim unused X,
  1042. Xtoolkit, and Motif storage \*- this allows programmers to concentrate on
  1043. the UI and application functionality, rather than memory management.
  1044. Memory management is one of the pitfalls that complicates X programming in
  1045. C \*- novices have difficulty in determining the lifetime of objects in X
  1046. and the Xtoolkit, resulting in hard-to debug program crashes if objects are
  1047. freed too early, or subtle memory leaks if objects are not freed at all. In
  1048. \fIWinterp\fP, memory need not be managed explicitly, since Lisp's garbage
  1049. collection automatically frees up any memory that is no longer referenced
  1050. by the system.
  1051. .LP
  1052. In particular, \fIXlisp\fP's garbage collector has been extended to reclaim
  1053. storage associated with destroyed widget objects, along with any
  1054. toolkit-internal storage associated with these widget objects. Such garbage
  1055. collection occurs for callbacks, event-handlers, timeouts, XmStrings, and
  1056. XmStringTables.
  1057. .LP
  1058. Garbage collection of pixmaps in \fIWinterp\fP is especially useful because
  1059. we can expect pixmaps to take up a reasonable amount of client and server
  1060. space in typical graphic/iconic Motif applications. \fIWinterp\fP extends
  1061. Motif's reference counting and pixmap caching scheme to work with garbage
  1062. collection. Server and client-side storage associated with a pixmap will
  1063. get reclaimed when no references to them exist in any widget-object or
  1064. other \fIWinterp\fP variable.
  1065. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1066. .\"subsection{}
  1067. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1068. .NH 2
  1069. Programming by Direct Manipulation
  1070. .LP
  1071. The current release of \fIWinterp\fP includes a primitive which allows for
  1072. \*Qprogramming by direct manipulation.\*U When one is interactively,
  1073. programmatically modifying a user interface, one often wants to send a
  1074. message to a widget-object without knowing it's \*Qname\*U or the symbol to
  1075. which the widget object is bound. The primitive \f(CWget_moused_widget\fP
  1076. allows messages to be passed to any widget-object one can point the mouse
  1077. at. Developers may use this for rapid prototyping \*- they can immediately
  1078. see the changes they are making to the UI. Users may customize delivered
  1079. \fIWinterp\fP-based applications by simply \*Qpointing\*U at the widgets
  1080. they wish to change \*- colors, fonts, sizes, callbacks, and other such
  1081. widget parameters may be changed on the fly.
  1082. .LP
  1083. \f(CWget_moused_widget\fP may also be used to implement an interactive,
  1084. direct manipulation builder and resource editor application on top of
  1085. \fIWinterp\fP. Other direct manipulation primitives are being considered to
  1086. allow widgets to be placed or moved interactively.
  1087. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1088. .\"subsection{}
  1089. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1090. .NH 2
  1091. Extensibility
  1092. .LP
  1093. \fIWinterp\fP is not a closed system. Hybrid programming with \fIXlisp\fP
  1094. makes it straightforward to add new C-implemented widgets to the system so
  1095. that they can be accessed via the interpreter. It is also easy to add
  1096. special Xlib-level primitives to \fIWinterp\fP in order to implement
  1097. functionality not available via the widgets. The same goes for interfaces
  1098. to special \fIUnix\fP device drivers, etc.
  1099. .LP
  1100. Simple widgets (such as a pushbutton) can be interfaced with about 10 lines of C
  1101. code, which needs to be linked in to the rest of system. More complex
  1102. widgets (such as a text or graph editor) are added with the same techniques
  1103. as used by simple widgets.  However, if such widgets provide a number of
  1104. \*Qconvenience functions\*U (methods), then each convenience function will
  1105. need to be interfaced to Lisp. Each convenience function interface usually
  1106. takes about 5-10 lines of C code. Such C-level interfacing of convenience
  1107. functions and widgets is simple because most of it amounts to programming
  1108. via example (\*Qcut and paste\*U) from existing code.
  1109. .LP
  1110. Widgets requiring new resource representations can be added as well. To
  1111. achieve this, one needs to code Lisp-to-resource converters, or simply use
  1112. the String-to-Resource converters required to make such widgets work with
  1113. the X resource database.
  1114. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1115. .\"section{}
  1116. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1117. .NH 1
  1118. Example Use
  1119. .LP
  1120. In the following code, we will first step through some simple \fIWinterp\fP
  1121. code that will allow us to create windows, put widgets inside those windows
  1122. and attach callbacks to execute code when a particular widget is activated
  1123. via X input. Afterwards, we will take some of concepts from the example
  1124. code and apply it to a real application \*- a bitmap browser.
  1125. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1126. .\"subsection{}
  1127. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1128. .NH 2
  1129. Introduction to Xlisp Syntax
  1130. .LP
  1131. First, we shall introduce a few rudimentary aspects of \fIWinterp\fP
  1132. programming and \fIXlisp\fP syntax for those not familiar with the
  1133. language. The examples below only use a small fraction of the functionality
  1134. of Lisp \*- assignment, function calls, object creation, and message
  1135. passing.
  1136. .\"---------------
  1137. .\"begin{itemize}
  1138. .\"---------------
  1139. .RS .5in
  1140. .\"-----
  1141. .\"\item
  1142. .\"-----
  1143. .Ip
  1144. Symbols:
  1145. .LP
  1146. Those not familiar with Lisp will find symbols to be similar to variables
  1147. and function names in compiled languages such as Pascal or C.  When a
  1148. symbol is evaluated, it returns it's value. A value can be assigned to a
  1149. symbol with the function \f(CWsetq\fP.
  1150. .\"-----
  1151. .\"\item
  1152. .\"-----
  1153. .Ip
  1154. Assignment:
  1155. .LP
  1156. The function \f(CWsetq\fP will bind \f(CW<value>\fP to \f(CW<symbol>\fP:
  1157. .\"%%%%%%%%%%%%%%%
  1158. .\"begin{verbatim}
  1159. .\"%%%%%%%%%%%%%%%
  1160. .LS
  1161.         (setq <symbol> <value>)
  1162. .\"%%%%%%%%%%%%%%%
  1163. .\"end{verbatim}
  1164. .\"%%%%%%%%%%%%%%%
  1165. .LE
  1166. Upon evaluation of \f(CW<symbol>\fP, \f(CW<value>\fP will be returned.
  1167. .\"-----
  1168. .\"\item
  1169. .\"-----
  1170. .Ip
  1171. Function calls:
  1172. .LP
  1173. A function named by the symbol \f(CW<function-name>\fP can be called with a
  1174. sequence of arguments \f(CW<argument-1> <argument-2>...<argument-n>\fP.
  1175. The syntax for a function call is:
  1176. .\"%%%%%%%%%%%%%%%
  1177. .\"begin{verbatim}
  1178. .\"%%%%%%%%%%%%%%%
  1179. .LS
  1180.         (<function-name> <argument-1> <argument-2>...<argument-n>)
  1181. .\"%%%%%%%%%%%%%%%
  1182. .\"end{verbatim}
  1183. .\"%%%%%%%%%%%%%%%
  1184. .LE
  1185. Where each \f(CW<argument-i>\fP is a symbol, a function call, or a value.
  1186. Each argument is evaluated before being passed in to the function
  1187. associated with \f(CW<function-name>\fP.
  1188. .\"-----
  1189. .\"\item
  1190. .\"-----
  1191. .Ip
  1192. Sending a message to an object:
  1193. .LP
  1194. The \fIXlisp\fP function \f(CWsend\fP allows one to send the \fImessage\fP
  1195. \f(CW:<message>\fP to the object \f(CW<object-instance>\fP. If
  1196. \f(CW<object-instance>\fP's \fIclass\fP contains a \fImethod\fP for the
  1197. particular \fImessage\fP, that method will be called just like a function
  1198. call with arguments \f(CW[...arguments...]\fP.
  1199. .\"%%%%%%%%%%%%%%%
  1200. .\"begin{verbatim}
  1201. .\"%%%%%%%%%%%%%%%
  1202. .LS
  1203.         (send <object-instance> :<message> [...arguments...])
  1204. .\"%%%%%%%%%%%%%%%
  1205. .\"end{verbatim}
  1206. .\"%%%%%%%%%%%%%%%
  1207. .LE
  1208. .\"-----
  1209. .\"\item
  1210. .\"-----
  1211. .Ip
  1212. Object creation:
  1213. .LP
  1214. To create a new instance of \fIclass\fP \f(CW<object-class>\fP, send the
  1215. message \f(CW:NEW\fP to the class. The arguments \f(CW[...arguments...]\fP
  1216. are dependent on what kinds of initialization need to be done by the
  1217. instance initializer method \f(CW:ISNEW\fP.
  1218. .\"%%%%%%%%%%%%%%%
  1219. .\"begin{verbatim}
  1220. .\"%%%%%%%%%%%%%%%
  1221. .LS
  1222.         (send <object-class> :NEW [...arguments...])
  1223. .\"%%%%%%%%%%%%%%%
  1224. .\"end{verbatim}
  1225. .\"%%%%%%%%%%%%%%%
  1226. .LE
  1227. .\"-------------
  1228. .\"\end{itemize}
  1229. .\"-------------
  1230. .RE
  1231. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1232. .\"subsection{}
  1233. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1234. .NH 2
  1235. Create a Top-Level Window:
  1236. .LP
  1237. Below, we create a top level window\**
  1238. .FS
  1239. A top level window is conceptually a child of the root window in the X
  1240. server. These top level windows are managed by the window manager, allowing
  1241. users to move, resize, and iconize application windows.
  1242. .FE
  1243. by creating an instance of the Xt Intrinsics
  1244. \f(CWtopLevelShellWidgetClass\fP. The symbol \f(CWtoplevel_w\fP is bound to
  1245. the widget-object representing the new top level widget instance.  The
  1246. keyword arguments \f(CW:XMN_HEIGHT\fP and \f(CW:XMN_WIDTH\fP are set so
  1247. that the window is of size 500x500\**
  1248. .FS
  1249. Hard-coding the window size in an X application is not a good idea. The
  1250. code we are presenting here is just the result of our interactive session
  1251. with \fIWinterp\fP, and not representative of how a real application should
  1252. be coded.
  1253. .FE
  1254. , and we also set the titlebar and icon names displayed by the window
  1255. manager.
  1256. .LP
  1257. In order to actually create the toplevel window, the Xt Intrinsics require
  1258. that function \f(CWXtRealizeWidget()\fP be called \*- that operation is
  1259. done by sending the message \f(CW:REALIZE\fP to the widget instance.
  1260. .LP
  1261. Sending the two forms below to \fIWinterp\fP's server will cause a new
  1262. toplevel window to pop up immediately:
  1263. .\"%%%%%%%%%%%%%%%
  1264. .\"begin{verbatim}
  1265. .\"%%%%%%%%%%%%%%%
  1266. .LS
  1267. (setq toplevel_w
  1268.       (send TOP_LEVEL_SHELL_WIDGET_CLASS :new
  1269.             :XMN_HEIGHT    500
  1270.             :XMN_WIDTH     500
  1271.             :XMN_TITLE     "Winterp: example-1"
  1272.             :XMN_ICON_NAME "example-1"
  1273.             ))
  1274. (send toplevel_w :realize)
  1275. .\"%%%%%%%%%%%%%%%
  1276. .\"end{verbatim}
  1277. .\"%%%%%%%%%%%%%%%
  1278. .LE
  1279. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1280. .\"subsection{}
  1281. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1282. .NH 2
  1283. Create a Widget Layout Manager:
  1284. .LP
  1285. Above, we have created an instance of a
  1286. \f(CWTOP_LEVEL_SHELL_WIDGET_CLASS\fP which is bound to symbol
  1287. \f(CWtoplevel_w\fP. We now attach a layout manager widget as a child of the
  1288. top level widget.  Layout manager widgets generally do not add to the
  1289. visual appearance of an application in and of themselves, rather, they
  1290. manage the layout and geometries of the set of child widgets that appear
  1291. within them.  One of the important manager widgets in Motif is the
  1292. Row/Column manager \f(CWxmRowColumnWidgetClass\fP. This widget will lay out
  1293. its child widgets to appear in a configurable number of rows and columns.
  1294. .LP
  1295. In the code below, we create an instance of
  1296. \f(CWXM_ROW_COLUMN_WIDGET_CLASS\fP bound to symbol \f(CWrowcol_w\fP. The
  1297. widget is a child of an instance of \f(CWXM_SCROLLED_WINDOW_WIDGET_CLASS\fP
  1298. which is bound to \f(CWscrl_w\fP. The scrolled window widget will put up
  1299. scrollbars if the row/column widget within in grows larger than the 500x500
  1300. toplevel window associated with \f(CWtoplevel_w\fP. The arguments to the
  1301. resources \f(CW:XMN_ORIENTATION\fP and \f(CW:XMN_PACKING\fP cause the row
  1302. column widget's children to be laid out vertically, with no space padding
  1303. between widgets.
  1304. .LP
  1305. Sending the following code to \fIWinterp\fP's server will cause the widgets
  1306. to be created:
  1307. .\"%%%%%%%%%%%%%%%
  1308. .\"begin{verbatim}
  1309. .\"%%%%%%%%%%%%%%%
  1310. .LS
  1311. (setq scrl_w
  1312.       (send XM_SCROLLED_WINDOW_WIDGET_CLASS :new :managed 
  1313.             toplevel_w                      ;parent is toplevel
  1314.             :XMN_SCROLLING_POLICY :automatic
  1315.             ))
  1316. (setq rowcol_w
  1317.       (send XM_ROW_COLUMN_WIDGET_CLASS :new :managed
  1318.             scrl_w                          ;parent is scroller
  1319.             :XMN_ORIENTATION      :vertical
  1320.             :XMN_PACKING          :pack_tight
  1321.             :XMN_ENTRY_ALIGNMENT  :alignment_center
  1322.             :XMN_FOREGROUND       "Black"
  1323.             :XMN_BACKGROUND       "LightGray"
  1324.             ))
  1325. .\"%%%%%%%%%%%%%%%
  1326. .\"end{verbatim}
  1327. .\"%%%%%%%%%%%%%%%
  1328. .LE
  1329. .LP
  1330. Note that the \f(CW:MANAGED\fP argument for widget creation does the
  1331. equivalent of \f(CWXtManageWidget()\fP. In simplistic terms, managing a
  1332. child widget makes it visible within its parent.
  1333. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1334. .\"subsection{}
  1335. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1336. .NH 2
  1337. Adding Widgets to the Layout Manager:
  1338. .LP
  1339. Now we can interactively add a variety of widgets to the Row/Column manager
  1340. by sending each of the forms below to \fIWinterp\fP's server.  For every
  1341. form that gets evaluated below, we will see the corresponding widget appear
  1342. within the window titled \*QWinterp: example-1\*U that we created earlier.
  1343. See Figure 4 to see how these widgets look.
  1344. .\"%%%%%%%%%%%%%%%
  1345. .\"begin{verbatim}
  1346. .\"%%%%%%%%%%%%%%%
  1347. .LS
  1348. (setq arrow_up_w
  1349.       (send XM_ARROW_BUTTON_WIDGET_CLASS :new :managed rowcol_w
  1350.             :XMN_ARROW_DIRECTION :arrow_up
  1351.             ))
  1352. (setq big_arrow_left_w
  1353.       (send XM_ARROW_BUTTON_WIDGET_CLASS :new :managed rowcol_w
  1354.             :XMN_ARROW_DIRECTION :arrow_left
  1355.             :XMN_HEIGHT          50
  1356.             :XMN_WIDTH           50
  1357.             ))
  1358. (setq label_w
  1359.       (send XM_LABEL_WIDGET_CLASS :new :managed rowcol_w
  1360.             :XMN_LABEL_STRING "hi, I'm a label widget"
  1361.             :XMN_FOREGROUND      "White"
  1362.             :XMN_BACKGROUND      "Black"
  1363.             ))
  1364. (setq string_push_button_w
  1365.       (send XM_PUSH_BUTTON_WIDGET_CLASS :new :managed rowcol_w
  1366.             :XMN_LABEL_STRING    "hi, I'm a pushbutton widget"
  1367.             :XMN_FOREGROUND      "Black"
  1368.             :XMN_BACKGROUND      "LightGrey"
  1369.             ))
  1370. (setq pixmap_push_button_w
  1371.       (send XM_PUSH_BUTTON_WIDGET_CLASS :new :managed rowcol_w
  1372.               :XMN_LABEL_TYPE    :pixmap
  1373.               :XMN_LABEL_PIXMAP  (xm_get_pixmap 
  1374.                                   "/users/mayer/src/bitmaps/bob0.xbm"
  1375.                                   "black" "white")
  1376.               ))
  1377. (setq text_editor_w 
  1378.       (send XM_TEXT_WIDGET_CLASS :new :managed :scrolled rowcol_w
  1379.             :XMN_EDIT_MODE       :MULTI_LINE_EDIT
  1380.             :XMN_FONT_LIST       "hp8.10x20b"
  1381.             :XMN_HEIGHT          100
  1382.             :XMN_FOREGROUND      "Black"
  1383.             :XMN_BACKGROUND      "LightGrey"
  1384.             ))
  1385. (setq string_toggle_button_w
  1386.       (send XM_TOGGLE_BUTTON_WIDGET_CLASS :new :managed rowcol_w
  1387.             :XMN_LABEL_STRING    "hi, I'm a togglebutton widget"
  1388.             ))
  1389. (setq pixmap_toggle_button_w
  1390.       (send XM_TOGGLE_BUTTON_WIDGET_CLASS :new :managed rowcol_w
  1391.             :XMN_LABEL_TYPE      :pixmap
  1392.             :XMN_LABEL_PIXMAP    "/users/mayer/src/bitmaps/bob1.xbm"
  1393.             ))
  1394. .\"%%%%%%%%%%%%%%%
  1395. .\"end{verbatim}
  1396. .\"%%%%%%%%%%%%%%%
  1397. .LE
  1398. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1399. .\"subsection{}
  1400. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1401. .NH 2
  1402. Setting or Querying the State of a Widget
  1403. .LP
  1404. Messages may be sent to widgets in order to set or get widget-specific
  1405. state information. Widget resources are accessible via the messages
  1406. \f(CW:SET_VALUES\fP and \f(CW:GET_VALUES\fP, the methods associated with
  1407. those messages correspond to the Xtoolkit functions \f(CWXtSetValues()\fP
  1408. and \f(CWXtGetValues()\fP, respectively.
  1409. .LP
  1410. Some widget classes define certain class-specific methods \*- for example,
  1411. the Motif \f(CWXM_TEXT_WIDGET_CLASS\fP responds to message
  1412. \f(CW:SET_STRING\fP by invoking the method \f(CWXmTextSetString()\fP which
  1413. sets the string within the editor. To set the string in the editor widget
  1414. instance created above, we do:
  1415. .\"%%%%%%%%%%%%%%%
  1416. .\"begin{verbatim}
  1417. .\"%%%%%%%%%%%%%%%
  1418. .LS
  1419. (send text_editor_w :set_string "Hi, I'm a text editor widget")
  1420. .\"%%%%%%%%%%%%%%%
  1421. .\"end{verbatim}
  1422. .\"%%%%%%%%%%%%%%%
  1423. .LE
  1424. .LP
  1425. Note that \fIWinterp\fP's use of a real object system brings added safety
  1426. and error checking to programming with Motif. In C, a programmer may make
  1427. the naive assumption that calling \f(CWXmTextSetString()\fP on a label
  1428. widget would set the text string in the label; in reality, the program
  1429. would core dump because the function was called on an instance of the wrong
  1430. class. In \fIWinterp\fP, such a misunderstanding would result in a
  1431. continuable error which the programmer could fix and continue-from
  1432. interactively.
  1433. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1434. .\"subsection{}
  1435. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1436. .NH 2
  1437. Adding Callbacks
  1438. .LP
  1439. Above, we have shown how to create a \*Qrandom\*U layout of widgets with
  1440. \fIWinterp\fP. In order to make the interface do anything, we need to add
  1441. callbacks, event-handlers, or actions to the widgets \*- these will call
  1442. arbitrary code in response to user input.
  1443. .LP
  1444. For example, suppose we want to make the push button widget with the label
  1445. \f(CW"hi I'm a pushbutton widget"\fP call some code that will print
  1446. something on standard output when it is activated via mouse. To do this, we
  1447. use the \fIWinterp\fP equivalent of \f(CWXtAddCallback()\fP, the method
  1448. \f(CW:add_callback\fP.
  1449. .LP
  1450. Each widget class's \f(CW:ADD_CALLBACK\fP method takes as argument the name
  1451. of the callback list, a widget-class specific list of symbols to bind to
  1452. data from the callback's \f(CWcall_data\fP callback structure, and a list
  1453. containing arbitrary code to be evaluated upon execution of the callback.
  1454. Note that the symbols bound to the values from \f(CWcall_data\fP are only
  1455. bound within the lexical and dynamic scope of the callback code.
  1456. .LP
  1457. In the example below, we are adding a callback to the push button widget's
  1458. \f(CWXmNactivateCallback\fP list, which will fire the callback's code
  1459. whenever the pushbutton is pressed and released. The code simply calls the
  1460. \f(CWformat\fP function, which is akin to the \fIUnix\fP
  1461. \f(CWfprintf(3S)\fP subroutine: it will print out the callback reason and
  1462. the widget-object that caused the callback on the \fIUnix\fP standard
  1463. output.
  1464. .\"%%%%%%%%%%%%%%%
  1465. .\"begin{verbatim}
  1466. .\"%%%%%%%%%%%%%%%
  1467. .LS
  1468. (send string_push_button_w :add_callback
  1469.       :XMN_ACTIVATE_CALLBACK                  ;name of callback list
  1470.       '(CALLBACK_REASON CALLBACK_WIDGET)      ;list of callback data
  1471.       '(                                      ;code to execute
  1472.         (format T "reason = ~A; widget = ~A\\\\n" 
  1473.                 CALLBACK_REASON CALLBACK_WIDGET)
  1474.         ))
  1475. .\"%%%%%%%%%%%%%%%
  1476. .\"end{verbatim}
  1477. .\"%%%%%%%%%%%%%%%
  1478. .LE
  1479. .LP
  1480. Obviously, the callback above doesn't do anything very interesting. We will
  1481. have to wait till the bitmap browser example to see a more useful callback.
  1482. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1483. .\"subsection{}
  1484. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1485. .NH 2
  1486. Direct Manipulation Programming
  1487. .LP
  1488. In \fIWinterp\fP, any widget's resources may be changed interactively via
  1489. method \f(CW:SET_VALUES\fP, which is equivalent to the Xtoolkit's
  1490. \f(CWXtSetValues()\fP. For example, we can interactively change the
  1491. direction of the arrow in the arrow button widget by sending \fIWinterp\fP
  1492. the following code.  Immediately after \fIWinterp\fP evaluates this code,
  1493. one will see the button display a downward facing arrow:
  1494. .\"%%%%%%%%%%%%%%%
  1495. .\"begin{verbatim}
  1496. .\"%%%%%%%%%%%%%%%
  1497. .LS
  1498. (send arrow_up_w :set_values
  1499.       :XMN_ARROW_DIRECTION :arrow_down
  1500.       )
  1501. .\"%%%%%%%%%%%%%%%
  1502. .\"end{verbatim}
  1503. .\"%%%%%%%%%%%%%%%
  1504. .LE
  1505. .LP
  1506. In the example above, we needed to get a hold of the widget-object value
  1507. bound to symbol \f(CWarrow_up_w\fP before we could operate on the widget.
  1508. In some cases, this is impractical, as one would rather just point at the
  1509. desired widget. The \fIWinterp\fP primitive function
  1510. \f(CWget_moused_widget\fP allows just that.
  1511. .LP
  1512. If we send the form below to \fIWinterp\fP's server, we will see the cursor
  1513. change to a \*Qcrosshair\*U indicating we are to click on a widget.  Upon
  1514. clicking on the widget, we will see it change colors:
  1515. .\"%%%%%%%%%%%%%%%
  1516. .\"begin{verbatim}
  1517. .\"%%%%%%%%%%%%%%%
  1518. .LS
  1519. (send (get_moused_widget) :set_values 
  1520.       :XMN_FOREGROUND "Green"
  1521.       :XMN_BACKGROUND "LightGrey"
  1522.       )
  1523. .\"%%%%%%%%%%%%%%%
  1524. .\"end{verbatim}
  1525. .\"%%%%%%%%%%%%%%%
  1526. .LE
  1527. .LP
  1528. The primitive \f(CWget_moused_widget\fP can be used in any place that
  1529. requires a widget-object as a parameter. One can use this function to
  1530. interactively change callbacks, font sizes, colors, etc. In delivered
  1531. \fIWinterp\fP-based applications, one can use this feature to experiment
  1532. with resource settings without needing documentation on the internals of
  1533. the application, nor the widget hierarchy.
  1534. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1535. .\"subsection{}
  1536. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1537. .NH 2
  1538. A Simple Application \*- a Bitmap Browser
  1539. .LP
  1540. We now create a simple application \*- a bitmap browser \*- using some of
  1541. the ideas from the code above. For each bitmap file in a directory of
  1542. bitmaps, this browser will put up a label widget containing the name of the
  1543. bitmap file, followed by a push button widget displaying the bitmap itself,
  1544. followed by a separator widget. All these widgets are held within a
  1545. scrolled row/column widget, which we've already seen used in the example
  1546. above. When a push button containing a pixmap is pressed, that pixmap
  1547. becomes the root window's tile pattern by calling the X11 program
  1548. \f(CWxsetroot(1)\fP with the appropriate arguments.  In Figure 4, the
  1549. window titled \*QBitmap Browser Example\*U shows what this bitmap browser
  1550. looks like.
  1551. .LP
  1552. The simplicity of implementing the bitmap browser application demonstrates
  1553. the power of \fIWinterp\fP and the expressiveness of its language syntax.
  1554. Furthermore, this example illustrates one of the interesting features of
  1555. \fIWinterp\fP \*- the ability to subclass a Motif widget by using
  1556. \fIXlisp\fP's object system.
  1557. .LP
  1558. We have seen the following code in the example above \*- here, we create a
  1559. top level widget, which contains a scrolled window widget, which in turn
  1560. contains a Row/Column widget:
  1561. .\"%%%%%%%%%%%%%%%
  1562. .\"begin{verbatim}
  1563. .\"%%%%%%%%%%%%%%%
  1564. .LS
  1565. (setq toplevel_w
  1566.       (send TOP_LEVEL_SHELL_WIDGET_CLASS :new 
  1567.             :XMN_TITLE "Bitmap Browser Example"
  1568.             :XMN_ICON_NAME "Bitmap-Br"
  1569.             ))
  1570. (setq scrl_w
  1571.       (send XM_SCROLLED_WINDOW_WIDGET_CLASS :new :managed
  1572.             toplevel_w
  1573.             :XMN_SCROLLING_POLICY :automatic
  1574.             ))
  1575. (setq rowcol_w
  1576.       (send XM_ROW_COLUMN_WIDGET_CLASS :new :managed
  1577.             scrl_w
  1578.             :XMN_ORIENTATION     :vertical
  1579.             :XMN_PACKING         :pack_tight
  1580.             :XMN_ENTRY_ALIGNMENT :alignment_center
  1581.             :XMN_FOREGROUND      "Black"
  1582.             :XMN_BACKGROUND      "LightGray"))
  1583. .\"%%%%%%%%%%%%%%%
  1584. .\"end{verbatim}
  1585. .\"%%%%%%%%%%%%%%%
  1586. .LE
  1587. .LP
  1588. Rather than placing an identical callback structure on each push button
  1589. widget in the browser (which is memory-inefficient), we exploit a feature
  1590. of the Motif Row/Column widget which allows us to place a single callback,
  1591. \f(CWXmNentryCallback\fP, on the Row/Column manager widget. Any activate
  1592. callback occurring on a widget that is a child of this Row/Column widget
  1593. will end up firing the callback below.  When the callback fires, symbol
  1594. \f(CWCALLBACK_ENTRY_WIDGET\fP will be bound to the entry in the Row/Column
  1595. widget that was activated. The code for the callback then sends the message
  1596. \f(CW:XSETROOT\fP to that widget, which will cause the root window's
  1597. background tile to be set to the bitmap contained in the button that was
  1598. activated.
  1599. .\"%%%%%%%%%%%%%%%
  1600. .\"begin{verbatim}
  1601. .\"%%%%%%%%%%%%%%%
  1602. .LS
  1603. (send rowcol_w :set_callback :XMN_ENTRY_CALLBACK
  1604.        '(CALLBACK_ENTRY_WIDGET)
  1605.        '(
  1606.          (send CALLBACK_ENTRY_WIDGET :xsetroot)
  1607.          ))
  1608. .\"%%%%%%%%%%%%%%%
  1609. .\"end{verbatim}
  1610. .\"%%%%%%%%%%%%%%%
  1611. .LE
  1612. .LP
  1613. Now, we create a specialization of the Motif
  1614. \f(CWXM_PUSH_BUTTON_GADGET_CLASS\fP\**
  1615. .FS
  1616. A Motif gadget, is for all intents and purposes the same as a Motif widget.
  1617. They are more efficient, and take up less client and server memory.
  1618. .FE
  1619. by making a trivial subclass called \f(CWNiels_Pixmap_Push_Button_Class\fP.
  1620. .LP
  1621. From the outside, instances of this class work just like a pushbutton. The
  1622. difference is that at initialization time, an instance of
  1623. \f(CWNiels_Pixmap_Push_Button_Class\fP requires that one give it a filename
  1624. containing the full path to a X bitmap file. The pushbutton will then
  1625. display this bitmap.
  1626. .LP
  1627. Internally, this subclass contains an additional instance variable
  1628. \f(CWpixmap_file\fP. Each instance of this push button will thus contain
  1629. the name of the bitmap file it is displaying. This instance variable is
  1630. later used by the method \f(CW:XSETROOT\fP.
  1631. .LP
  1632. The following code implements the subclassed widget.  The second form below
  1633. overrides the instance initializer associated with the superclass (the
  1634. \fIWinterp\fP code associated with \f(CWXM_PUSH_BUTTON_GADGET_CLASS\fP that
  1635. actually creates the widget) in order to initialize the instance variable
  1636. and pass special arguments on to the superclass's initializer method
  1637. \f(CW:ISNEW\fP
  1638. .\"%%%%%%%%%%%%%%%
  1639. .\"begin{verbatim}
  1640. .\"%%%%%%%%%%%%%%%
  1641. .LS        
  1642. ;;;
  1643. ;;; make a trivial subclass of XM_PUSH_BUTTON_GADGET_CLASS
  1644. ;;;
  1645. (setq Niels_Pixmap_Push_Button_Class                    
  1646.       (send Class :new
  1647.             '(pixmap_file)  ;a new inst-var for this subclass
  1648.             '()             ;no class vars for subclass
  1649.             XM_PUSH_BUTTON_GADGET_CLASS)) 
  1650. ;;;
  1651. ;;; override XM_TOGGLE_BUTTON_GADGET_CLASS's instance initializer
  1652. ;;;
  1653. (send Niels_Pixmap_Push_Button_Class :answer :isnew
  1654.       '(filename &rest args)
  1655.       '(
  1656.         (setq pixmap_file filename)
  1657.         (apply 'send-super `(:isnew ,@args
  1658.                                     :XMN_LABEL_TYPE :pixmap
  1659.                                     :XMN_LABEL_PIXMAP ,filename))
  1660.         ))
  1661. .\"%%%%%%%%%%%%%%%
  1662. .\"end{verbatim}
  1663. .\"%%%%%%%%%%%%%%%
  1664. .LE
  1665. .LP
  1666. Now we define the method \f(CW:XSETROOT\fP for the new class. When one
  1667. sends the message \f(CW:XSETROOT\fP to an instance of class
  1668. \f(CWNiels_Pixmap_Push_Button_Class\fP, this method answers by calling the
  1669. X program \f(CWxsetroot(1)\fP specifying the bitmap file that was contained
  1670. in the instance variable \f(CWpixmap_file\fP. \fIWinterp\fP calls the
  1671. \f(CWxsetroot(1)\fP program through the primitive \f(CWsystem\fP, which
  1672. corresponds to the \fIUnix\fP subroutine \f(CWsystem(3S)\fP:
  1673. .\"%%%%%%%%%%%%%%%
  1674. .\"begin{verbatim}
  1675. .\"%%%%%%%%%%%%%%%
  1676. .LS        
  1677. ;;;
  1678. ;;; a method that calls the xsetroot(1) program to set background
  1679. ;;;
  1680. (send Niels_Pixmap_Push_Button_Class :answer :xsetroot '()
  1681.       '(
  1682.         (system (format nil "xsetroot -bitmap ~A -fg Black -bg DimGrey" 
  1683.                         pixmap_file))
  1684.         ))
  1685. .\"%%%%%%%%%%%%%%%
  1686. .\"end{verbatim}
  1687. .\"%%%%%%%%%%%%%%%
  1688. .LE
  1689. .LP
  1690. The code below returns a stream of bitmap file names in a particular
  1691. directory on my system.
  1692. .LP
  1693. We use the \fIUnix\fP \f(CWpopen(3s)\fP routine to read the results of the
  1694. \fIUnix\fP command \f(CWls(1)\fP, which returns to \f(CWstdout\fP a list of
  1695. matching filenames in the shell created by \f(CWpopen(3s)\fP.\**
  1696. .FS
  1697. People familiar with \f(CWpopen(3S)\fP will realize that the command
  1698. \f(CW/bin/ls\fP could in fact be replaced by \f(CW/bin/echo\fP.
  1699. .FE
  1700. \f(CWpopen(3s)\fP returns a \f(CWFILE*\fP that can be read by the
  1701. \fIXlisp\fP primitive \f(CWread-line\fP.
  1702. .\"%%%%%%%%%%%%%%%
  1703. .\"begin{verbatim}
  1704. .\"%%%%%%%%%%%%%%%
  1705. .LS
  1706. (setq ls_reader_pipe
  1707.       (popen "/bin/ls /usr/local/mayer/src/bitmaps/*.xbm" 
  1708.              :direction :input))
  1709. .\"%%%%%%%%%%%%%%%
  1710. .\"end{verbatim}
  1711. .\"%%%%%%%%%%%%%%%
  1712. .LE
  1713. .LP
  1714. The following code does the brunt of the work in the bitmap browser
  1715. application. The \f(CWdo*\fP form is essentially a do-loop. It will
  1716. repeatedly use primitive \f(CWread-line\fP to retrieve a single file name
  1717. from \f(CWls_reader_pipe\fP that we created above. For each filename
  1718. retrieved, we create an instance of \f(CWXM_LABEL_GADGET_CLASS\fP
  1719. displaying the name of the bitmap file, followed by an instance of
  1720. \f(CWNiels_Pixmap_Push_Button_Class\fP displaying the pixmap itself, and
  1721. finally, we create an instance of \f(CWXM_SEPARATOR_GADGET_CLASS\fP to
  1722. separate the buttons from one another inside the Row/Column widget that is
  1723. managing them.
  1724. .LP
  1725. When \f(CWread-line\fP returns NIL, it means that we have hit the end of
  1726. file in \f(CWls_reader_pipe\fP. At this point we have created a browser of
  1727. all the bitmaps in the directory specified above. To clean up, we call
  1728. \f(CWpclose(3S)\fP to close the pipe opened by \f(CWpopen(3S)\fP and then
  1729. call \f(CWXtRealizeWidget()\fP to create the windows associated with the
  1730. browser, which is displayed in Figure 4.
  1731. .\"%%%%%%%%%%%%%%%
  1732. .\"begin{verbatim}
  1733. .\"%%%%%%%%%%%%%%%
  1734. .LS        
  1735. (do* 
  1736.  (;; local do-loop variables with initialize and increment expressions.
  1737.   (file-name (read-line ls_reader_pipe) (read-line ls_reader_pipe))
  1738.   )
  1739.  ((null file-name) ;loop done when (read-line) returns NIL ==> EOF
  1740.   )
  1741.  (send XM_LABEL_GADGET_CLASS :new :managed
  1742.        rowcol_w
  1743.        :XMN_LABEL_TYPE :STRING
  1744.        :XMN_LABEL_STRING file-name)
  1745.  (send Niels_Pixmap_Push_Button_Class :new file-name :managed
  1746.        rowcol_w)
  1747.  (send XM_SEPARATOR_GADGET_CLASS :new :managed
  1748.        rowcol_w
  1749.        :XMN_SEPARATOR_TYPE :DOUBLE_LINE)
  1750.  )
  1751. ;;;
  1752. ;;; Cleanup
  1753. ;;;
  1754. (pclose ls_reader_pipe)        ;close the pipe
  1755. (send toplevel_w :realize)     ;create the widgets windows
  1756. .\"%%%%%%%%%%%%%%%
  1757. .\"end{verbatim}
  1758. .\"%%%%%%%%%%%%%%%
  1759. .LE
  1760. .\"%%%%%%%%%%%%%
  1761. .\"begin{figure}
  1762. .\"label{winterp_snapshot}
  1763. .\"%%%%%%%%%%%%%
  1764. .KF
  1765. .sp 8.25i
  1766. .sp
  1767. .CD
  1768. Figure 4. The graphics produced by the \fIWinterp\fP example code.
  1769. .DE
  1770. .\"%%%%%%%%%%%%%
  1771. .\"end{figure}
  1772. .\"%%%%%%%%%%%%%
  1773. .KE
  1774. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1775. .\"section{}
  1776. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1777. .\" .1C
  1778. .NH 1
  1779. A Real Application \*- A Search Browser Based on the Unix Grep(1) Program.
  1780. .LP
  1781. In this section we create a Motif user interface to the \fIUnix\fP
  1782. \f(CWgrep(1)\fP program. This example continues to show off the power and
  1783. expressivity of object oriented programming in Winterp-Lisp \*- we make
  1784. extensive use of the \fIXlisp\fP object system here. This simple but useful
  1785. application searches a wildcarded set of files for a regular expression,
  1786. displaying each matching line in a browser. When an item is browsed (via
  1787. mouse double click) the file associated with the item is displayed, with
  1788. the matching line displayed at the top of the file. See Figure 5 to see
  1789. what the \f(CWgrep(1)\fP browser application looks like.
  1790. .LP
  1791. As an introductory example of using the object system, we create a new
  1792. class \*- \f(CWGrep-Item-Class\fP. Instances of the class correspond to a
  1793. datum produced by the \fIUnix\fP \f(CWgrep(1)\fP file searching program.
  1794. \f(CWgrep(1)\fP produces output consisting of file-names, line-numbers, and
  1795. the instance of a regular expression match. Below, we create a new class
  1796. containing those items as instance variables. The new class instance is
  1797. created by sending the instance creation message \f(CW:NEW\fP to the class
  1798. \f(CWClass\fP:
  1799. .LS
  1800. ;; (SEND Grep-Item-Class :NEW) returns <grep-item> instance.
  1801. (SETQ Grep-Item-Class
  1802.       (SEND Class :NEW
  1803.             '(file-name line-num match-line)
  1804.             ))
  1805. .LE
  1806. .LP
  1807. Below, we define a method corresponding to the message
  1808. \f(CW:display-string\fP \*- this method will be used by the search browser
  1809. as a way to present the objects in the browser.  We also define the
  1810. accessor methods \f(CW:file-name\fP and \f(CW:line-num\fP.
  1811. .LS
  1812. ;; (SEND <grep-item> :display-string) returns "<filename>: <match-line>"
  1813. (SEND Grep-Item-Class :ANSWER :display-string '()
  1814.       '(
  1815.         (FORMAT NIL "~A: ~A"    
  1816.                 file-name match-line)
  1817.         ))
  1818. ;; (SEND <grep-item> :file-name) returns file-name (string) of <grep-item>
  1819. (SEND Grep-Item-Class :ANSWER :file-name '()
  1820.       '(
  1821.         file-name
  1822.         ))
  1823. ;; (SEND <grep-item> :file-name) returns line-number (fixnum) of <grep-item>
  1824. (SEND Grep-Item-Class :ANSWER :line-num '()
  1825.       '(
  1826.         line-num
  1827.         ))
  1828. .LE
  1829. .LP
  1830. Now we add a new method on the class defined above, which reads a line of
  1831. output from the \fIUnix\fP command \f(CWgrep(1)\fP from a pipe, and puts
  1832. the data into the instance variables of a \f(CWGrep-Item-Class\fP object.
  1833. .LS
  1834. ;; (SEND <grep-item> :read-grep-info <pipe>) returns <grep-item> or NIL
  1835. ;; if EOF. Ivars are initialized to data from a line of "grep -n" output,
  1836. ;; which is of the format <filename>:<linenum>:<matching line>\\\\n
  1837. (SEND Grep-Item-Class :ANSWER :read-grep-info '(pipe)
  1838.       '(
  1839.         (if (AND
  1840.              (SETQ file-name  (FSCANF-STRING pipe "%[^:]:"))
  1841.              (SETQ line-num   (FSCANF-FIXNUM pipe "%d:"))
  1842.              (SETQ match-line (FSCANF-STRING pipe "%[^\\\\n]\\\\n"))
  1843.              )
  1844.           SELF                          ;return SELF if successful
  1845.           NIL                           ;return NIL if hit EOF
  1846.           )
  1847.         ))
  1848. .LE
  1849. .LP
  1850. The Lisp function \f(CWgrep\fP, below, is an example of using
  1851. \f(CWGrep-Item-Class\fP. This function invokes \f(CW"grep -n <regexp>
  1852. <wildcarded files>"\fP in a sub-shell, sending the output of the command to
  1853. a pipe. An instance of \f(CWGrep-Item-Class\fP is created for each regular
  1854. expression match found, with method \f(CW:read-grep-info\fP initializing the
  1855. object to contain the data corresponding to one match. The function returns
  1856. a list of objects corresponding to the matching items found by
  1857. \f(CWgrep(1)\fP. This function plays a key role in the upcoming search
  1858. browser example application.
  1859. .LS
  1860. ;; (grep <grep-arg-string>) returns list of <grep-item>.
  1861. ;; <grep-arg-string> == "[flags] <regexp> <wildcarded files>"
  1862. (DEFUN grep (grep-arg-string) 
  1863.   (DO* 
  1864.    (;; loop variables, initializers, and increments.
  1865.     (fp (POPEN (STRCAT "grep -n " grep-arg-string " /dev/null")
  1866.                :DIRECTION :INPUT))
  1867.     (line (SEND (SEND Grep-Item-Class :NEW) :read-grep-info fp)
  1868.           (SEND (SEND Grep-Item-Class :NEW) :read-grep-info fp))
  1869.     (result '())                        ;init to an empty list
  1870.     )
  1871.    ;; loop test and return
  1872.    ((NULL line)                         ;:read-grep-info returns NIL on EOF
  1873.     (PCLOSE fp)                         ;close the pipe opened above
  1874.     (REVERSE result)                    ;return list of grep objects.
  1875.     )
  1876.    ;; loop body
  1877.    (SETQ result (CONS line result))     ;prepend grep-obj to list
  1878.    ))
  1879. .LE
  1880. .LP
  1881. As an example of using \fIXlisp\fP's object-oriented features with Motif
  1882. widgets, we specialize Motif's text editor widget as a file-viewer via
  1883. (trivial) subclassing. Instances of the new class,
  1884. \f(CWText-Viewer-Widget-Class\fP, display the file of a browsed item with
  1885. the text scrolled to the appropriate line. We subclass the Motif XmText
  1886. widget so that we can add a method \f(CW:find-file\fP which reads the
  1887. specified file, displays it in the text widget, and scrolls the text to the
  1888. appropriate line number. The class has an extra instance variable,
  1889. \f(CWfile-path\fP which stores the name of the file. This allows method
  1890. \f(CW:find-file\fP to be more intelligent \*- if the same file is browsed
  1891. multiple times, it will not be reread each time.
  1892. .LP
  1893. First, we define the new class by sending message \f(CW:NEW\fP to class
  1894. \f(CWClass\fP, with arguments specifying the instance variables of the
  1895. class, as well as the superclass. Then, we define the instance initializer
  1896. method \f(CW:ISNEW\fP, which will automatically be called whenever new
  1897. instances of the widget are created (by sending \f(CW:NEW\fP to the class).
  1898. The initializer method sets the instance variable, then calls the
  1899. superclass' initializer method to create the Motif text editor widget.
  1900. Since \f(CWText-Viewer-Widget-Class\fP is a specialized editor, the
  1901. instance initializer hard-codes optional features of the editor such that
  1902. all instances end up having scroll bars, display multiple lines of text,
  1903. etc.
  1904. .LS
  1905. (SETQ Text-Viewer-Widget-Class
  1906.       (SEND Class :NEW
  1907.             '(file-path)                ;new instance vars
  1908.             '()                         ;no class vars
  1909.             XM_TEXT_WIDGET_CLASS))      ;superclass
  1910.  
  1911. ;; (SEND Text-Viewer-Widget-Class :NEW <:MANAGED/:UNMANAGED> <parent> [resources...])
  1912. (SEND Text-Viewer-Widget-Class :ANSWER :ISNEW '(managed-kwd &rest args)
  1913.       '(
  1914.         (SETQ file-path "")    ;initialize instance var
  1915.         (APPLY 'SEND-SUPER     ;call superclass's init to create widget
  1916.                `(:ISNEW ,managed-kwd ;either :MANAGED or :UNMANAGED
  1917.                         :SCROLLED    ;force the editor to have scrollbars
  1918.                         ,@args       ;parent widget + optional arguments
  1919.                         :XMN_EDIT_MODE :MULTI_LINE_EDIT ;multi line for files
  1920.                         :XMN_EDITABLE NIL ;do not allow user to edit text.
  1921.                         ))
  1922.         ))
  1923. .LE
  1924. .LP
  1925. The method \f(CW:find-file\fP is defined next. Note that in \fIXlisp\fP
  1926. methods, the symbol \f(CWSELF\fP is bound to the object receiving the
  1927. message. The messages \f(CW:SET_INSERTION_POSITION\fP,
  1928. \f(CW:GET_INSERTION_POSITION\fP, \f(CW:SCROLL\fP, \f(CW:REPLACE\fP,
  1929. \f(CW:SET_STRING\fP, \f(CW:ENABLE_REDISPLAY\fP and
  1930. \f(CW:DISABLE_REDISPLAY\fP correspond to methods defined on the superclass
  1931. \f(CWXM_TEXT_WIDGET_CLASS\fP. These are implemented in C by the Motif
  1932. toolkit.
  1933. .LS
  1934. ;; (SEND <textviewer> :find-file <filename> <linenum>)
  1935. (SEND Text-Viewer-Widget-Class :ANSWER :find-file '(filename linenum)
  1936.       '(
  1937.         (COND
  1938.          ((STRING= filename file-path)  ;if file already read into widget
  1939.           (SEND SELF :SET_INSERTION_POSITION 0) ;then make <linenum> top
  1940.           (SEND SELF :SCROLL (1- linenum))      ;by scrolling to it.
  1941.           )
  1942.          (T                                     ;else read file into widget.
  1943.           (LET* ((fp (OPEN filename :DIRECTION :INPUT))
  1944.                  insert-pos
  1945.                  text-line)
  1946.             (IF (NULL fp)
  1947.                 (ERROR "Can't open file." filename))
  1948.  
  1949.             (SEND SELF :SET_STRING "")          ;clear out old text
  1950.             (SEND SELF :DISABLE_REDISPLAY NIL)  ;show no changes till done
  1951.             (LOOP
  1952.              (IF (NULL (SETQ text-line (READ-LINE fp)))
  1953.                  (RETURN))
  1954.              (SETQ insert-pos (SEND SELF :GET_INSERTION_POSITION))
  1955.              (SEND SELF :REPLACE insert-pos insert-pos (STRCAT text-line "\\\\n"))
  1956.              )
  1957.             (SEND SELF :SCROLL linenum)   ;make <linenum> top of screen
  1958.             (SEND SELF :ENABLE_REDISPLAY) ;now show changes...
  1959.             (CLOSE fp)
  1960.             (SETQ file-path filename)
  1961.             )))
  1962.         ))
  1963. .LE
  1964. .LP
  1965. The browser user-interface to \f(CWgrep(1)\fP is made from the Motif list
  1966. widget, which simply displays a list of (compound) strings as a series of
  1967. selectable lines of text.  Callbacks can be defined on the list widget such
  1968. that when a line is selected one can retrieve the compound string that was
  1969. browsed, or get back the position (index) of the item that was browsed.
  1970. Both callback mechanisms require the programmer to maintain an external
  1971. association between the browser objects and their textual representation in
  1972. the list widget.  By subclassing the list widget, we can create an
  1973. interface that hides the mechanism for associating objects with the strings
  1974. representing them. As an additional feature, the abstraction enables the
  1975. browser to display an arbitrary collection of objects, as long as the
  1976. objects respond to a simple \*Qprotocol\*U \*- objects receiving the
  1977. message \f(CW:display-string\fP must return a textual representation of the
  1978. object.
  1979. .LP
  1980. The subclassed list widget adds a new instance variable \f(CWitems\fP which
  1981. holds an array of objects presented by the browser. The browser will
  1982. display the list of objects given as argument to the method
  1983. \f(CW:set-browser-items\fP (the method also initializes \f(CWitems\fP).
  1984. When an item is selected via a callback, the position of the selected item
  1985. is passed to method \f(CW:get-br-item-at-pos\fP, which returns
  1986. the browsed object using an efficient lookup implemented by array indexing.
  1987. .LS
  1988. (SETQ List-Browser-Widget-Class
  1989.       (SEND Class :NEW
  1990.             '(items)                    ;new instance vars
  1991.             '()                         ;no class vars
  1992.             XM_LIST_WIDGET_CLASS))      ;superclass
  1993.  
  1994. (SEND List-Browser-Widget-Class :ANSWER :set-browser-items '(items-list)
  1995.       '(
  1996.         (LET* (
  1997.                (items-end-idx (LENGTH items-list))
  1998.                (display-items (MAKE-ARRAY items-end-idx)))
  1999.  
  2000.           ;; initialize the 'items' instance variable so that it
  2001.           ;; holds all the BROWSER_OBJECTs passed in <items-list>
  2002.           (SETQ items (MAKE-ARRAY items-end-idx)) ;create the array
  2003.           (DO (                         ;copy elts from list to array
  2004.                (i    0          (1+ i))
  2005.                (elts items-list (CDR elts)))
  2006.               ;; loop till no more elts
  2007.               ((NULL elts))
  2008.               ;; loop body
  2009.               (SETF (AREF items i) (CAR elts)) ;set items[i]
  2010.               (SETF (AREF display-items i)     ;set display-items[i]
  2011.                     (SEND (CAR elts) :display-string))
  2012.               )
  2013.           ;; initialize the widget, passing in the browser items.
  2014.           (SEND SELF :SET_VALUES
  2015.                 :XMN_ITEMS      display-items
  2016.                 :XMN_ITEM_COUNT items-end-idx
  2017.                 )
  2018.           )
  2019.         ))
  2020. (SEND List-Browser-Widget-Class :ANSWER :get-br-item-at-pos '(position)
  2021.       '(
  2022.         (AREF items (1- position))
  2023.         ))
  2024. .LE
  2025. .LP
  2026. The user interface for the search browser application is created by
  2027. defining a hierarchy of widget-objects. Parent widgets manage the
  2028. geometries of their children, so the resulting interface is a nesting of
  2029. windows corresponding to the parent-child relationships created.  Refer to
  2030. Figure 5 to see the graphics produced by the code below.
  2031. .LP
  2032. In the UI code below, we first create an instance of
  2033. \f(CWTOP_LEVEL_SHELL_WIDGET_CLASS\fP which represents the outermost window
  2034. of the application \*- its geometry is managed by the X window manager,
  2035. allowing the user to move, resize, and iconize the window.  Inside that, we
  2036. create an instance of \f(CWXM_PANED_WINDOW_WIDGET_CLASS\fP: this widget
  2037. divides up the space of the toplevel window into a series of vertical
  2038. panes; the sizes of the panes can be adjusted by moving their resize
  2039. handles with the mouse. The first pane is an instance of
  2040. \f(CWXM_ROW_COLUMN_WIDGET_CLASS\fP, a manager widget which lays out the
  2041. controls for the search browser in the following horizontal sequence: (1) a
  2042. pushbutton, \f(CWdoit-button-w\fP; (2) a text label "Search for string:";
  2043. (3) a single-line text editor, \f(CWsearch-editor-w\fP, into which the user
  2044. types the regular expression for the search; (4) a label "From Files:"; and
  2045. (5) a single-line text editor, \f(CWfiles-editor-w\fP, into which the user
  2046. types the wildcarded filenames to search. The pane below the controlpanel
  2047. is \f(CWbrowser-w\fP, an instance of the \f(CWList-Browser-Widget-Class\fP.
  2048. The pane below the browser is \f(CWfilename-label-w\fP, which displays the
  2049. name of the file being browsed. And finally, the last pane is
  2050. \f(CWviewtext-w\fP, an instance of \f(CWText-Viewer-Widget-Class\fP which
  2051. is used to display the browsed files. The keyword \f(CW:SCROLLED\fP used in
  2052. creating the text viewer and browser widgets mean that these widgets are
  2053. created with scrollbars.
  2054. .LE
  2055. .\"%%%%%%%%%%%%%
  2056. .\"begin{figure}
  2057. .\"label{winterp_snapshot}
  2058. .\"%%%%%%%%%%%%%
  2059. .KF
  2060. .sp 8.25i
  2061. .sp
  2062. .CD
  2063. Figure 5. The \fIWinterp\fP \f(CWgrep(1)\fP browser example application.
  2064. .DE
  2065. .\"%%%%%%%%%%%%%
  2066. .\"end{figure}
  2067. .\"%%%%%%%%%%%%%
  2068. .KE
  2069. .LS
  2070. (LET (top-w paned-w controlpanel-w)
  2071.   (SETQ top-w
  2072.         (SEND TOP_LEVEL_SHELL_WIDGET_CLASS :NEW 
  2073.               :XMN_TITLE "Grep Browser"
  2074.               :XMN_ICON_NAME "Grep Browser"
  2075.               ))
  2076.   (SETQ paned-w
  2077.         (SEND XM_PANED_WINDOW_WIDGET_CLASS :NEW :MANAGED
  2078.               top-w                     ;the only child of the toplevel window
  2079.               ))
  2080.   (SETQ controlpanel-w
  2081.         (SEND XM_ROW_COLUMN_WIDGET_CLASS :NEW :MANAGED
  2082.               paned-w                   ;the first child of the paned window
  2083.               :XMN_ORIENTATION :HORIZONTAL
  2084.               :XMN_PACKING :PACK_TIGHT
  2085.               ))
  2086.   (SETQ doit-button-w
  2087.         (SEND XM_PUSH_BUTTON_WIDGET_CLASS :NEW :MANAGED
  2088.               controlpanel-w            ;the first child of the controlpanel
  2089.               :XMN_LABEL_STRING "Do Search"
  2090.               ))
  2091.   (SEND XM_LABEL_WIDGET_CLASS :NEW :MANAGED
  2092.         controlpanel-w                  ;the second child of the controlpanel
  2093.         :XMN_LABEL_STRING "Search for string:"
  2094.         )
  2095.   (SETQ search-editor-w
  2096.         (SEND XM_TEXT_WIDGET_CLASS :NEW :MANAGED
  2097.               controlpanel-w            ;the third child of the controlpanel
  2098.               :XMN_EDIT_MODE :SINGLE_LINE_EDIT
  2099.               ))
  2100.   (SEND XM_LABEL_WIDGET_CLASS :NEW :MANAGED
  2101.         controlpanel-w                  ;the fourth child of the controlpanel
  2102.         :XMN_LABEL_STRING "From Files:"
  2103.         )
  2104.   (SETQ files-editor-w
  2105.         (SEND XM_TEXT_WIDGET_CLASS :NEW :MANAGED
  2106.               controlpanel-w            ;the fifth child of the controlpanel
  2107.               :XMN_EDIT_MODE :SINGLE_LINE_EDIT
  2108.               ))
  2109.   (SETQ browser-w
  2110.         (SEND List-Browser-Widget-Class :NEW :MANAGED :SCROLLED
  2111.               paned-w                   ;the second child of the paned window
  2112.               :XMN_VISIBLE_ITEM_COUNT 20
  2113.               ))
  2114.   (SETQ filename-label-w
  2115.         (SEND XM_LABEL_WIDGET_CLASS :NEW :MANAGED
  2116.               paned-w                   ;the third child of the paned window
  2117.               :XMN_LABEL_STRING "None"
  2118.               ))
  2119.   (SETQ viewtext-w
  2120.         (SEND Text-Viewer-Widget-Class :NEW :MANAGED
  2121.               paned-w                   ;the fourth & final child of paned window
  2122.               :XMN_HEIGHT 400
  2123.               ))
  2124.   (SEND top-w :REALIZE)                 ;create the toplevel window & children
  2125.   ;;
  2126.   ;; now that the widgets have been created, we know their sizes; set constraint 
  2127.   ;; resources on the controlpanel and the filename label widget so that the paned
  2128.   ;; window widget managing their geometries won't let them be resized (this 
  2129.   ;; removes the "resize handles" for these widgets).
  2130.   (LET (h)
  2131.        (SEND controlpanel-w :GET_VALUES :XMN_HEIGHT 'h)
  2132.        (SEND controlpanel-w :SET_VALUES 
  2133.              :XMN_PANE_MAXIMUM h
  2134.              :XMN_PANE_MINIMUM h))
  2135.   (LET (h)
  2136.        (SEND filename-label-w :GET_VALUES :XMN_HEIGHT 'h)
  2137.        (SEND filename-label-w :SET_VALUES 
  2138.              :XMN_PANE_MAXIMUM h
  2139.              :XMN_PANE_MINIMUM h))
  2140.   )
  2141. .LE
  2142. .LP
  2143. Calling function \f(CWdo-grep-search\fP runs \f(CWgrep(1)\fP, searching for
  2144. the regular expression in \f(CWsearch-editor-w\fP from the list of
  2145. wildcarded files specified in \f(CWfiles-editor-w\fP.  The list of objects
  2146. returned by \f(CWgrep\fP is then displayed in the browser widget:
  2147. .LS
  2148. (DEFUN do-grep-search ()
  2149.   (SEND browser-w :set-browser-items
  2150.         (grep (STRCAT
  2151.                "'"                                ;protect regexps from shell
  2152.                (SEND search-editor-w :GET_STRING) ;get regexp for search
  2153.                "' "
  2154.                (SEND files-editor-w :GET_STRING)) ;wildcarded files to search
  2155.               )))
  2156. .LE
  2157. .LP
  2158. We complete the user interface by attaching programmatic actions \*-
  2159. callbacks \*- to the widget-objects created above. First, we want the
  2160. pushbutton associated with symbol \f(CWdoit-button-w\fP to initiate
  2161. searches when it is pressed by calling \f(CWdo-grep-search\fP.
  2162. .LS
  2163. (SEND doit-button-w :ADD_CALLBACK :XMN_ARM_CALLBACK '()
  2164.       '(
  2165.         (do-grep-search)
  2166.         ))
  2167. .LE
  2168. .LP
  2169. We now attach a callback to the browser widget \*- when a browser-item is
  2170. double clicked, symbol \f(CWCALLBACK_ITEM_POSITION\fP gets bound to the
  2171. position of the object in the browser. The position is passed to
  2172. \f(CW:get-br-item-at-pos\fP which returns the browsed item. The
  2173. file-name and line-number data from the grep-item is retrieved and used to
  2174. display the file at the correct line number in the text viewer widget.
  2175. .LS
  2176. (SEND browser-w :ADD_CALLBACK :XMN_DEFAULT_ACTION_CALLBACK
  2177.       '(CALLBACK_ITEM_POSITION) ;bound to the position of the item selected
  2178.       `(
  2179.         (LET* ((browsed-object
  2180.                 (SEND ,browser-w :get-br-item-at-pos CALLBACK_ITEM_POSITION))
  2181.                (filename
  2182.                 (SEND browsed-object :file-name))
  2183.                (linenum
  2184.                 (SEND browsed-object :line-num))
  2185.                )
  2186.           (SEND ,filename-label-w :SET_VALUES :XMN_LABEL_STRING filename)
  2187.           (SEND ,viewtext-w :find-file filename linenum)
  2188.           ))
  2189.       )
  2190. .LE
  2191. .LP
  2192. Finally, to make the user-interface easier to use, we note that after
  2193. entering text into one of the single-line text editor widgets, it is more
  2194. natural to hit the return-key to initiate a new search. Otherwise one has
  2195. to move from the keyboard to the mouse just to click the "Do Search"
  2196. button. The following Xtoolkit translation entries provide the binding
  2197. between hitting the return-key and calling the \f(CWdo-grep-search\fP
  2198. function that initiates a new search.
  2199. .LS
  2200. (SEND search-editor-w :OVERRIDE_TRANSLATIONS 
  2201.       "<Key>Return: Lisp(do-grep-search)")
  2202. (SEND files-editor-w  :OVERRIDE_TRANSLATIONS 
  2203.       "<Key>Return: Lisp(do-grep-search)")
  2204. .LE
  2205. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2206. .\"subsection{}
  2207. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2208. .NH 2
  2209. A Note on Programming Style.
  2210. .LP
  2211. The examples presented in this section do not necessarily represent good
  2212. Motif or \fIWinterp\fP programming style \*- the style has been relaxed
  2213. and simplified for the purpose of exposition.
  2214. .LP
  2215. First, we have used global variables throughout. For these examples, such
  2216. usage makes sense because that is the way one might use Lisp in
  2217. interactively prototyping an application \*- try bits of functionality out
  2218. piece by piece until one has come up with functionality that deserves to be
  2219. encapsulated. Once the prototype works, one may want to turn the code into
  2220. a function, or encapsulate it within an \fIXlisp\fP object. In that way,
  2221. the reliance on global variables will be removed.
  2222. .LP
  2223. Second, the examples above hard-code a number of X resources that should be
  2224. specifiable in the X resource database \*- either in .Xdefaults or in the
  2225. application defaults files. For the purposes of these examples, it would
  2226. have been confusing to specify these resources separately from the code.
  2227. Again, since the above code is prototype code, it is perfectly justifiable
  2228. to hard-code resources until one has settled on which parameters of
  2229. customization should and should not be accessible via the X resource
  2230. database.
  2231. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2232. .\"section{}
  2233. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2234. .NH 1
  2235. Future Directions
  2236. .LP
  2237. \fIWinterp\fP's features make it a good platform for a number of
  2238. interesting experiments in UIMS and \*Qdirect manipulation builder\*U
  2239. technologies. Because \fIWinterp\fP is currently a language-based builder,
  2240. it would make an ideal platform for the development of a \*Qtwo view\*U
  2241. builder that would allow application prototyping via programmatic or visual
  2242. manipulation of UIs.
  2243. .LP
  2244. \fIWinterp\fP was designed to support the addition of direct manipulation
  2245. interface building capabilities. We envision that a widget \*Qpalette\*U
  2246. could be built to allow the interactive selection and placement of widgets
  2247. within an interface. Another useful feature would be a resource browser
  2248. which would be used to display and edit the resources associated with any
  2249. widget in the system. Extending \fIWinterp\fP's widget-object based
  2250. interfaces so that they are \*Qself describing\*U would be a very elegant way
  2251. of dumping out a programmatic user-interface specification after it has
  2252. been built interactively and would provide the basis for a \*Qtwo view\*U
  2253. approach to interface building.
  2254. .LP
  2255. One of the areas where current direct-manipulation and \*QWhat You See Is
  2256. What You Get\*U (WYSIWYG) interface builders fail is in allowing end-user
  2257. customization without having to include the builder in the deliverable. The
  2258. challenge here is to allow the traditional X resources mechanism to customize
  2259. sizes, fonts, spacing, line-widths, etc., while still maintaining a
  2260. facsimile of the static UI layout intended by the application designers.
  2261. Traditional Xtoolkit-based applications do not suffer from such problems
  2262. because their interfaces are laid-out via the constraints provided by
  2263. geometry management widgets. With builders, such constraint management is
  2264. hard to specify graphically, so widget positioning and sizes must be
  2265. hard-coded.  What is needed is the ability to provide an explicit,
  2266. user-manipulable interface to the constraint-based language that is
  2267. implicit in the Xtoolkit's manager widgets. This is an open and active
  2268. research area.
  2269. .LP
  2270. Robert Leichner of HP Labs has already provided a novel UIMS structure for
  2271. \fIWinterp\fP by building a general-purpose event-driven recursive state
  2272. machine as a high level means of describing how application state interacts
  2273. with the UI. This UIMS architecture is being used in an ongoing project to
  2274. support collaboration among distributed workgroups via the use of
  2275. multimedia (audio and video). \fIWinterp\fP and the state-machine based
  2276. UIMS are being used as the basis for a media management toolkit which
  2277. controls experimental multimedia hardware residing on the workstation.  The
  2278. \fIStrudel\fP project is also experimenting with a variety of UIMS
  2279. approaches in order to come up with a high-level description of e-mail
  2280. based forms.
  2281. .LP
  2282. In order to ease application development and simplify \*Qhybrid
  2283. programming\*U, we are considering the addition of a dynamic loader to allow
  2284. new C-implemented primitives to be loaded into a running application.  It
  2285. may also be useful to dynamically load widget code on demand, instead of
  2286. always having it compiled in to the application.
  2287. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2288. .\"section{}
  2289. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2290. .NH 1
  2291. Conclusion
  2292. .LP
  2293. We believe that \fIWinterp\fP provides an excellent, practical development
  2294. and delivery environment for extensible Motif-based applications. If this
  2295. paper has piqued your interest in \fIWinterp\fP, you may obtain the current
  2296. source, documentation, and examples via anonymous ftp from host
  2297. \f(CWexport.lcs.mit.edu\fP: in directory \f(CWcontrib/winterp\fP you will
  2298. find the \f(CWcompress(1)'d\fP \f(CWtar(1)\fP file
  2299. \f(CWwinterp-<latestversion>.tar.Z\fP\**.
  2300. .FS
  2301. As of this writing, <latestversion> \(>= 1.12 .
  2302. .FE
  2303. If you do not have Internet access you may request the source code to be
  2304. mailed to you by sending a message to
  2305. \f(CWwinterp-source@hplnpm.hpl.hp.com\fP or
  2306. \f(CWhplabs!hplnpm!winterp-source\fP.
  2307. .LP
  2308. There is also a mailing list for \fIWinterp\fP-related announcements and
  2309. discussions. To get added to the list, send mail to
  2310. \f(CWwinterp-request@hplnpm.hpl.hp.com\fP or
  2311. \f(CWhplabs!hplnpm!winterp-request\fP.
  2312. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2313. .\"section{}
  2314. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2315. .NH 1
  2316. Acknowledgements
  2317. .LP
  2318. I would like to thank my team-mates Allan Kuchinsky, Allan Shepherd, and
  2319. Bob Leichner for being highly supportive early users of \fIWinterp\fP and
  2320. giving feedback on problems and limitations of the design.  I would also
  2321. like to thank Nancy Kendzierski, manager of HP Labs' Human-Computer
  2322. Interaction Department for providing the support for the development of
  2323. \fIWinterp\fP and \fIStrudel\fP. Also, Nancy Kendzierski, Jim Miller, and
  2324. Allan Kuchinsky provided helpful comments on this paper.
  2325. .LP
  2326. Doug Young deserves special thanks for answering lots of \*Qstupid
  2327. questions\*U I had in working with the Motif and HP widgets and for
  2328. providing early copies of his excellent book on programming with Xt and
  2329. Motif [Young90]. And finally, many thanks are due to David Betz for making
  2330. \fIXlisp\fP publicly available.
  2331. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2332. .\"section{}
  2333. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2334. .NH 1
  2335. Addendum \*- Instructions for Obtaining WINTERP 1.12 via anonymous ftp.
  2336. .LP
  2337. The following instructions give the details of how to obtain \fIWinterp\fP
  2338. sources, examples, and documentation via anonymous ftp on a \fIUnix\fP
  2339. workstation.
  2340. .LS
  2341. Note: In the output below, your input is denoted by '^^^^^^^^^^')
  2342.  
  2343. hplnpm-17-/tmp> ftp export.lcs.mit.edu  (HP-ites, do ftp hplnpm.hpl.hp.com)
  2344.                 ^^^^^^^^^^^^^^^^^^^^^^               ^^^^^^^^^^^^^^^^^^^^^
  2345.         [...]
  2346. Name (hplnpm.hpl.hp.com:mayer): anonymous
  2347.                                 ^^^^^^^^^
  2348. Password (hplnpm.hpl.hp.com:anonymous): <anypassword you want here>
  2349.                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  2350. 331 Guest login ok, send ident as password.
  2351. 230 Guest login ok, access restrictions apply.
  2352. ftp> cd contrib/winterp   (HPites should do cd pub)
  2353.      ^^^^^^^^^^^^^^^^^^                     ^^^^^^
  2354. 200 CWD command okay.
  2355.  
  2356. ftp> type image
  2357.      ^^^^^^^^^^
  2358. 200 Type set to I.
  2359.  
  2360. ftp> get winterp-1.12.tar.Z
  2361.      ^^^^^^^^^^^^^^^^^^^^^^
  2362. 200 PORT command okay.
  2363. 150 Opening data connection for winterp-1.12.tar.Z (15.255.176.225,3988) (1414493 bytes).
  2364. 226 Transfer complete.
  2365. 1414493 bytes received in 690.63 seconds (1.96 Kbytes/sec)
  2366.  
  2367. ftp> quit
  2368.      ^^^^
  2369. 221 Goodbye.
  2370.  
  2371. hplnpm-18-/tmp> zcat winterp-1.12.tar.Z | tar xvf -
  2372.                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  2373.         [... lengthy list of files from tar ...]
  2374.  
  2375. hplnpm-19-/tmp> rm winterp-1.12.tar.Z
  2376.                 ^^^^^^^^^^^^^^^^^^^^^
  2377.  
  2378.    * For compilation tips, take a look at winterp-1.12/doc/COMPILING
  2379.  
  2380.    * For running hints, take a look at winterp-1.12/doc/RUNNING
  2381.  
  2382.    * For known (Motif 1.1 only) bugs, see winterp-1.12/doc/BUGS
  2383.  
  2384.    * For information on the examples, look at winterp-1.12/examples/README
  2385.  
  2386.    * For general information about WINTERP, see winterp-1.12/doc/winterp.doc
  2387. .LE
  2388. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2389. .\"begin{thebibliography} {99}
  2390. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2391. .NH 1
  2392. References
  2393. .XP
  2394. [Betz89] David Michael Betz.  \fIXLISP: An Object-oriented Lisp (version
  2395. 2.1)\fP.  Unpublished documentation accompanying the public domain
  2396. \fIXlisp\fP software release.  David Michael Betz, P.O. Box 144,
  2397. Peterborough, NH 03458, April, 1989. Note: this documentation is included
  2398. in the \fIWinterp\fP source distribution.
  2399. .XP
  2400. [Borenstein88] Nathaniel S. Borenstein and Chris A. Thyberg.  Cooperative
  2401. Work in the Andrew Message System.  In proceedings \fIConference on
  2402. Computer-Supported Cooperative Work\fP, 1988.
  2403. .XP
  2404. [Bourne90] Philip E. Bourne and Lawrence S. Shapiro.  Developing with
  2405. DECwindows.  \fIDEC Professional\fP, vol. 9, no. 2, pp. 36-44, February
  2406. 1990.
  2407. .XP
  2408. [Comer86] D. Comer and L. Peterson.  Conversation-Based Mail.  \fIACM
  2409. Transactions on Computer Systems\fP, vol. 4, no. 4, pp 299-319, November
  2410. 1986.
  2411. .XP
  2412. [Conk87] Jeff Conklin and Michael Begeman.  gIBIS: A Hypertext Tool for
  2413. Team Design Deliberation.  In proceedings \fIHypertext '87 Papers\fP,
  2414. November 1987.
  2415. .XP
  2416. [Creech87a] Michael Creech.  Lisp-C Evaluation Final Report.  Internal
  2417. Technical Report STL-TM-87-18, Hewlett-Packard Laboratories, Software
  2418. Technology Lab, July 9, 1987.
  2419. .XP
  2420. [Creech87b] Michael Creech, Scott Marovich and Niels Mayer.  Lisp-C
  2421. Evaluation Meeting Notes.  Internal Technical Report STL-TM-87-17,
  2422. Hewlett-Packard Laboratories, Software Technology Lab, July 22, 1987.
  2423. .XP
  2424. [Dollimore89] Jean Dollimore and Sylvia Wilbur.  Experiences in building a
  2425. configurable {CSCW} system.  In proceedings \fI1st European Conference on
  2426. CSCW\fP, pp 215-225, September 1989.
  2427. .XP
  2428. [Fikes82] R.E. Fikes.  A Commitment-Based Framework for Describing Informal
  2429. Cooperative Work.  \fICognitive Science\fP, vol. 6, no. 4, pp. 331-347,
  2430. 1982.
  2431. .XP
  2432. [Heimburger] Olaf Heimburger. Elche Im Winter \*- Interaktive
  2433. X-Applicationbuilder unter Lisp \*- Elk und WINTERP. \fIiX\fP, July 1991, pp
  2434. 64-68.
  2435. .XP
  2436. [Holt81] A.W. Holt and P.M. Cashman.  Designing Systems to Support
  2437. Cooperative Activity: An Example.  In \fIProceedings of Compsac 81. IEEE
  2438. Computer Society's Fifth International Computer Software And Applications
  2439. Conference\fP, pp 18-91, November 1981.
  2440. .XP
  2441. [Kaplan90] Simon Kaplan.  COED: A Conversation-oriented tool for
  2442. coordinated design work.  In \fIProceedings of IFIP International Workshop
  2443. on Human Factors in Information Systems\fP, in print, June 1990.
  2444. .XP
  2445. [Lai88] Kum-Yew Lai and Tom Malone.  Object-Lens: A Spreadsheet for
  2446. Cooperative Work.  In proceedings \fIConference on Computer-Supported
  2447. Cooperative Work\fP, September 1988.
  2448. .XP
  2449. [Malone86] Tom Malone, K. Grant, K. Lai, R. Rao, and D. Rosenblitt.
  2450. Semi-structured Messages are Surprisingly Useful for Computer-Supported
  2451. Coordination.  In proceedings \fIConference on Computer-Supported
  2452. Cooperative Work\fP, pp 102-114, December 1986.
  2453. .XP
  2454. [Mayer90a] Niels P. Mayer, Allan W. Shepherd and Allan J. Kuchinsky.
  2455. Winterp: An object-oriented, rapid prototyping, development and delivery
  2456. environment for building extensible applications with the OSF/Motif UI
  2457. Toolkit.  In Proceedings \fIXhibition '90, X Window System and Open Systems
  2458. Technical Conference\fP, San Jose, CA, May 1990, pp 49-64.
  2459. .XP
  2460. [Mayer90b] Niels P. Mayer, Allan W. Shepherd and Allan J. Kuchinsky.  The
  2461. WINTERP Widget INTERPreter \*- An Application Prototyping and Extension
  2462. Environment for OSF/Motif.  In Proceedings \fIX Into The Future, The
  2463. European X Users Group Autumn Conference 1990\fP, Surrey, UK, September
  2464. 1990, pp. 33-55.
  2465. .XP
  2466. [Mayer91] Niels P. Mayer.  The WINTERP Widget INTERPreter \*- A Lisp
  2467. Prototyping and Extension Environment for OSF/Motif-based Applications and
  2468. User-Interfaces.  \fILisp Pointers\fP, \fIACM SIGPLAN\fP, Volume IV, Number
  2469. 1, pp 45-60.
  2470. .XP
  2471. [Myers89] Brad A. Myers.  Tools for Creating User Interfaces: An
  2472. Introduction and Survey.  \fIIEEE Software\fP, vol. 6, no. 1, pp. 15-23,
  2473. January 1989.
  2474. .XP
  2475. [OSF90] Open Software Foundation.  \fIOSF/Motif Series\fP (5 Volumes):
  2476. \fIMotif Style Guide; Programmer's Guide; Programmer's Reference; User's
  2477. Guide; Application Environment Specification; User Environment Volume\fP.
  2478. Prentice-Hall, 1990.
  2479. .XP
  2480. [Reichman85] Rachel Reichman. \fIGetting Computers to Talk Like You and
  2481. Me\fP.  The MIT Press, 1985.
  2482. .XP
  2483. [Rosenberg88] Jarrett Rosenberg (moderator), Ralph Hill, Jim Miller, Andrew
  2484. Schulert, and David Shewmake (panelists).  UIMSs: Threat or Menace?  In
  2485. \fIHuman Factors in Computing Systems\fP, SIGCHI '88, Washington, D.C., May
  2486. 1988, pp. 197-200.
  2487. .XP
  2488. [Rose86] M.T. Rose and J.L. Romine.  \fIThe Rand MH message handling system:
  2489. User's manual, UCI Version 6.5\fP.  University of California, December
  2490. 1986.
  2491. .XP
  2492. [Schulert88] Andrew Schulert and Kate Erf.  Open Dialogue: Using an
  2493. extensible retained object workspace to support a UIMS. In proceedings \fI
  2494. USENIX C++ Workshop\fP, Denver, Colorado, 1988.
  2495. .XP
  2496. [SEI89] Software Engineering Institute.  \fISerpent Overview\fP.
  2497. Technical Report CMU/SEI-89-UG-2, Carnegie Mellon University, Software
  2498. Engineering Institute, August 1989.
  2499. .XP
  2500. [Searle76] John R. Searle.  A Taxonomy of Illocutionary Acts.  In K.
  2501. Gunderson, editor, \fILanguage, Mind and Knowledge\fP University of
  2502. Minnesota Press, 1976.
  2503. .XP
  2504. [Shepherd90] Allan Shepherd, Niels Mayer, and Allan Kuchinsky.  Strudel: An
  2505. Extensible Electronic Conversation Toolkit.  In proceedings \fIConference
  2506. on Computer-Supported Cooperative Work\fP, Los Angeles, October 1990, pp. 93-104.
  2507. .XP
  2508. [Stallman87] Richard M. Stallman.  \fIGNU Emacs Manual\fP.  Free Software
  2509. Foundation, 675 Massachusetts Ave., Cambridge, MA 02139, 1987.
  2510. .XP
  2511. [Sulonen90] Reijo Sulonen and Panu Pietikainen.  Forget-Me-Not \*-
  2512. Controlling intercompany operations by intelligent mail.  In \fIProceedings
  2513. 23rd Annual Hawaii International Conference on Systems Sciences\fP, pp.
  2514. 428-435, 1990.
  2515. .XP
  2516. [Trigg86] Randall Trigg, Lucy A. Suchman, and Frank G. Halasz.  Supporting
  2517. Collaboration in NoteCards.  In \fIConference on Computer-Supported
  2518. Cooperative Work\fP, December 1986.
  2519. .XP
  2520. [Winograd86] Terry Winograd and Fernando Flores.  \fIUnderstanding
  2521. computers and cognition, A new foundation for design\fP.  Ablex, Norwood
  2522. New Jersey, 1986.
  2523. .XP
  2524. [Winograd87] Terry Winograd.  A Language/Action Perspective On The Design
  2525. Of Cooperative Work.  Technical Report CSLI-87-98, Stanford University,
  2526. 1987.
  2527. .XP
  2528. [Young90] Douglas A. Young.  \fIThe X Window System: Programming and
  2529. Applications With Xt, OSF/Motif Edition\fP.  Prentice Hall, 1990.
  2530. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2531. .\"end{thebibliography}
  2532. .\"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2533.