home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.arizona.edu
/
ftp.cs.arizona.edu.tar
/
ftp.cs.arizona.edu
/
icon
/
historic
/
v941.tgz
/
icon.v941src.tar
/
icon.v941src
/
ipl
/
gprocs
/
tieedit.icn
< prev
next >
Wrap
Text File
|
2002-01-24
|
23KB
|
877 lines
############################################################################
#
# File: tieedit.icn
#
# Subject: Procedures to create and edit binary arrays
#
# Authors: Ralph E. Griswold and Gregg M. Townsend
#
# Date: January 19, 2002
#
############################################################################
#
# This file is in the public domain.
#
############################################################################
#
# This package provides a variety of facilities for creating and
# editing binary arrays. It is intended for use with weaving tie-ups
# and liftplans.
#
############################################################################
#
# Requires: Version 9 graphics, /tmp
#
############################################################################
#
# Links: interact, patxform, vdialog, vsetup, dialog, wopen
#
############################################################################
link interact
link patxform
link vdialog
link vsetup
link dialog
link wopen
global cellsize
global flip_horiz # icon for horizontal flip
global flip_left # icon for left flip
global flip_right # icon for right flip
global flip_vert # icon for vertical flip
global grid_height
global grid_pane
global grid_root
global grid_rows
global grid_state
global grid_window
global grid_width
global grid_vidgets
global hbits # number of bits horizontally
global hi_horiz # highlighted icon for h-flip
global hi_ident # highlighted icon for identity
global hi_left # highlighted icon for l-flip
global hi_right # highlighted icon for r-flip
global hi_rot_180 # highlighted icon for 180 rot
global hi_rot_90 # highlighted icon for 90-rot
global hi_rot_m90 # highlighted icon for -90 rot
global hi_vert # highlighted icon for v-flip
global ident # icon for identity
global maxsize # maximum grid dimensions
global mode # pattern/tile display mode
global old_pat # old pattern for undo
global rotate_180 # icon for 180-degree rotation
global rotate_90 # icon for 90-degree rotation
global rotate_m90 # icon for -90-degree rotation
global subservient # application status
global sym_image_current # current drawing images
global sym_image_next # next drawing images
global sym_state # drawing state
global symmet_xpos
global symmet_yoff
global symmetries # general symmetry state
global tile_touched # tile modification switch
global vbits # number of bits veritcally
global xform_xpos
global xform_ypos
$define MaxCell 24 # maximum size of grid cell
$define IconSize 16 # size of button icons
$define MaxPatt 32
$define InfoLength 40 # length of lines in info box
record pattrec(tile)
procedure copy_tile()
local output
output := open("/tmp/tieclip", "w") | {
Notice("Cannot copy tile.")
fail
}
write(output, rows2pat(grid_rows))
close(output)
return
end
# draw editing grid
procedure grid()
local x, y
EraseArea(grid_pane)
every x := 0 to hbits * cellsize by cellsize do
DrawLine(grid_pane, x, 0, x, vbits * cellsize)
every y := 0 to vbits * cellsize by cellsize do
DrawLine(grid_pane, 0, y, hbits * cellsize, y)
return
end
# editing grid
procedure grid_cb(vidget, e)
local x, y, i, j
static xpos, ypos
initial {
xpos := grid_vidgets["grid"].ax
ypos := grid_vidgets["grid"].ay
}
if e === (&lpress | &rpress | &ldrag | &rdrag) then {
j := (&x - xpos) / cellsize
i := (&y - ypos) / cellsize
if j < 0 | j >= hbits | i < 0 | i >= vbits then return
if e === (&lpress | &ldrag) then setbit(i, j, "1")
else setbit(i, j, "0")
tile_touched := 1
}
return
end
# file menu
procedure grid_file_cb(vidget, menu)
return case menu[1] of {
"read @R" : read_tile()
"open @O" : open_gif()
"ims @M" : open_ims()
"write @W" : write_tile()
"copy @C" : copy_tile()
"paste @P" : paste_tile()
"quit @Q" : return_tile()
"save @S" : save_image()
}
return
end
procedure grid_init()
local e, i, j, x, y, v, h, input, window_save, atts
local shift_up, shift_left, shift_right, shift_down, pixmap
local clear, invert, scramble, trim, enlarge, resize, crop
symmetries := 0 # initially no symmetries
sym_state := [ # initially no symmetries
[1, -1, -1, -1],
[-1, -1, -1, -1]
]
tile_touched := &null
# Set up vidgets
window_save := &window # save current subject window
&window := &null # clear for new subject
atts := grid_ui_atts()
put(atts, "canvas=hidden")
(WOpen ! atts) | stop("*** can't open drawdown editor window")
grid_vidgets := grid_ui()
grid_window := &window
&window := window_save # restore previous subject window
grid_root := grid_vidgets["root"]
xform_xpos := grid_vidgets["xform"].ux
xform_ypos := grid_vidgets["xform"].uy
grid_width := grid_vidgets["grid"].uw
grid_height := grid_vidgets["grid"].uh
maxsize := grid_width / 3
grid_pane := Clone(grid_window, "bg=white", "dx=" || grid_vidgets["grid"].ax,
"dy=" || grid_vidgets["grid"].ay)
Clip(grid_pane, 0, 0, grid_width, grid_height)
symmet_xpos := grid_vidgets["symregion"].ux
symmet_yoff := grid_vidgets["symregion"].uy
shift_up := "16,#3ffe6003408141c143e140814081408140814081408140_
81408160033ffe0000"
shift_left := "16,#3ffe6003400140014001401140195ffd40194011400140_
01400160033ffe0000"
shift_right := "16,#3ffe600340014001400144014c015ffd4c014401400140_
01400160033ffe0000"
shift_down := "16,#3ffe60034081408140814081408140814081408143e141_
c1408160033ffe0000"
flip_left := "16,#3ffe600340014079403940394049408149014e014e014f_
01400160033ffe0000"
flip_right := "16,#3ffe600340014f014e014e014901408140494039403940_
79400160033ffe0000"
flip_vert := "16,#3ffe6003408141c143e14081408140814081408143e141_
c1408160033ffe0000"
flip_horiz := "16,#3ffe600340014001400144114c195ffd4c194411400140_
01400160033ffe0000"
rotate_90 := "16,#3ffe6003400140f141014201420142014f814701420140_
01400160033ffe0000"
rotate_m90 := "16,#3ffe600340014781404140214021402140f94071402140_
01400160033ffe0000"
rotate_180 := "16,#3ffe6003400141c140214011401140114111432147c143_
01410160033ffe0000"
clear := "16,#3ffe600340014001400140014001400140014001400140_
01400160033ffe0000"
invert := "16,#3ffe60ff40ff40ff40ff40ff40ff7fff7f817f817f817f_
817f817f833ffe0000"
scramble := "16,#3ffe60034c014c0d418d41814001403159b1598140194c_
194c0160033ffe0000"
trim := "16,#3ffe60134011407d40394011400140fd48854c857e854c_
8548fd60033ffe0000"
enlarge := "16,#3ffe6083418143fd418148815c017efd48854885488548_
8548fd60033ffe0000"
resize := "16,#3ffe6093419943fd419948915c017efd488548857e855c_
8548fd60033ffe0000"
crop := "16,#3ffe60034011401147fd441144114411441144115ff144_
01440160033ffe0000"
ident := "16,#3ffe6003400140014001400141c141c141c14001400140_
01400160033ffe0000"
hi_ident := "16,#00001ffc3ffe3ffe3ffe3ffe3e3e3e3e3e3e3ffe3ffe3f_
fe3ffe1ffc00000000"
hi_rot_90 := "16,#00001ffc3ffe3f0e3efe3dfe3dfe3dfe307e38fe3dfe3f_
fe3ffe1ffc00000000"
hi_rot_m90 := "16,#00001ffc3ffe387e3fbe3fde3fde3fde3f063f8e3fde3f_
fe3ffe1ffc00000000"
hi_rot_180 := "16,#00001ffc3ffe3e3e3fde3fee3fee3fee3eee3cde383e3c_
fe3efe1ffc00000000"
hi_right := "16,#00001ffc3ffe30fe31fe31fe36fe3f7e3fb63fc63fc63f_
863ffe1ffc00000000"
hi_left := "16,#00001ffc3ffe3f863fc63fc63fb63f7e36fe31fe31fe30_
fe3ffe1ffc00000000"
hi_vert := "16,#00001ffc3f7e3e3e3c1e3f7e3f7e3f7e3f7e3f7e3c1e3e_
3e3f7e1ffc00000000"
hi_horiz := "16,#00001ffc3ffe3ffe3ffe3bee33e6200233e63bee3ffe3f_
fe3ffe1ffc00000000"
sym_image_next := [
[ident, hi_rot_90, hi_rot_m90, hi_rot_180],
[hi_right, hi_left, hi_vert, hi_horiz]
]
sym_image_current := [
[hi_ident, rotate_90, rotate_m90, rotate_180],
[flip_right, flip_left, flip_vert, flip_horiz]
]
# now place the images
place(xform_xpos, xform_ypos, 1, 0, shift_up)
place(xform_xpos, xform_ypos, 0, 1, shift_left)
place(xform_xpos, xform_ypos, 2, 1, shift_right)
place(xform_xpos, xform_ypos, 1, 2, shift_down)
place(xform_xpos, xform_ypos, 0, 4, flip_right)
place(xform_xpos, xform_ypos, 0, 5, flip_left)
place(xform_xpos, xform_ypos, 1, 4, flip_vert)
place(xform_xpos, xform_ypos, 1, 5, flip_horiz)
place(xform_xpos, xform_ypos, 0, 7, rotate_90)
place(xform_xpos, xform_ypos, 0, 8, rotate_m90)
place(xform_xpos, xform_ypos, 1, 7, rotate_180)
place(xform_xpos, xform_ypos, 0, 10, clear)
place(xform_xpos, xform_ypos, 1, 10, invert)
place(xform_xpos, xform_ypos, 2, 10, scramble)
place(xform_xpos, xform_ypos, 0, 12, trim)
place(xform_xpos, xform_ypos, 1, 12, enlarge)
place(xform_xpos, xform_ypos, 2, 12, resize)
place(xform_xpos, xform_ypos, 0, 14, crop)
place(symmet_xpos, symmet_yoff, 0, 0, hi_ident)
place(symmet_xpos, symmet_yoff, 1, 0, rotate_90)
place(symmet_xpos, symmet_yoff, 2, 0, rotate_m90)
place(symmet_xpos, symmet_yoff, 3, 0, rotate_180)
place(symmet_xpos, symmet_yoff, 0, 1, flip_right)
place(symmet_xpos, symmet_yoff, 1, 1, flip_left)
place(symmet_xpos, symmet_yoff, 2, 1, flip_vert)
place(symmet_xpos, symmet_yoff, 3, 1, flip_horiz)
VSetState(grid_vidgets["symstate"], "none ")
return
end
# keyboard shortcuts
procedure grid_shortcuts(e)
if (e === "\r") & \subservient then return_tile() # subservient role
if &meta then case map(e) of {
"0" : read_rows()
"1" : write_rows()
"c" : copy_tile()
"i" : tile_info()
"m" : open_ims()
"n" : new_tile()
"o" : open_gif()
"p" : paste_tile()
"q" : return_tile()
"r" : read_tile()
"s" : save_image()
"z" : undo_xform()
"w" : write_tile()
}
return
end
# check for valid integers
procedure icheck(values)
local i
every i := !values do
if not(integer(i)) | (i < 0) then {
Notice("Invalid value")
fail
}
return
end
procedure new_tile()
case Dialog("New:", ["height", "width"], [*grid_rows, *grid_rows[1]], 3,
["Okay", "Cancel"]) of {
"Cancel" : fail
"Okay" : {
icheck(dialog_value) | fail
grid_rows := list(dialog_value[1], repl("0", dialog_value[2]))
tile_touched := 1
return setup()
}
}
return
end
procedure open_gif()
local win, ims
repeat {
if OpenDialog("Open image:") == "Cancel" then fail
win := WOpen("canvas=hidden", "image=" || dialog_value) | {
Notice("Cannot open image.")
next
}
ims := Capture(win, "g2")
WClose(win)
setup_ims(ims)
return
}
end
procedure open_ims()
local ims, input
repeat {
if OpenDialog("Open ims:") == "Cancel" then fail
input := open(dialog_value) | {
Notice("Cannot open ims file.")
next
}
ims := read(input)
close(input)
setup_ims(ims)
return
}
end
procedure setup_ims(ims)
local width
grid_rows := []
ims ? {
width := tab(upto(','))
while tab(upto(',') + 1)
# while put(grid_rows, map(move(width), "01", "10"))
while put(grid_rows, move(width))
}
setup()
return
end
procedure paste_tile()
local input, tile
input := open("/tmp/tieclip") | {
Notice("Cannot paste tie-up file.")
fail
}
tile := read_pattern(input) | {
Notice("Cannot process matrix.")
close(input)
fail
}
close(input)
grid_rows := pat2rows(tile.tile)
return setup()
end
# place icon
procedure place(xoff, yoff, col, row, pattern)
DrawImage(grid_window, xoff + col * IconSize,
yoff + row * IconSize, pattern)
return
end
# read pattern specification
procedure read_pattern(file)
local line
line := readpattline(file) | fail
return pattrec(legaltile(getpatt(line)), getpattnote(line))
end
# read and add pattern to tile list
procedure read_tile()
local input, tile
static file, line
initial line := "1"
repeat {
if TextDialog("Read tile:", ["file", "line"], [file, line], [60, 4]) ==
"Cancel" then fail
input := open(dialog_value[1]) | {
Notice("Cannot open file.")
next
}
file := dialog_value[1]
line := (0 < integer(dialog_value[2]))
every 1 to line - 1 do
read(input) | {
Notice("Not that many lines in file.")
close(input)
next
}
tile := read_pattern(input) | {
Notice("Cannot process matrix.")
close(input)
next
}
close(input)
grid_rows := pat2rows(tile.tile)
return setup()
}
end
# read and add rows to tile list
procedure read_rows()
local input
static file
repeat {
if OpenDialog("Read rows:") == "Cancel" then fail
input := open(dialog_value) | {
Notice("Cannot open file.")
next
}
file := dialog_value
grid_rows := []
while put(grid_rows, read(input))
close(input)
return setup()
}
end
procedure return_tile()
grid_state := "Done"
return
end
procedure save_image()
snapshot(grid_pane)
return
end
# set bits of tile
procedure setbit(i, j, c)
local x, y, xu, yu, xv, yv, xt, yt, action
static xpos, ypos
initial {
xpos := grid_vidgets["grid"].ax
ypos := grid_vidgets["grid"].ay
}
if (symmetries = 0) & (grid_rows[i + 1, j + 1] == c) then return # optimization
x := j * cellsize + 1 # the selected cell itself
y := i * cellsize + 1
xt := i * cellsize + 1
yt := j * cellsize + 1
i +:= 1 # computational convenience
j +:= 1
xu := (hbits - j) * cellsize + 1 # opposite cells
yu := (vbits - i) * cellsize + 1
xv := (hbits - i) * cellsize + 1
yv := (vbits - j) * cellsize + 1
action := if c = 1 then FillRectangle else EraseArea
if sym_state[1, 1] = 1 then { # cell itself
grid_rows[i, j] := c
action(grid_pane, x, y, cellsize - 1, cellsize - 1)
}
if sym_state[1, 2] = 1 then { # 90 degrees
if grid_rows[j, -i] := c then # may be out of bounds
action(grid_pane, xv, yt, cellsize - 1, cellsize - 1)
}
if sym_state[1, 3] = 1 then { # -90 degrees
if grid_rows[-j, i] := c then # may be out of bounds
action(grid_pane, xt, yv, cellsize - 1, cellsize - 1)
}
if sym_state[1, 4] = 1 then { # 180 degrees
grid_rows[-i, -j] := c
action(grid_pane, xu, yu, cellsize - 1, cellsize - 1)
}
if sym_state[2, 1] = 1 then { # left diagonal
if grid_rows[j, i] := c then # may be out of bounds
action(grid_pane, xt, yt, cellsize - 1, cellsize - 1)
}
if sym_state[2, 2] = 1 then { # right diagonal
if grid_rows[-j, -i] := c then # may be out of bounds
action(grid_pane, xv, yv, cellsize - 1, cellsize - 1)
}
if sym_state[2, 3] = 1 then { # vertical
grid_rows[-i, j] := c
action(grid_pane, x, yu, cellsize - 1, cellsize - 1)
}
if sym_state[2, 4] = 1 then { # horizontal
grid_rows[i, -j] := c
action(grid_pane, xu, y, cellsize - 1, cellsize - 1)
}
return
end
# set up editing grid and view area
procedure setup()
local i, j
hbits := *grid_rows[1]
vbits := *grid_rows
if (hbits | vbits) > maxsize then { # based on cell size >= 3
Notice("Dimensions too large.")
fail
}
if hbits > MaxPatt then mode := &null # too large for pattern
cellsize := MaxCell # cell size on window
cellsize >:= grid_width / (vbits + 4)
cellsize >:= grid_height / (hbits + 4)
grid()
every i := 1 to hbits do
every j := 1 to vbits do
if grid_rows[j, i] == "1" then
FillRectangle(grid_pane, (i - 1) * cellsize,
(j - 1) * cellsize, cellsize, cellsize)
return
end
procedure symstate_cb(vidget, value)
local row, col
# Note: the blanks at the end of these radio-button labels are
# for interface formatting.
sym_state := case value of {
"none " : [[1, -1, -1, -1], [-1, -1, -1, -1]]
"all " : [[1, 1, 1, 1], [1, 1, 1, 1]]
}
sym_image_next := [
[ident, hi_rot_90, hi_rot_m90, hi_rot_180],
[hi_right, hi_left, hi_vert, hi_horiz]
]
sym_image_current := [
[hi_ident, rotate_90, rotate_m90, rotate_180],
[flip_right, flip_left, flip_vert, flip_horiz]
]
if value == "all " then sym_image_next :=: sym_image_current
every col := 1 to 4 do
every row := 1 to 2 do
place(symmet_xpos, symmet_yoff, col - 1, row - 1,
sym_image_current[row, col])
return
end
# symmetry buttons
procedure symmet_cb(vidget, e)
local col, row, symcount
if e === (&lpress | &rpress | &mpress) then {
col := (&x - symmet_xpos) / IconSize + 1
row := (&y - symmet_yoff) / IconSize + 1
sym_state[row, col] *:= -1
sym_image_current[row, col] :=: sym_image_next[row, col]
place(symmet_xpos, symmet_yoff, col - 1, row - 1,
sym_image_current[row, col])
symcount := 0
every symcount +:= !!sym_state
if symcount = -8 then
Notice("No drawing mode enabled; pattern cannot be edited")
else if (sym_state[1, 1] = 1) & (symcount = -6) then symmetries := 0
else symmetries := 1
return
}
fail
end
# tile menu
procedure tile_cb(vidget, value)
local result
case value[1] of {
"new @N" : new_tile()
"info @I" : tile_info()
}
return
end
# show information about tile
procedure tile_info()
local line1, line2, pattern, bits, density
pattern := rows2pat(grid_rows)
bits := tilebits(grid_rows)
density := left(bits / real(*grid_rows[1] * *grid_rows), 6)
line1 := left(*grid_rows[1] || "x" || *grid_rows || " b=" || bits || " d=" ||
density, InfoLength)
line2 := if *pattern > InfoLength then pattern[1+:(InfoLength - 3)] ||
"..." else left(pattern, InfoLength)
Notice(line1, line2)
return
end
# undo transformation
procedure undo_xform()
grid_rows := pat2rows(old_pat)
return setup()
end
# write pattern
procedure write_tile()
local output
repeat {
if SaveDialog("Write pattern") == "Cancel" then fail
output := open(dialog_value, "w") | {
Notice("Cannot open file for writing.")
next
}
write(output, rows2pat(grid_rows))
close(output)
return
}
end
# write rows
procedure write_rows()
local output
repeat {
if SaveDialog("Write rows") == "Cancel" then fail
output := open(dialog_value, "w") | {
Notice("Cannot open file for writing.")
next
}
every write(output, !grid_rows)
close(output)
return
}
end
# handle transformation
procedure xform(col, row)
local result
static params
tile_touched := 1
return case col of {
0: case row of {
1: pshift(grid_rows, -1, "h")
4: pflip(grid_rows, "r")
5: pflip(grid_rows, "l")
7: protate(grid_rows, 90)
8: protate(grid_rows, -90)
10: list(vbits, repl("0", hbits))
12: ptrim(grid_rows)
14: {
case Dialog("Crop:", ["left", "right", "top", "bottom"],
0, 3, ["Okay", "Cancel"]) of {
"Cancel": fail
"Okay": {
icheck(dialog_value) | fail
result := copy(params := dialog_value)
push(result, grid_rows)
pcrop ! result
}
}
}
default: fail
}
1: case row of {
0: pshift(grid_rows, -1, "v")
2: pshift(grid_rows, 1, "v")
4: pflip(grid_rows, "v")
5: pflip(grid_rows, "h")
7: protate(grid_rows, 180)
10: pinvert(grid_rows)
12: {
case Dialog("Enlarge:", ["left", "right", "top", "bottom"],
0, 3, ["Okay", "Cancel"]) of {
"Cancel": fail
"Okay": {
icheck(dialog_value) | fail
result := copy(params := dialog_value)
push(result, grid_rows)
pborder ! result
}
}
}
default: fail
}
2: case row of {
1: pshift(grid_rows, 1, "h")
10: pscramble(grid_rows, "b")
12: {
case Dialog("Center:", ["width", "height"], [*grid_rows[1], *grid_rows],
3, ["Okay", "Cancel"]) of {
"Cancel": fail
"Okay": {
icheck(dialog_value) | fail
result := copy(params := dialog_value)
push(result, grid_rows)
pcenter ! result
}
}
}
default: fail
}
default: fail
}
end
# transformation buttons
procedure xform_cb(vidget, e)
local col, row
if e === (&lpress | &rpress | &mpress) then {
old_pat := rows2pat(grid_rows)
col := (&x - xform_xpos) / IconSize
row := (&y - xform_ypos) / IconSize
grid_rows := xform(col, row) | fail
return setup()
}
end
#===<<vib:begin>>=== modify using vib; do not remove this marker line
procedure grid_ui_atts()
return ["size=635,568", "bg=pale gray", "label=Drawdown Editor"]
end
procedure grid_ui(win, cbk)
return vsetup(win, cbk,
["grid_ui:Sizer:::0,0,635,568:Drawdown Editor",],
["file:Menu:pull::0,0,36,21:File",grid_file_cb,
["read @R","open @O","ims @M","write @W","copy @C",
"paste @P","quit @Q ","save @S"]],
["line1:Line:::0,22,660,22:",],
["symmetries:Label:::22,316,70,13:symmetries",],
["symstate:Choice::2:26,384,64,42:",symstate_cb,
["all ","none "]],
["tile:Menu:pull::38,0,64,21:Drawdown",tile_cb,
["new @N","info @I"]],
["transformations:Label:::5,33,105,13:transformations",],
["symregion:Rect:grooved::24,338,68,36:",symmet_cb],
["info:Rect:invisible::123,32,251,19:",],
["xform:Rect:grooved::32,58,52,244:",xform_cb],
["grid:Rect:sunken::123,58,500,500:",grid_cb],
)
end
#===<<vib:end>>=== end of section maintained by vib