1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
|
\documentstyle[11pt]{article}
\setlength{\textwidth}{6in}
\setlength{\textheight}{8.75in}
\setlength{\topmargin}{-0.25in}
\setlength{\oddsidemargin}{0.25in}
\newcommand{\macbold}[1]{{\bf #1}}
\newcommand{\dcode}[1]{{\tt #1}}
\newcommand{\LS}{Lisp}
\newcommand{\XLS}{XLISP-STAT}
\newcommand{\WXLS}{WXLS}
\newcommand{\LSE}{LSPEDIT}
\newcommand{\lfun}[1]{{\tt #1}}
\newcommand{\lkeyword}[1]{{\tt :#1}}
\newcommand{\NIL}{{\tt nil}}
\newcommand{\TRUE}{{\tt t}}
\title{\XLS\ for Microsoft Windows 3.1}
\author{Luke Tierney\\School of Statistics\\University of Minnesota}
\begin{document}
\maketitle
\section{Basics}
This note outlines an implementation of \XLS\ for Microsoft Windows
3.1. The executable is called \WXLS. \WXLS\ must be run in protected
mode and requires at least a 386 processor with at least 2MB of
memory. Only one instance of \WXLS\ can be run at one time. A Win32
version is now available as well. The Win32 executable is called
\WXLS32. It requires Win32s to run under Windows 3.1.
This implementation uses an MDI-style interface. The listener,
graphics windows, and modeless dialog windows are subwindows of an
MDI client window. Menus appear in the client window's menu bar. The
implementation is quite similar to the Macintosh version. This note
assumes you are familiar with the description of the Macintosh version
given Appendix B.2 of Tierney~(1990).
The current implementation is experimental; the current release at the
time of writing is {\em 3.39}. I have only tested this version on a
486DX2 computer with 16MB of memory and a math coprocessor. Please let
me know if you run into any problems. A detailed description of the
problem and the hardware configuration would be most helpful.
\subsection{The Listener}
The listener provides parenthesis matching. Hitting the {\em tab}\/
key indents code to an appropriate level. The listener follows
standard Windows 3.1 conventions for handling arrow keys, cut and
paste accelerators, etc.. In addition, hitting {\em SHIFT-ENTER}\/
moves the cursor to the end of the current input expression.
Hitting and holding down {\em CONTROL-BREAK}\/ should interrupt the
current calculation. You may need to wait a bit since key events are
only checked periodically during calculations.
Closing the listener is equivalent to minimizing it; you cannot remove
the listener. Minimizing a graphics window is equivalent to hiding
(i.e. sending it the \dcode{:hide-window} message). Closing a graph
window removes it.
\subsection{Editing Files}
A separate program, \LSE, provides a very simple \LS\ file
editor.\footnote{This editor is based on the code examples in
Microsoft (1990).} Like the listener, \LSE\ supports parenthesis
matching and code indentation. In addition, the \macbold{Edit} menu in
\LSE\ contains an item for pasting a selected expression into an \XLS\
application. This is accomplished using the Windows Dynamic Data
Exchange (DDE) mechanism. It seems to work with one instance of \LSE\
and one of \XLS\ running. It should also work if there are multiple
instances of \LSE\ running. It would get very confused if there were
multiple instances of \XLS, but the current version does not allow
this.
\subsection{Menus}
As with the Macintosh version, menus can be installed in and removed
from the menu bar by sending them the \dcode{:install} and
\dcode{:remove} messages. The \macbold{File} and \macbold{Edit} menus
that appear in the menu bar on startup are \LS\ menus. They are the
values of the global variables \dcode{*file-menu*} and
\dcode{*edit-menu*}. The third menu, the \macbold{Windows} menu, is
part of the MDI interface and is {\em not}\/ a \LS\ menu; you cannot
change or remove it.
When a graphics window is the front window and you select the
\macbold{Copy} item from the \macbold{Edit} menu, a copy of the graph
is placed in the clipboard. This is done by turning on buffering,
sending the window the \dcode{:redraw} message, copying the contents
of the buffer to a bitmap, and placing that bitmap in the clipboard.
\subsection{User Preferences}
User preferences can be set in a file {\tt wxls.ini} (or {\tt
wxls32.ini} for the Win32 version) in the windows system directory.
This file can contain several variables in sections {\tt [Xlisp]},
{\tt [Listener]}, and {\tt [Graphics]}:
\begin{center}
\begin{tabular}{ll}
Section & Variables\\
\hline
{\tt [Xlisp]} & {\tt Libdir}, {\tt Workspace}\\
{\tt [Listener]} & {\tt Font}, {\tt FontSize}\\
{\tt [Graphics]} & {\tt Font}, {\tt FontSize}, {\tt Color}\\
\hline
\end{tabular}
\end{center}
The {\tt Libdir} variable should be set to the directory containing
the executable and runtime files; this should be done at installation
time by loading {\tt config.lsp}. The {\tt Workspace} variable allows
an alternate initial workspace to be specified. Both can be overridden
on the command line by specifying {\tt -d} or {\tt -w} options,
respectively. The {\tt Color} variable can be used to turn color use
off if allocating a color background buffer would require too much
memory. As an example, a {\tt wxls.ini} file containing
\begin{verbatim}
[Xlisp]
Libdir=C:\WXLS
[Listener]
Font="Courier New Bold"
FontSize=13
[Graphics]
Color=off
\end{verbatim}
specifies a library directory, a listener font, and turns color off.
\subsection{Miscellaneous Notes}
The feature \dcode{msdos} is included in the \dcode{*features*} list
and can be used for conditional evaluation of DOS-specific code.
Since the DOS operating system uses the backslash character \verb+\+
as the directory separator and the backslash character is also the
\LS\ escape character, a file name string that is specified within
\XLS, for example as an argument to the \dcode{load} command, must be
entered with two backslashes. For example, a file \dcode{foo.lsp} in
the subdirectory \dcode{bar} of the current directory would be loaded
using
\begin{verbatim}
(load "bar\\foo.lsp")
\end{verbatim}
or by
\begin{verbatim}
(load "bar\\foo")
\end{verbatim}
if the \dcode{.lsp} extension is dropped.
DOS imposes an 8-character limit on base file names. When asked to
access a file with a longer base name, file system functions truncate
the base name to 8 characters. Thus
\begin{verbatim}
(load "regression.lsp")
\end{verbatim}
is equivalent to
\begin{verbatim}
(load "regressi.lsp")
\end{verbatim}
If you have files that uses a longer name on other systems you can
therefore truncate their names as long as they are unique in the first
8 characters.
There are several features that are either missing, not yet
implemented, or only partially implemented:
\begin{itemize}
\item Clipping is not yet implemented in the graphics system. I have
not yet figured out how to remove clip regions from a device
context.
\item A mouse is essentially required for the graphics windows and
dialogs. A proper alternate keyboard interface is not yet
available.
\item Listener and graphics windows do not have a maximize button. The
reason for this is that strange things seem to happen when the menu
bar is modified while windows are maximized. You can maximize the
MDI frame and then resize windows within the frame.
\item \WXLS\ has access to all the memory Windows makes available to
it, but because of the segmented architecture of the 80X86
processor, no single item larger than 64K can be allocated. This
limits the total number of elements in a \LS\ array to 16K and the
total size of a numerical array used in the linear algebra functions
to about 8K elements. There is little guarantee that violations of
these limits will be handled gracefully. This limitation does not exist
in the Win32 version \WXLS32.
\item The Win16 version has a system stack of only 20K. The Win32 version is
limited to a system stack of about 70K when run under Win32s, but should
have a much larger stack of 250K under Windows NT.
\end{itemize}
\section{More Advanced Features}
\subsection{Dynamic Link Libraries}
Dynamic link libraries can be used from both \WXLS\ and \WXLS32, but
\WXLS\ can only use 16-bit DLL's and \WXLS32 can only use 23-bit
DLL's.
Dynamic Link Libraries (DLL's) can be used to provide additional
cursor resources created with SDK or other toolkits, or to provide
dynamically callable subroutines. The file \dcode{xlsx.c} contains
startup and cleanup code for a DLL that seems to work with Borland
C++. This code can be linked with cursor resources or with code into a
DLL.
Once you have a DLL, the function \dcode{load-dll} can be used to load
a DLL. The return value of this function is an integer representing
the DLL handle. The function \dcode{free-dll} can be used to release
the library.
\subsection{Cursors}
When the \dcode{make-cursor} function is used to load a cursor from a
DLL it is given three arguments. The first is a symbol naming the
cursor. The second is an integer representing a DLL handle (the DLL
must have been loaded with \dcode{load-dll}). The third argument can
be either an integer resource index or a string naming the cursor
resource. If the DLL \dcode{stick.dll} contains a cursor resource
defined by a resource file line like
\begin{verbatim}
Stick CURSOR STICK.CUR
\end{verbatim}
then it can be loaded as a cursor named \dcode{stick} using the
expressions
\begin{verbatim}
(setf stick-dll (load-dll "stick.dll"))
\end{verbatim}
to load the library and
\begin{verbatim}
(make-cursor 'stick stick-dll "Stick")
\end{verbatim}
to load the cursor.
The function \dcode{msw-cursor-size} returns a list of the width and
height of a cursor on the graphics device. \XLS\ expands or truncates
arrays supplied as arguments to \dcode{make-cursor} to this size.
\subsection{Dynamic Loading}
Subroutines in DLL's can also be called from within \XLS. The
subroutine should be defined as for dynamic loading on the Macintosh
and should use C, not Pascal, calling conventions. The header file
\dcode{xlsx.h} contains the required definitions and macros. The
\dcode{call-cfun} function requires two arguments to identify the
routine to be loaded, a DLL handle and an ordinal index or a name
string. Suppose the file \dcode{foo.c} shown on page 362 of Tierney
(1990) is linked with the DLL code \dcode{xlsx.c} using the module
definition file \dcode{foo.def} given by
\begin{verbatim}
LIBRARY FOO
EXETYPE WINDOWS
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD MOVEABLE SINGLE
EXPORTS FOO=_foo
WEP
\end{verbatim}
If the DLL is loaded as
\begin{verbatim}
(setf foo-dll (load-dll "foo.dll"))
\end{verbatim}
then the routine \dcode{foo} can be called using either
\begin{verbatim}
(call-cfun foo-dll "foo" 5 (float (iseq 1 5)) 0.0)
\end{verbatim}
or
\begin{verbatim}
(call-cfun foo-dll 1 5 (float (iseq 1 5)) 0.0)
\end{verbatim}
The second approach works since \dcode{foo} is the first routine in
the exports table.
\subsection{Dynamic Data Exchange}
A very minimal DDE interface is provided. The interface is very simple
and based on the DDEML library. As a server, WXLS allows connections
to the topic {\tt XLISP-STAT} under the service name {\tt XLISP-STAT}.
It accepts two kinds of transactions:
\begin{itemize}
\item Execute transactions in which the command is a sequence of lisp
expressions. The LSPEDIT application sends the current selection as
an execute transaction when the {\bf Eval Selection} menu item is
chosen.
\item Request transactions for the item {\tt VALUE}. This returns a
string with a printed representation of the value returned by the
last expression in the most recent execute transaction of the
conversation.
\end{itemize}
As a client, there are three functions you can use that correspond
fairly closely to their DDEML equivalents: \lfun{dde-connect},
\lfun{dde-disconnect}, and \lfun{dde-client-transaction}.
\lfun{dde-connect} takes two arguments, strings naming a service and
a topic. The topic string is optional; it defaults to the service
string. The return value is a descriptor of the conversation if the
connection is established, otherwise it is \NIL. At the moment
conversation descriptors are integer indices into a table, and the
number of concurrent conversation is limited to 30. This may change.
\lfun{dde-disconnect} takes a conversation descriptor and attempts to
close the conversation. If successful it returns \TRUE, otherwise
\NIL. If dde-disconnect is called with no arguments, then all
currently active conversations are terminated. In this case the return
value is \TRUE\ if any are terminated, \NIL\ if not.
\lfun{dde-client-transaction} requires a conversation descriptor as
its first argument. The remaining arguments are keyword arguments:
\begin{description}
\item \lkeyword{type}: should be \lkeyword{request} or
\lkeyword{execute}; the default is \lkeyword{execute}.
\item \lkeyword{data}: a string, currently only used by execute
transactions.
\item \lkeyword{item}: an item name string, currently only used by
request transactions.
\item \lkeyword{timeout}: a positive integer specifying the timeout in
milliseconds. The default is 60000.
\end{description}
The return value is \TRUE\ if the transaction is successful, \NIL\ if
not.
As an example, you could have WXLS communicate with WXLS by DDE (why
you would want to I do not know, but it works):
\begin{verbatim}
> (dde-connect "xlisp-stat")
0
> (dde-client-transaction 0 :data "(+ 1 2)")
T
> (dde-client-transaction 0 :type :request :item "value")
"3"
> (dde-disconnect 0)
T
\end{verbatim}
You can also communicate with the program manager:
\begin{verbatim}
> (dde-connect "progman")
0
> (dde-client-transaction 0 :data "[ShowGroup(Main,1)]")
T
> (dde-client-transaction 0 :type :request :item "Groups")
"Main\r
Accessories\r
Applications\r
Microsoft C/C++ 7.0\r
Software Development Kit 3.1\r
Win32 Applications\r
Adobe\r
Borland C++ 4.0 Online Books\r
Borland C++ 4.0\r
StartUp\r
Games\r
Borland C++ 3.1\r
Pocket Tools\r
XLISP-STAT Programs\r
"
> (dde-disconnect 0)
T
\end{verbatim}
The first transaction is an execute transaction that opens the Main
group's window. The second is a request that obtains a list of the
current groups.
This DDE interface is experimental and may change. For the moment it
seems adequate for providing configuring the integration of WXLS into
Windows during setup.
\subsection{Other Functions}
The function \dcode{msw-free-mem} returns the total amount of free
global memory that is available in Windows.
The \dcode{system} function takes a command string and an optional
state argument and \dcode{WinExec}'s the command string. If the
command starts a windows application then the application starts
iconified if the state arguments is \dcode{nil} and normal if the
argument is \dcode{t}, the default. Thus
\begin{verbatim}
(system "clock")
\end{verbatim}
starts up a clock in normal state and
\begin{verbatim}
(system "clock" nil)
\end{verbatim}
starts up an iconified clock. The result returned is either \dcode{t}
if the {\tt WinExec} succeeds or \NIL\ if it fails. On failure,
anumerical error code is returned as the second value.
The function \dcode{msw-win-help} provides a minimal interface to the
windows \dcode{WinHelp} function. Two arguments are required, a string
naming the help file to be used, and a symbol specifying the type of
help requested. The keyword symbols \lkeyword{help},
\lkeyword{context}, \lkeyword{index}, \lkeyword{key}, and
\lkeyword{quit} are currently supported. Context help requires an
additional integer argument, and key help requires an additional key
string. For example,
\begin{verbatim}
(msw-win-help "calc.hlp" :index)
\end{verbatim}
opens help for the calculator application at the contents section. No
Windows help file for \XLS\ is available at this time, but this
function provides the necessary hook for using such a file if it
becomes available.
The functions \lfun{msw-tile}, \lfun{msw-cascade},
\lfun{msw-close-all}, and \lfun{msw-arrange-icons} implement the
corresponding actions on the Windows menu. These functions take no
arguments.
The functions \lfun{msw-get-profile-string} and
\lfun{msw-write-profile-string} can be used to access and modify user
preference information. They require three and four arguments,
respectively. The first and second arguments specify the section and
item names as strings, and the last argument specifies the preference
file name. A preference file name of \NIL\ refers to the system
preference file. For \lfun{msw-write-profile-string} the third
argument is a new value. This can be a string or \NIL; if it is \NIL,
the entry is deleted. This function deletes a section if the item
argument is \NIL.
\subsection{Recompiling the System}
If you want to recompile the system you can do so, but you have to
start with a compiled version of the compiler. The system stack
available under Windows is very small -- only 20K compared to 180K on
the Macintosh version -- and is not sufficient for recompiling the
compiler from {\tt .lsp} files. You can recompile the compiler as long
as you start with a compiled version.
\section*{References}
\begin{description}
\item[]
Microsoft Corporation, (1990). {\em Microsoft Windows Guide to
Programming}. Redmond, WA: Microsoft.
\item[]
Tierney, L. (1990). {\em LISP-STAT: An Object-Oriented Environment for
Statistical Computing and Dynamic Graphics}. New York, NY: Wiley.
\end{description}
\end{document}
|