From: tenaglia@mis.mcw.edu
Newsgroups: comp.lang.icon
Subject: X-Icon Sample Program
Date: 11 Sep 92 07:56:11 CDT
Organization: Medical College of Wisconsin


I imagine X-Icon hasn't caught on real big yet, however, I'd like to post
a sample. It's a doodler of recursive Sierpinski triangles. The mouse is
polled as is the keyboard. The code could probably be better, but I thought
we could get a few more X-Icon posts going by getting out some samples.

Chris Tenaglia (System Manager) |  "The past explained,     
Medical College of Wisconsin    |   the future fortold, 
8701 W. Watertown Plank Rd.     |   the present largely appologized for."
Milwaukee, WI 53226             |   Organon to The Doctor
(414)257-8765                   |     
tenaglia@mis.mcw.edu

#
# FILE : SIER.ICN
# DESC : DRAWS SIERPINSKI TRIANGLES IN X-WINDOWS
# USAGE: ICONX SIER WIDTH HEIGHT
#        WIDTH AND HEIGHT ARE USED TO SIZE THE XWINDOW. THREE RANDOM POINTS
#        ARE AUTOMATICALLY CHOOSEN. 2000 DOTS PER TRIANGLE IS THE DEFAULT.
#        THE MOUSE IS USED TO ADJUST THINGS.
#        MOUSE BUTTON 1 -- SET A TRIANGLE CORNER
#        MOUSE BUTTON 2 -- SET THE NUMBER OF DOTS TO PLOT  (ALSO "D")
#        MOUSE BUTTON 3 -- START DRAWING TRIANGLE          (ALSO "C")
#        ALSO "S" SAVES THE PICTURE TO SIERPINSKI.IMG
#        ALSO "E" ERASES THE PICTURE SO YOU CAN START OVER
#        ALSO "Q" QUITS THE PROGRAM
#
# UPDATE          BY          WHAT
# 11-SEP-1992     TENAGLIA    INITIAL PORT FROM ADEX CHROMAGRAPH & C
#

global VW,VH,yes,x,ox,y,oy,xw,yw,
       wl,wr,wt,wb,CW,CR,mode,answer,
       xwindow,px,py,lines,columns,pass

procedure main(param)
  setup(param)
  until (answer ~== yes) & (trim(answer) ~== "") do
    {
#
#  LOAD THE SEED MATRIX TO DETERMINE THE INITIAL DIMENSIONS
#
    every i := 1 to 3 do
      {
      px[i]   := ?VW
      px[i+3] := px[i]
      py[i]   := ?VH
      py[i+3] := py[i]
      }
#
# ALLOW MOUSE TO CHANGE THE TRIANGLE CORNER POINTS
#
    XDrawPoint(xwindow,px[1],py[1],px[2],py[2],px[3],py[3])
    adjust()

#
#  DRAW THE INITIAL OUTLINE OF THE TRIANGLE  AND SET SEED NUMBERS
#
    XDrawLine(xwindow,px[1],py[1],px[2],py[2],px[3],py[3],px[1],py[1])

    h := ?VW
    v := ?VH

#
#  THIS IS THE MAIN DRAWING LOOP FOR THE RECURSIVE TRIANGLE
#
    writes(at(24,1),blink("Drawing...."))
    every times := 1 to mode do
      {
      p   := ?6     # PICK SOME INTERESTING PLACE
      h1  := px[p]
      v1  := py[p]
      h   := integer(real((h1 - h) / 2.0 + h))
      v   := integer(real((v1 - v) / 2.0 + v))
      XDrawPoint(xwindow,h,v)
      }
   }
  close(xwindow)
  end

#
# SETUP INITIAL GLOBAL PARAMETERS AND CONSTANTS
#
procedure setup(items)
  VW    := integer(items[1]) | 500
  VH    := integer(items[2]) | 400
  mode  := 2000
  yes   := "y"

  OX    := 0
  OY    := 0
  xw    := VW - 2 * OX
  yw    := VH - 2 * OY
  pass  := 0

  wl    := -xw/2
  wr    := - wl
  wb    := -yw/2
  wt    := - wb
  px    := [0,0,0,0,0,0]
  py    := [0,0,0,0,0,0]

  lines    := integer(VH / 14.22 + 0.5)
  columns  := integer(VW /  5.69 + 0.5)
  &random  := map(&clock,":","0")
  answer   := yes

  (xwindow := open("SIERPINSKI","x",
                   "x=" || VW,"y=" || VH,
                   "bg=black","fg=white",
                   "lines=" || lines,"columns=" || columns)) |
    {
    write("Can't open window. Press <RETURN>")
    stop("ABEND ANOX")
    }
  XSync(xwindow)
  XSetStipple(xwindow,8,0)
  end

#
# PROMPT FOR AN INPUT STRING
#
procedure input(prompt)
  writes(prompt)
  return read()
  end

#
# ALLOW MOUSE TO ADJUST THE TRIANGLE CORNER POINTS
#
procedure adjust()
  i := 1
  writes(cls())
  write("+---------------------------------------------+")
  write("|                                             |")
  write("| Press M1 to plant a corner                  |")   
  write("| Press M2 to set the dot count               |")
  write("| Press M3 or enter 'C' to start plotting     |")
  write("| Enter E  to Erase window                    |")
  write("| Enter S  to Save window                     |")
  write("| Enter Q  to Quit program                    |")
  write("+---------------------------------------------+")
  write(at(2,20),"Sierpinski Triangle # ",pass)
  byte := ""                      
  while byte := map(XEvent(xwindow)) do
    {
    xy := []
    every put(xy,XQueryPointer(w))
    x := xy[1] - 10 ; y := xy[2] - 40
    case byte of
      {
      string(&lpress) :
        {
        XDrawPoint(xwindow,px[i],py[i])
        px[i]   := x
        px[i+3] := x
        py[i]   := y
        py[i+3] := y
        XDrawPoint(xwindow,x,y)
        if (i +:= 1) > 3 then i := 1
        }
      string(&mpress) | "D" | "d" :
        {
        tmp := open("DOT QUANTITY","x","font=-*-Terminal-*-*-*-*-*-*-*-*-*-160-*-*")
        write(tmp,"How many dots to plot")
        itera := read(tmp)
        if not(numeric(itera)) then
          {
          write(tmp,"\7Numeric input needed. Press <RETURN>")
          read(tmp)
          close(tmp)
          byte := ""
          XFlush(xwindow)
          next
          }
        close(tmp)
        mode := itera
        }
      string(&rpress) | "C" | "c" :
        {
        write(at(2,20),"Sierpinski Triangle # ",(pass+:=1))
        return
        }
      "S" | "s" :
        {
        writes(at(24,1),blink("Writing Image to sierpinski.img"))
        XWriteImage(xwindow,"sierpinski.img")
        writes(at(24,1),"\e[K\7")
        }
      "E" | "e" : { XEraseArea(xwindow,0,0,0,0) ; pass := 0 }
      "Q" | "q" : stop(at(23,1),"X SIERPINSKI cancelled")
      default   : &null
      }
    byte := ""
    XFlush(xwindow)
    }
  end

#
# PROCEDURE USES ANSI SEQUENCE TO SET CURSOR TO SCREEN LOCATION
#
procedure at(row,column)
  return "\e[" || row || ";" || column || "f"
  end

#
# PROCEDURE RETURNS AN ANSI BLINKING STRING
#                                
procedure blink(str)
  return "\e[5m" || str || "\e[m"
  end
  
#
# PROCEDURE RETURNS AN ANSI STRING TO CLEAR THE TERM WINDOW
#
procedure cls()
  return "\e[2J\e[H"
  end