CLIM on Genera 8.3 [Updated]

In preparation of doing some actual software engineering on Genera, I decided to take a look at the CLIM implementation on my MacIvory III Genera 8.3.

There are a few steps to do first:

  • Load System CLIM: This will take a while. It loads a lot of files and several subsystems, including:
    • Loading system CLIM version 66
    • Initializing subsystem CLIM Utilities
    • Initializing subsystem CLIM Silica
    • Initializing subsystem CLIM Standalone
    • Initializing system CLIM version 66
    • Loading patches for system CLIM version 66
    • Patches for CLIM (Current version is 66.3):
  • If you attempt to use CLIM at this point, however, it won't work because there is no driver (in my parlance only, I'm not sure the official term). The example code will fail: Error: Cannot find port type: :GENERA
  • Load System Genera-CLIM will install the remaining parts

This whole process takes probably 15+ minutes of compiling and crunching, so you might want to save the world and restart after this (although I didn't do this yet).

Oddly enough, at this point, I figured I'd read the CLIM documentation online in the Document Examiner, but alas, it doesn't seem to have it there even if I ask it to show candidates.

Anyway, as usual, Bitsavers has the docs so I decided to follow along with the tutorial to run the puzzle-1.lisp example. (Reproduced at the end.)

To back up one step, let me mention how I have my development environment set up. I have the MacIvory III configured in a Mac Quadra 950 running Mac OS 8 with a SuperMac Thunder II GX running on a Dell 2007FP LCD, but unfortunately only running at 1360x1024 (since I don't have a monitor which can do 1600x1200 at 75Hz on VGA). I couldn't get my second Ethernet card to work (due to a bug in the Genera Ethernet control panel under Mac OS 8) so when Genera is running, the Mac is not on the LAN.

I run Genera, and leave it and the Mac running, but I turn off the monitors and lock the Mac's keyboard/mouse. Then I Telnet into Genera, Start X Screen twice to my iMac, and then Halt Remote Terminal (which ends the Telnet session). In the X screen, I use my Tenkeyless Enhanced keyboard layout with my custom WASD keyboard.

Back to CLIM. When I first ran the demo:

(setq fp1 (make-application-frame 'fifteen-puzzle-1
        :left 200 :right 400 :top 150 :bottom 350))
(run-frame-top-level fp1)

By selecting this and hitting c-sh-E in Zmacs, nothing happened, although Zmacs kept telling me it was executing the CLIM program. I couldn't figure it out. Furthermore, I couldn't get my nicely mapped ABORT button to do anything, nor c-ABORT. (It took me a while to remember to do c-m-ABORT which worked.) Turns out I had to tell System Preferences in the Mac (OS X.11) to unmap ^F8 from "Move focus to the status menus."

Anyway, I abort and restart the program a few times, both from Zmacs and a Lisp Listener ((clim:run-frame-top-level clim-user::fp1)). Finally I power on the MacIvory screen running Genera and, voila, the puzzle window is running on the console.

Well, needless to say, I may have to not use CLIM to do my Genera development, because I need (well, want) everything to work over an X screen.

Genera CLIM Puzzle Toy v1

Documentation [Updated]

I searched and found that the CLIM documentation was indeed on my filesystem, at ARGON:>sys>doc>clim>. I tried Read Private Document on the various .sab files, but nothing would show up in Document Examiner.

In there was an attractive looking LISP file, clim-doc.lisp, that had lots of interesting references to documentation. So I Load Filed it, but no luck.

Then I typed Load System and COMPLETE and, voila, CLIM Documentation showed up as an available system to load. Actually, it showed up twice (not sure why). I loaded it, and boom, I had my documentation.

Loading CLIM Documentation System CLIM Documentation in Examiner

TODOs

  • Figure out how to get CLIM to run over CLX, which can be loaded using Load System CLX-CLIM

Puzzle-1 Source

;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; Package: CLIM-USER; Base: 10; Lowercase: Yes -*-
;;;>
;;;> *****************************************************************************************
;;;> ** (c) Copyright 1993 Symbolics, Inc.  All rights reserved.
;;;> ** Portions of font library Copyright (c) 1984 Bitstream, Inc.  All Rights Reserved.
;;;>
;;;>    The software, data, and information contained herein are proprietary 
;;;> to, and comprise valuable trade secrets of, Symbolics, Inc., which intends 
;;;> to keep such software, data, and information confidential and to preserve 
;;;> them as trade secrets.  They are given in confidence by Symbolics pursuant 
;;;> to a written license agreement, and may be used, copied, transmitted, and 
;;;> stored only in accordance with the terms of such license.
;;;> 
;;;> Symbolics, Symbolics 3600, Symbolics 3670 (R), Symbolics 3675 (R), Symbolics
;;;> 3630, Symbolics 3640, Symbolics 3645 (R), Symbolics 3650 (R), Symbolics 3653,
;;;> Symbolics 3620 (R), Symbolics 3610 (R), Symbolics Common Lisp (R),
;;;> Symbolics-Lisp (R), Zetalisp (R), Genera (R), Open Genera, Virtual Lisp Machine,
;;;> VLM, Wheels (R), Dynamic Windows (R), SmartStore (R), Semanticue (R), Frame-Up (R),
;;;> Firewall (R), Document Examiner (R), Delivery Document Examiner, Ivory, MacIvory,
;;;> MacIvory model 1, MacIvory model 2, MacIvory model 3, XL400, XL1200, XL1201,
;;;> Symbolics UX400S, Symbolics UX1200S, NXP1000, Symbolics C, Symbolics Pascal (R),
;;;> Symbolics Prolog, Symbolics Fortran (R), CLOE (R), CLOE Application Generator,
;;;> CLOE Developer, CLOE Runtime, Common Lisp Developer, Symbolics Concordia, Joshua,
;;;> Statice (R), and Minima are trademarks of Symbolics, Inc.
;;;> 
;;;> RESTRICTED RIGHTS LEGEND
;;;>    Use, duplication, and disclosure by the Government are subject to restrictions 
;;;> as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data and Computer 
;;;> Software Clause at DFAR 52.227-7013.
;;;> 
;;;>      Symbolics, Inc.
;;;>      6 Concord Farms
;;;>      555 Virginia Road
;;;>      Concord, Massachusetts 01742-2727
;;;>      United States of America
;;;>      508-287-1000
;;;>
;;;> *****************************************************************************************
;;;>

(define-application-frame fifteen-puzzle-1 ()
    ((pieces :initform (make-array '(4 4) :initial-contents '((1 2 3 4)
                                  (5 6 7 8)
                                  (9 10 11 12)
                                  (13 14 15 0)))))
  (:menu-bar nil)
  (:panes
    (display :application
         :text-style '(:fix :bold :very-large)
         :display-function 'draw-the-display
         :scroll-bars nil)
    (menu :command-menu))
  (:layouts
    (main 
      (vertically () display menu))))

;;; this draws the entire display

(defmethod draw-the-display ((application fifteen-puzzle-1) stream)
  (with-slots (pieces) application
    (dotimes (y 4)
      (dotimes (x 4)
    (let ((piece (aref pieces y x)))
      (if (zerop piece)
          (format stream "   ")
          (format stream "~2D " piece))))
      (terpri stream))))

;;; useful macrology - the body will be run with x and y bound to
;;; the coordinates of the empty cell

(defmacro find-empty-piece-and-do ((y x) &body body)
  `(block find-empty-piece
     (dotimes (,y 4)
       (dotimes (,x 4)
     (when (zerop (aref pieces ,y ,x))
       ,@body
       (return-from find-empty-piece))))))

(define-fifteen-puzzle-1-command (down :menu t) ()
  (with-slots (pieces) *application-frame*
    (find-empty-piece-and-do (y x)
      (if (not (zerop y))
      (rotatef (aref pieces y x) (aref pieces (- y 1) x))))))

(define-fifteen-puzzle-1-command (up :menu t) ()
  (with-slots (pieces) *application-frame*
    (find-empty-piece-and-do (y x)
      (if (not (= y 3))
      (rotatef (aref pieces y x) (aref pieces (+ y 1) x))))))

(define-fifteen-puzzle-1-command (left :menu t) ()
  (with-slots (pieces) *application-frame*
    (find-empty-piece-and-do (y x)
      (if (not (= x 3))
      (rotatef (aref pieces y x) (aref pieces y (+ x 1)))))))

(define-fifteen-puzzle-1-command (right :menu t) ()
  (with-slots (pieces) *application-frame*
    (find-empty-piece-and-do (y x)
      (if (not (zerop x))
      (rotatef (aref pieces y x) (aref pieces y (- x 1)))))))

#||
()
(setq fp1 (make-application-frame 'fifteen-puzzle-1
        :left 200 :right 400 :top 150 :bottom 350))
(run-frame-top-level fp1)
||#

Douglas Fields

Writing LISP and Haskell since 1990