{Probable bug in loop at label wireydrawn:}
{loop variable screwed up by complex condition}
{I'm afraid it takes level 1.5 graphics interaction to reproduce the exact}
{conditions of failure}
include "level1:graphinc.imp"
begin
{framestore sizes}
constant integer framestorexl = 0, framestorexr = 687,
framestoreyb = 0, framestoreyt = 511
{display & editing area}
constant integer windowframe = 12,
windowxl = framestorexl+windowframe,
windowxr = framestorexr-windowframe,
windowyb = framestoreyb+windowframe,
windowyt = framestoreyt-windowframe
{virtual grid size}
constant integer vgridxl = 0, vgridxr = 255,
vgridyb = 0, vgridyt = 255
{virtual grid data structures}
byte integer array vgrid(vgridxl:vgridxr, vgridyb:vgridyt)
byte integer array hvgrid(vgridxl:vgridxr+1, vgridyb:vgridyt)
byte integer array vvgrid(vgridxl:vgridxr, vgridyb:vgridyt+1)
{menu item codings}
constant integer mpoly = 1, mdiff = 2, mmetal1 = 3, mmetal2 = 4
constant integer mcontact = 5, msubcon = 6, mtranx = 7, mtrany = 8
constant integer mptranx = 9, mptrany = 10, mpwell = 11
constant integer mzoom = 12, minput = 13, moutput = 14
constant integer mitems = 14
{menu scales}
constant integer mwscale = 8, mtscale = 4, mtscale3 = 12
{positions of items in menu}
constant integer array mitemx(1:mitems) = c
20, 48, 76, 104, 132, 160, 22, 56, 90, 124, 158,
20, 20, 68
constant integer array mitemxl(1:mitems) = c
0, 34, 62, 90, 118, 146, 0, 39, 73, 107, 141,
0, 0, 53
constant integer array mitemxr(1:mitems) = c
33, 61, 89, 117, 145, 180, 38, 72, 106, 140, 180,
41, 52, 110
constant integer array mitemy(1:mitems) = c
96(6), 66(5), 36, 10(2)
constant integer array mitemyb(1:mitems) = c
84(6), 49(5), 23, 0(2)
constant integer array mitemyt(1:mitems) = c
114(6), 83(5), 48, 22(2)
{menu size}
constant integer menuxs = 180, menuys = 114
{cursor outline box in scale units}
constant integer array curxl(1:mitems) = c
-1(6), -3(5), -1(3)
constant integer array curxr(1:mitems) = c
1(6), 3(5), 1(3)
constant integer array curyb(1:mitems) = c
-1(6), -3(5), -1(3)
constant integer array curyt(1:mitems) = c
1(6), 3(5), 1(3)
{layer codings}
constant integer poly = 1, diff = 2, metal1 = 4, metal2 = 8,
pwell = 16, contact = 32, alllayers = 63,
grid = 64, menuback = 128
{codings for wire erasing in progress}
constant integer polywireerased = 16, diffwireerased = 32,
metal1wireerased = 64, metal2wireerased = 128
{primitive codings}
constant integer tranx = 1, trany = 2, subcon = 4
{pwell = 16, contact = 32}
{window frame colours}
constant integer array windowframelr(1:mitems) = c
poly, diff, metal1, metal2, menuback, menuback,
poly, diff, poly, diff, pwell,
menuback(3)
constant integer array windowframebt(1:mitems) = c
poly, diff, metal1, metal2, menuback, menuback,
diff, poly, diff, poly, pwell,
menuback(3)
{wire drawing directions}
constant integer nodir = 0, south = 1, east = 2, north = 3, west = 4
{state values}
constant integer nostate = 0, drawing = 1, erasing = 2
{button states}
constant integer notpressed = 0, pressed = 1, released = 2, stillpressed = 3
half integer array cmap (0:255)
integer backgroundcolour, flashcolour
routine spec setupcolourmap
routine spec drawwindowframe(integer b, r, t, l)
routine spec setupnewscale(integer newscale)
routine spec clipfill(integer xl, yb, xr, yt)
routine spec clipvline(integer x, yb, yt)
routine spec cliphline(integer xl, xr, y)
routine spec clipdbtline(integer xl, yb, xr, yt)
routine spec clipdtbline(integer xl, yt, xr, yb)
routine spec outline(integer xl, yb, xr, yt)
routine spec clipoutline(integer xl, yb, xr, yt)
routine spec drawwirex(integer layer, gx, gy)
routine spec erasewirex(integer layer, gx, gy)
routine spec drawwirey(integer layer, gx, gy)
routine spec erasewirey(integer layer, gx, gy)
routine spec drawtranx(integer gx, gy)
routine spec drawtrany(integer gx, gy)
routine spec drawcontact(integer gx, gy)
routine spec drawsubcon(integer gx, gy)
routine spec drawpwell(integer gx, gy)
routine spec redrawdesign
routine spec redrawgridpoint(integer gx, gy)
routine spec redrawprim(integer gx, gy)
routine spec redrawwirex(integer gx, gy)
routine spec redrawwirey(integer gx, gy)
routine spec drawcursor
routine spec erasecursor
routine spec pan(integer xi, yi)
routine spec zoomin
routine spec zoomout
routine spec drawmenu
routine spec erasemenu
routine spec flash
{display grid coordinate arrays}
{bounds -1 & +1 to avoid problems with off-display grid points}
short integer array gridx(vgridxl-1:vgridxr+1),
gridy(vgridyb-1:vgridyt+1)
{grid window position within virtual grid}
integer wgridxl, wgridxr, wgridyb, wgridyt
{display grid limits}
constant integer gridxl = 0, gridyb = 0
integer gridxr, gridyt
{menu variables}
integer menuxl, menuxr, menuyb, menuyt
integer curbuts, curgx, curgy, newbuts, newgx, newgy, vgx, vgy, vg, vgw
integer scale, scale2, scale3, scale4, scale6, x, y, xi, yi, curx, cury, s
integer state, butl, butm, butr, curtype, newtype, vgwh, vgwv
integer wirestartgx, wirestartgy, wirecurgx, wirecurgy
integer curwiredir, newwiredir, layer
integer xl, xr, yb, yt
switch action(1:mitems), wireaction(0:2)
switch wiredrawn(nodir:west), undrawwire(nodir:west), drawwire(nodir:west)
switch wireerased(nodir:west), unerasewire(nodir:west), erasewire(nodir:west)
{clear virtual grid}
for x = vgridxl, 1, vgridxr cycle
for y = vgridyb, 1, vgridyt cycle
vgrid(x, y) = 0
hvgrid(x, y) = 0
vvgrid(x, y) = 0
repeat
repeat
hvgrid(vgridxr+1, y) = 0 for y = vgridyb, 1, vgridyt
vvgrid(x, vgridyt+1) = 0 for x = vgridxl, 1, vgridxr
{initialise display}
clear
setupcolourmap
drawwindowframe(poly, poly, poly, poly)
{put display window in middle of virtual grid}
wgridxl = (vgridxl+vgridxr)//2
wgridyb = (vgridyb+vgridyt)//2
{put cursor in middle of window}
curgx = 0
curgy = 0
gridx(curgx) = (windowxl+windowxr)//2
gridy(curgy) = (windowyb+windowyt)//2
{create initial display}
setupnewscale(6)
mousex = (windowxr+windowxl)//2
mousey = (windowyt+windowyb)//2
curbuts = mousebuttons
curtype = mpoly
drawcursor
menu:{enter menu sequence}
drawmenu
menuloop:{select next cursor type}
x = mousex
y = mousey
if x < menuxl then x = menuxl and mousex = x else c
if x > menuxr then x = menuxr and mousex = x
if y < menuyb then y = menuyb and mousey = y else c
if y > menuyt then y = menuyt and mousey = y
{find new menu cursor type}
x = x-menuxl
y = y-menuyb
for newtype = 1, 1, mitems cycle
if mitemxl(newtype) <= x <= mitemxr(newtype) and c
mitemyb(newtype) <= y <= mitemyt(newtype) then exit
repeat
{change cursor outline if necessary}
if newtype # curtype then start
{erase old cursor}
colour(0); enable(contact)
outline(mitemxl(curtype)+menuxl, mitemyb(curtype)+menuyb,
mitemxr(curtype)+menuxl, mitemyt(curtype)+menuyb)
{draw new cursor}
curtype = newtype
colour(contact); enable(contact)
outline(mitemxl(curtype)+menuxl, mitemyb(curtype)+menuyb,
mitemxr(curtype)+menuxl, mitemyt(curtype)+menuyb)
finish
{look at buttons}
newbuts = mousebuttons
butl = (curbuts&1)<<1!(newbuts&1)
butm = (curbuts&2)!(newbuts&2)>>1
butr = (curbuts&4)>>1!(newbuts&4)>>2
! 0 : not pressed
! 1 : pressed
! 2 : released
! 3 : still pressed
curbuts = newbuts
unless butl = pressed or butm = pressed then ->menuloop
{change window frame colour for selected menu item}
drawwindowframe(windowframebt(curtype), windowframelr(curtype),
windowframebt(curtype), windowframelr(curtype))
display:{enter main edit loop}
erasemenu
drawcursor
state = nostate
displayloop:{edit}
{check for cursor at edge of display for panning}
x = mousex
y = mousey
xi = 0
yi = 0
if x < windowxl then xi = -1 else c
if x > windowxr then xi = 1
if y < windowyb then yi = -1 else c
if y > windowyt then yi = 1
if xi # 0 or yi # 0 then start
if x < framestorexl then x = framestorexl and mousex = x
if x > framestorexr then x = framestorexr and mousex = x
if y < framestoreyb then y = framestoreyb and mousey = y
if y > framestoreyt then y = framestoreyt and mousey = y
erasecursor
colour(contact); enable(contact)
plot(x,y)
pan(xi, yi)
->displayloop
finish
newgx = x//scale6
newgy = y//scale6
if newgx < gridxl then newgx = gridxl else c
if newgx > gridxr then newgx = gridxr
if newgy < gridyb then newgy = gridyb else c
if newgy > gridyt then newgy = gridyt
if newgx # curgx or newgy # curgy then start
erasecursor
curgx = newgx
curgy = newgy
drawcursor
finish
{look at buttons}
newbuts = mousebuttons
butl = (curbuts&1)<<1!(newbuts&1)
butm = (curbuts&2)!(newbuts&2)>>1
butr = (curbuts&4)>>1!(newbuts&4)>>2
! 0 : not unpressed
! 1 : pressed
! 2 : released
! 3 : still pressed
curbuts = newbuts
if butr = pressed then ->menu
vgx = curgx+wgridxl
vgy = curgy+wgridyb
vg = vgrid(vgx, vgy)
{what wires come to this grid point?}
vgwh = hvgrid(vgx,vgy)!hvgrid(vgx+1,vgy)
vgwv = vvgrid(vgx,vgy)!vvgrid(vgx,vgy+1)
vgw = vgwh!vgwv
->action(curtype)
{------------------------------------------------------------------------------}
action(mpoly):{poly selected}
layer = poly
->wireaction(state)
{------------------------------------------------------------------------------}
action(mdiff):{diff selected}
layer = diff
->wireaction(state)
{------------------------------------------------------------------------------}
action(mmetal1):{metal1 selected}
layer = metal1
->wireaction(state)
{------------------------------------------------------------------------------}
action(mmetal2):{metal2 selected}
layer = metal2
->wireaction(state)
{------------------------------------------------------------------------------}
wireaction(0):{no drawing or erasing in progress}
if butm = pressed or butl = pressed then start {start drawing or erasing}
wirestartgx = curgx
wirestartgy = curgy
wirecurgx = curgx
wirecurgy = curgy
curwiredir = nodir
if butm = pressed then state = drawing else state = erasing
finish
->displayloop
{------------------------------------------------------------------------------}
wireaction(drawing):{drawing wire}
if butm = stillpressed then ->wiredrawing
{butm = released assumed}
state = nostate
{check and confirm wire drawn}
->wiredrawn(curwiredir)
wiredrawn(nodir):
->displayloop
wiredrawn(south):
x = wirestartgx+wgridxl
yb = wirecurgy+wgridyb+1
yt = wirestartgy+wgridyb
option "-code-tt"
wireydrawn:
for y = yb, 1, yt cycle
if vvgrid(x, y)&layer # 0 then continue
{check wire segment for incompatibility}
if layer = poly then start
if (vvgrid(x, y-1)!vvgrid(x, y)!vvgrid(x, y+1))&diff#0 c
or (vgrid(x, y-1)!vgrid(x, y))&(tranx!contact!subcon)#0 c
or ((hvgrid(x, y-1)!hvgrid(x+1, y-1))&diff # 0 c
and vgrid(x-1, y)&trany = 0) c
or ((hvgrid(x, y)!hvgrid(x+1, y))&diff # 0 c
and vgrid(x, y)&trany = 0) then ->wireyko
finish else c
if layer = diff then start
if (vvgrid(x, y-1)!vvgrid(x, y)!vvgrid(x, y+1))&poly#0 c
or (vgrid(x, y-1)!vgrid(x, y))&(trany!contact!subcon)#0 c
or ((hvgrid(x, y-1)!hvgrid(x+1, y-1))&poly # 0 c
and vgrid(x, y-1)&tranx = 0) c
or ((hvgrid(x, y)!hvgrid(x+1, y))&poly # 0 c
and vgrid(x, y)&tranx = 0) then ->wireyko
finish else start {metal1 or metal2}
if (vgrid(x, y-1)!vgrid(x, y))&(contact!subcon) # 0 then ->wireyko
finish
vvgrid(x, y) = vvgrid(x, y)!layer
continue
wireyko:erasewirey(layer, x-wgridxl, y-wgridyb)
if y # yt then drawwirey(layer, x-wgridxl, y+1-wgridyb)
flash
repeat
->displayloop
wiredrawn(east):
xl = wirestartgx+wgridxl+1
xr = wirecurgx+wgridxl
y = wirestartgy+wgridyb
wirexdrawn:
for x = xl, 1, xr cycle
if hvgrid(x, y)&layer # 0 then continue
{check wire segment for incompatibility}
if layer = poly then start
if (hvgrid(x-1, y)!hvgrid(x, y)!hvgrid(x+1, y))&diff#0 c
or (vgrid(x-1, y)!vgrid(x, y))&(trany!contact!subcon)#0 c
or vgrid(x-1, y)&pwell # vgrid(x, y)&pwell c
or ((vvgrid(x-1, y)!vvgrid(x-1, y+1))&diff # 0 c
and vgrid(x-1, y)&tranx = 0) c
or ((vvgrid(x, y)!vvgrid(x, y+1))&diff # 0 c
and vgrid(x, y)&tranx = 0) then ->wirexko
finish else c
if layer = diff then start
if (hvgrid(x-1, y)!hvgrid(x, y)!hvgrid(x+1, y))&poly#0 c
or (vgrid(x-1, y)!vgrid(x, y))&(tranx!contact!subcon)#0 c
or ((vvgrid(x-1, y)!vvgrid(x-1, y+1))&poly # 0 c
and vgrid(x-1, y)&trany = 0) c
or ((vvgrid(x, y)!vvgrid(x, y+1))&poly # 0 c
and vgrid(x, y)&trany = 0) then ->wirexko
finish else start {metal1 or metal2}
if (vgrid(x-1, y)!vgrid(x, y))&(contact!subcon) # 0 then ->wirexko
finish
hvgrid(x, y) = hvgrid(x, y)!layer
drawwirex(layer, x-wgridxl, y-wgridyb)
continue
wirexko:erasewirex(layer, x-wgridxl, y-wgridyb)
if x # xr then drawwirex(layer, x+1-wgridxl, y-wgridyb)
flash
repeat
->displayloop
wiredrawn(north):
x = wirestartgx+wgridxl
yb = wirestartgy+wgridyb+1
yt = wirecurgy+wgridyb
->wireydrawn
wiredrawn(west):
xl = wirecurgx+wgridxl+1
xr = wirestartgx+wgridxl
y = wirestartgy+wgridyb
->wirexdrawn
wiredrawing:{button remaining pressed}
{find new direction}
x = curgx-wirestartgx
y = curgy-wirestartgy
if x = 0 and y = 0 then newwiredir = nodir else start
if x >= y then start
if x > -y then newwiredir = east else newwiredir = south
finish else start
if x > -y then newwiredir = north else newwiredir = west
finish
finish
if newwiredir # curwiredir then start
{erase wire so far drawn in wrong direction}
->undrawwire(curwiredir)
undrawwire(nodir):
->endundrawwire
undrawwire(south):
erasewirey(layer, wirestartgx, y) for y = wirecurgy+1, 1, wirestartgy
->endundrawwire
undrawwire(east):
erasewirex(layer, x, wirestartgy) for x = wirecurgx, -1, wirestartgx+1
->endundrawwire
undrawwire(north):
erasewirey(layer, wirestartgx, y) for y = wirecurgy, -1, wirestartgy+1
->endundrawwire
undrawwire(west):
erasewirex(layer, x, wirestartgy) for x = wirecurgx+1, 1, wirestartgx
->endundrawwire
endundrawwire:
wirecurgx = wirestartgx
wirecurgy = wirestartgy
curwiredir = newwiredir
finish {wire in wrong direction gotten rid of}
->drawwire(curwiredir)
{------------------------------------------------------------------------------}
drawwire(nodir):
drawcursor
->displayloop
{------------------------------------------------------------------------------}
drawwire(south):
if curgy <= wirecurgy then start {extend southwards}
yt = wirecurgy+1 {draw previous segment to allow for cursor erase}
if wirecurgy = wirestartgy then yt = yt-1
drawwirey(layer, wirestartgx, y) for y = yt, -1, curgy+1
finish else start {gone too far southwards}
erasewirey(layer, wirestartgx, y) for y = wirecurgy+1, 1, curgy
finish
wirecurgy = curgy
->displayloop
{------------------------------------------------------------------------------}
drawwire(east):
if curgx >= wirecurgx then start {extend eastwards}
xl = wirecurgx {draw previous segment to deal with cursor erase}
if wirecurgx = wirestartgx then xl = xl+1 {not if at start}
drawwirex(layer, x, wirestartgy) for x = xl, 1, curgx
finish else start {gone too far eastwards so erase back}
erasewirex(layer, x, wirestartgy) for x = wirecurgx, -1, curgx+1
finish
wirecurgx = curgx
->displayloop
{------------------------------------------------------------------------------}
drawwire(north):
if curgy >= wirecurgy then start {extend northwards}
yb = wirecurgy {draw previous wire segment also}
if wirecurgy = wirestartgy then yb = yb+1
drawwirey(layer, wirestartgx, y) for y = yb, 1, curgy
finish else start {gone too far northwards}
erasewirey(layer, wirestartgx, y) for y = wirecurgy, -1, curgy+1
finish
wirecurgy = curgy
->displayloop
{------------------------------------------------------------------------------}
drawwire(west):
if curgx <= wirecurgx then start {extend westwards}
xr = wirecurgx+1
if wirecurgx = wirestartgx then xr = xr-1
drawwirex(layer, x, wirestartgy) for x = xr, -1, curgx+1
finish else start {gone too far westwards}
erasewirex(layer, x, wirestartgy) for x = wirecurgx+1, 1, curgx
finish
wirecurgx = curgx
->displayloop
{------------------------------------------------------------------------------}
action(mcontact):{contact selected}
if butm = pressed then start {draw contact}
if vg&(tranx!trany!subcon) # 0 or (vgw # poly!metal1 and c
vgw # diff!metal1 and vgw # metal1!metal2) then flash c
else vgrid(vgx, vgy) = vg!contact
finish else c
if butl = pressed then vgrid(vgx, vgy) = vg&(¬contact) {erase contact}
->displayloop
{------------------------------------------------------------------------------}
action(msubcon):{subcon selected}
if butm = pressed then start {draw subcon}
if vg&(tranx!trany!contact) # 0 or vgw&(¬metal2) # metal1 then flash c
else vgrid(vgx, vgy) = vg!subcon
finish else c
if butl = pressed then vgrid(vgx, vgy) = vg&(¬subcon) {erase subcon}
->displayloop
{------------------------------------------------------------------------------}
action(mtranx):{tranx selected}
if butm = pressed then start {draw tranx}
if vg&(trany!contact!subcon) # 0 c
or vgwh&diff # 0 or vgwv&poly # 0 c
then flash else vgrid(vgx, vgy) = vg!tranx
finish else c
if butl = pressed then vgrid(vgx, vgy) = vg&(¬tranx) {erase tranx}
->displayloop
{------------------------------------------------------------------------------}
action(mtrany):{trany selected}
if butm = pressed then start {draw trany}
if vg&(tranx!contact!subcon) # 0 c
or vgwh&poly # 0 or vgwv&diff # 0 c
then flash else vgrid(vgx, vgy) = vg!trany
finish else c
if butl = pressed then vgrid(vgx, vgy) = vg&(¬trany) {erase trany}
->displayloop
{------------------------------------------------------------------------------}
action(mptranx):{ptranx selected}
if butm = pressed then start {draw ptranx}
if vg&(trany!contact!subcon) # 0 c
or vgwh&diff # 0 or vgwv&poly # 0 c
then flash else vgrid(vgx, vgy) = vg!tranx!pwell
finish else c
if butl = pressed then vgrid(vgx, vgy) = vg&(¬tranx)&(¬pwell) {erase ptranx}
->displayloop
{------------------------------------------------------------------------------}
action(mptrany):{ptrany selected}
if butm = pressed then start {draw ptrany}
if vg&(tranx!contact!subcon) # 0 c
or vgwh&poly # 0 or vgwv&diff # 0 c
then flash else vgrid(vgx, vgy) = vg!trany!pwell
finish else c
if butl = pressed then vgrid(vgx, vgy) = vg&(¬trany)&(¬pwell) {erase ptrany}
->displayloop
{------------------------------------------------------------------------------}
action(mpwell):{pwell selected}
if butm = pressed then start {draw pwell}
finish else c
if butl = pressed then start {erase pwell}
finish
->displayloop
{------------------------------------------------------------------------------}
action(mzoom):{zoom selected}
if butm = pressed then zoomin else c
if butl = pressed then zoomout
->displayloop
{------------------------------------------------------------------------------}
routine setupcolourmap
integer function cmapc (integer red, green, blue)
result = (blue<<5!green)<<5+red
end
integer i
cmap(i) = 0 for i=0,1,255
backgroundcolour = cmapc(14,16,14)
flashcolour = cmapc(31,0,0)
cmap(0) = backgroundcolour
cmap(poly) = cmapc(28,0,0)
cmap(diff) = cmapc(0,26,0)
cmap(diff+poly) = cmapc(18,18,0)
cmap(metal1) = cmapc(15,15,31)
cmap(metal1+poly) = cmapc(22,8,22)
cmap(metal1+diff) = cmapc(8,24,24)
cmap(metal1+diff+poly) = cmapc(18,18,31)
cmap(metal2) = cmapc(0,0,31)
cmap(metal2+poly) = cmapc(24,0,31)
cmap(metal2+diff) = cmapc(0,24,31)
cmap(metal2+diff+poly) = cmapc(24,24,31)
cmap(metal2+metal1) = cmapc(8,8,31)
cmap(metal2+metal1+poly) = cmapc(31,8,31)
cmap(metal2+metal1+diff) = cmapc(8,31,31)
cmap(metal2+metal1+diff+poly) = cmapc(24,24,24)
{pwell colour lowest priority}
cmap(pwell) = cmapc(20,20,0)
cmap(pwell+i) = cmap(i) for i=1, 1, pwell-1
{contact colour high priority}
cmap(i) = cmapc(24,24,24) for i=contact,1,2*contact-1
{grid colour higher priority}
cmap(i) = cmapc(28,28,28) for i=grid,1,2*grid-1
{menu background highest priority}
cmap(i) = cmapc(16,18,16) for i=menuback,1,2*menuback-1
cmap(menuback+i) = cmap(i) for i=1, 1, grid-1
updatecolourmap(cmap(0))
end
{------------------------------------------------------------------------------}
routine drawwindowframe(integer b, r, t, l)
own integer frame = 0
if frame = 0 then start
colour(grid); enable(grid)
outline(framestorexl, framestoreyb, framestorexr, windowyb-1)
outline(windowxr+1, framestoreyb, framestorexr, framestoreyt)
outline(framestorexl, windowyt+1, framestorexr, framestoreyt)
outline(framestorexl, framestoreyb, windowxl-1, framestoreyt)
frame = 1
finish
{clear frame first}
colour(0); enable(alllayers+menuback)
fill(framestorexl+1, framestoreyb+1, windowxl-2, framestoreyt-1)
fill(windowxr+2, framestoreyb+1, framestorexr-1, framestoreyt-1)
fill(framestorexl+1, framestoreyb+1, framestorexr-1, windowyb-2)
fill(framestorexl+1, windowyt+2, framestorexr-1, framestoreyt-1)
{fill in new colours}
colour(b); enable(b)
fill(framestorexl+1, framestoreyb+1, framestorexr-1, windowyb-2)
colour(r); enable(r)
fill(windowxr+2, framestoreyb+1, framestorexr-1, framestoreyt-1)
colour(t); enable(t)
fill(framestorexl+1, windowyt+2, framestorexr-1, framestoreyt-1)
colour(l); enable(l)
fill(framestorexl+1, framestoreyb+1, windowxl-2, framestoreyt-1)
end
{------------------------------------------------------------------------------}
routine setupnewscale(integer newscale)
integer x, y, curx, cury, curvgx, curvgy
scale = newscale
scale2 = 2*scale
scale3 = 3*scale
scale4 = 4*scale
scale6 = 6*scale
{current pixel position in old scale; this is the zoom fixed point}
curx = gridx(curgx)
cury = gridy(curgy)
{current virtual grid cursor position}
curvgx = curgx+wgridxl
curvgy = curgy+wgridyb
{virtual grid position of new window}
wgridxl = curvgx-(curx-windowxl)//scale6
wgridxr = curvgx+(windowxr-curx)//scale6
wgridyb = curvgy-(cury-windowyb)//scale6
wgridyt = curvgy+(windowyt-cury)//scale6
{new display window limits}
gridxr = wgridxr-wgridxl
gridyt = wgridyt-wgridyb
{new current display grid position}
curgx = curvgx-wgridxl
curgy = curvgy-wgridyb
{work out coordinate positions for display grid}
{bounds -1 & +1 for first off-display grid points}
curx = curx-scale6*(curgx+1)
for x = -1, 1, gridxr+1 cycle
gridx(x) = curx
curx = curx+scale6
repeat
cury = cury-scale6*(curgy+1)
for y = -1, 1, gridyt+1 cycle
gridy(y) = cury
cury = cury+scale6
repeat
{clear display window}
colour(0); enable(alllayers+grid)
fill(windowxl, windowyb, windowxr, windowyt)
{redraw grid}
colour(grid); enable(grid)
for x=gridxl, 1, gridxr cycle
for y=gridyb, 1, gridyt cycle
plot(gridx(x), gridy(y))
repeat
repeat
redrawdesign
end
{------------------------------------------------------------------------------}
routine clipfill(integer xl, yb, xr, yt)
if xl < windowxl then xl = windowxl
if yb < windowyb then yb = windowyb
if xr > windowxr then xr = windowxr
if yt > windowyt then yt = windowyt
fill(xl, yb, xr, yt)
end
{------------------------------------------------------------------------------}
routine clipvline(integer x, yb, yt)
{clip & draw vertical line}
if x < windowxl or x > windowxr then return
if yb < windowyb then yb = windowyb
if yt > windowyt then yt = windowyt
vline(x, yb, yt)
end
{------------------------------------------------------------------------------}
routine cliphline(integer xl, xr, y)
{clip & draw horizontal line}
if y < windowyb or y > windowyt then return
if xl < windowxl then xl = windowxl
if xr > windowxr then xr = windowxr
hline(xl, xr, y)
end
{------------------------------------------------------------------------------}
routine clipdbtline(integer xl, yb, xr, yt)
{clip & draw (bottom left to top right) diagonal line}
integer xll, xrr
{clip bottom left end}
if xl < windowxl or yb < windowyb then start
xll = xl+windowyb-yb
if xll >= windowxl then xl = xll and yb = windowyb c
else xl = windowxl and yb = yb+windowxl-xl
finish
{clip top right end}
if xr > windowxr or yt > windowyt then start
xrr = xr+windowyt-yt
if xrr <= windowxr then xr = xrr and yt = windowyt c
else xr = windowxr and yt = yt+windowxr-xr
finish
line(xl, yb, xr, yt)
end
{------------------------------------------------------------------------------}
routine clipdtbline(integer xl, yt, xr, yb)
{clip & draw (top left to bottom right) diagonal line}
integer xll, xrr
{clip top left end}
if xl < windowxl or yt > windowyt then start
xll = xl+yt-windowyt
if xll >= windowxl then xl = xll and yt = windowyt c
else xl = windowxl and yt = yt+xl-windowxl
finish
{clip bottom right end}
if xr > windowxr or yb < windowyb then start
xrr = xr+yb-windowyb
if xrr <= windowxr then xr = xrr and yb = windowyb c
else xr = windowxr and yb = yb+xr-windowxr
finish
line(xl, yt, xr, yb)
end
{------------------------------------------------------------------------------}
routine outline(integer xl, yb, xr, yt)
hline(xl, xr, yb)
vline(xr, yb, yt)
hline(xl, xr, yt)
vline(xl, yb, yt)
end
{------------------------------------------------------------------------------}
routine clipoutline(integer xl, yb, xr, yt)
if yb >= windowyb then cliphline(xl, xr, yb)
if xr <= windowxr then clipvline(xr, yb, yt)
if yt <= windowyt then cliphline(xl, xr, yt)
if xl >= windowxl then clipvline(xl, yb, yt)
end
{------------------------------------------------------------------------------}
routine drawwirex(integer layer, gx, gy)
colour(layer); enable(layer)
clipfill(gridx(gx-1)-scale, gridy(gy)-scale,
gridx(gx)+scale, gridy(gy)+scale)
end
{------------------------------------------------------------------------------}
routine erasewirex(integer layer, gx, gy)
colour(0); enable(layer)
clipfill(gridx(gx-1)-scale, gridy(gy)-scale,
gridx(gx)+scale, gridy(gy)+scale)
{redraw end points}
redrawgridpoint(gx-1, gy)
redrawgridpoint(gx, gy)
end
{------------------------------------------------------------------------------}
routine drawwirey(integer layer, gx, gy)
colour(layer); enable(layer)
clipfill(gridx(gx)-scale, gridy(gy-1)-scale,
gridx(gx)+scale, gridy(gy)+scale)
end
{------------------------------------------------------------------------------}
routine erasewirey(integer layer, gx, gy)
colour(0); enable(layer)
clipfill(gridx(gx)-scale, gridy(gy-1)-scale,
gridx(gx)+scale, gridy(gy)+scale)
{redraw end points}
redrawgridpoint(gx, gy-1)
redrawgridpoint(gx, gy)
end
{------------------------------------------------------------------------------}
routine drawtranx(integer gx, gy)
{poly in x-direction}
colour(poly); enable(poly)
clipfill(gridx(gx)-scale3, gridy(gy)-scale,
gridx(gx)+scale3, gridy(gy)+scale)
{diff in y-direction}
colour(diff); enable(diff)
clipfill(gridx(gx)-scale, gridy(gy)-scale3,
gridx(gx)+scale, gridy(gy)+scale3)
end
{------------------------------------------------------------------------------}
routine drawtrany(integer gx, gy)
{poly in y-direction}
colour(poly); enable(poly)
clipfill(gridx(gx)-scale, gridy(gy)-3*scale,
gridx(gx)+scale, gridy(gy)+3*scale)
{diff in x-direction}
colour(diff); enable(diff)
clipfill(gridx(gx)-3*scale, gridy(gy)-scale,
gridx(gx)+3*scale, gridy(gy)+scale)
end
{------------------------------------------------------------------------------}
routine drawcontact(integer gx, gy)
integer xm, xp, ym, yp
colour(contact); enable(contact)
{draw outline}
xm = gridx(gx)-scale2
xp = xm+scale4
ym = gridy(gy)-scale2
yp = ym+scale4
cliphline(xm, xp, ym)
clipvline(xp, ym, yp)
cliphline(xm, xp, yp)
clipvline(xm, ym, yp)
{draw diagonal lines}
clipdbtline(xm, ym, xp, yp)
clipdtbline(xm, yp, xp, ym)
end
{------------------------------------------------------------------------------}
routine drawsubcon(integer gx, gy)
integer x, y, xm, xp, ym, yp
colour(contact); enable(contact)
{draw outline}
x = gridx(gx)
xm = x-scale2
xp = xm+scale4
y = gridy(gy)
ym = y-scale2
yp = ym+scale4
cliphline(xm, xp, ym)
clipvline(xp, ym, yp)
cliphline(xm, xp, yp)
clipvline(xm, ym, yp)
{draw cross}
clipvline(x, ym, yp)
cliphline(xm, xp, y)
end
{------------------------------------------------------------------------------}
routine drawpwell(integer gx, gy)
integer x, y
colour(pwell); enable(pwell)
x = gridx(gx)
y = gridy(gy)
clipfill(x-scale3, y-scale3, x+scale3, y+scale3)
end
{------------------------------------------------------------------------------}
routine redrawdesign
integer x, y
for x = gridxl, 1, gridxr cycle
for y = gridyb, 1, gridyt cycle
redrawprim(x, y)
redrawwirex(x, y)
redrawwirey(x, y)
repeat
repeat
{draw rightmost column of horizontal wires}
redrawwirex(gridxr+1, y) for y = gridyb, 1, gridyt
{draw topmost row of vertical wires}
redrawwirey(x, gridyt+1) for x = gridxl, 1, gridxr
end
{------------------------------------------------------------------------------}
routine redrawgridpoint(integer gx, gy)
redrawprim(gx, gy)
redrawwirex(gx, gy)
redrawwirex(gx+1, gy)
redrawwirey(gx, gy)
redrawwirey(gx, gy+1)
end
{------------------------------------------------------------------------------}
routine redrawprim(integer gx, gy)
integer p
p = vgrid(gx+wgridxl, gy+wgridyb)
if p # 0 then start
if p&pwell # 0 then drawpwell(gx, gy)
if p&tranx # 0 then drawtranx(gx, gy) else c
if p&trany # 0 then drawtrany(gx, gy) else c
if p&contact # 0 then drawcontact(gx, gy) else c
if p&subcon # 0 then drawsubcon(gx, gy)
finish
end
{------------------------------------------------------------------------------}
routine redrawwirex(integer gx, gy)
integer wires, drawn, erased, layers
wires = hvgrid(gx+wgridxl, gy+wgridyb)
drawn = wires&16_f
erased = wires>>4
layers = drawn&(¬erased)
if layers # 0 then drawwirex(layers, gx, gy)
end
{------------------------------------------------------------------------------}
routine redrawwirey(integer gx, gy)
integer layers
layers = vvgrid(gx+wgridxl, gy+wgridyb)
if layers # 0 then drawwirey(layers, gx, gy)
end
{------------------------------------------------------------------------------}
routine pan(integer xi, yi)
{clear display window}
colour(0)
enable(alllayers)
fill(windowxl, windowyb, windowxr, windowyt)
wgridxl = wgridxl+xi
wgridxr = wgridxr+xi
wgridyb = wgridyb+yi
wgridyt = wgridyt+yi
redrawdesign
end
{------------------------------------------------------------------------------}
routine zoomin
setupnewscale(scale+1)
end
{------------------------------------------------------------------------------}
routine zoomout
setupnewscale(scale-1) unless scale = 1
end
{------------------------------------------------------------------------------}
routine drawmenu
integer x, y, xl, xr, yb, yt
erasecursor
{fit menu into display window}
menuxl = mousex-mitemx(curtype)
menuxr = menuxl+menuxs
if menuxl < windowxl then menuxl = windowxl and menuxr = menuxl+menuxs
if menuxr > windowxr then menuxr = windowxr and menuxl = menuxr-menuxs
menuyb = mousey-mitemy(curtype)
menuyt = menuyb+menuys
if menuyb < windowyb then menuyb = windowyb and menuyt = menuyb+menuys
if menuyt > windowyt then menuyt = windowyt and menuyb = menuyt-menuys
{clear menu area and draw menu grid}
colour(menuback)
enable(alllayers+menuback)
fill(menuxl, menuyb, menuxr, menuyt)
{draw menu outline}
colour(contact)
enable(contact)
outline(menuxl, menuyb, menuxr, menuyt)
{draw menu poly}
x = mitemx(mpoly)+menuxl
y = mitemy(mpoly)+menuyb
colour(poly); enable(poly)
fill(x-mwscale, y-mwscale, x+mwscale, y+mwscale)
{draw menu diff}
x = mitemx(mdiff)+menuxl
y = mitemy(mdiff)+menuyb
colour(diff); enable(diff)
fill(x-mwscale, y-mwscale, x+mwscale, y+mwscale)
{draw menu metal1}
x = mitemx(mmetal1)+menuxl
y = mitemy(mmetal1)+menuyb
colour(metal1); enable(metal1)
fill(x-mwscale, y-mwscale, x+mwscale, y+mwscale)
{draw menu metal2}
x = mitemx(mmetal2)+menuxl
y = mitemy(mmetal2)+menuyb
colour(metal2); enable(metal2)
fill(x-mwscale, y-mwscale, x+mwscale, y+mwscale)
{draw menu contact}
x = mitemx(mcontact)+menuxl
xl = x-mwscale
xr = x+mwscale
y = mitemy(mcontact)+menuyb
yb = y-mwscale
yt = y+mwscale
colour(contact); enable(contact)
outline(xl, yb, xr, yt)
line(xl, yb, xr, yt)
line(xl, yt, xr, yb)
{draw menu substrate contact}
x = mitemx(msubcon)+menuxl
xl = x-mwscale
xr = x+mwscale
y = mitemy(msubcon)+menuyb
yb = y-mwscale
yt = y+mwscale
colour(contact); enable(contact)
outline(xl, yb, xr, yt)
vline(x, yb, yt)
hline(xl, xr, y)
{draw menu tranx}
x = mitemx(mtranx)+menuxl
y = mitemy(mtranx)+menuyb
colour(poly); enable(poly)
fill(x-mtscale3, y-mtscale, x+mtscale3, y+mtscale)
colour(diff); enable(diff)
fill(x-mtscale, y-mtscale3, x+mtscale, y+mtscale3)
{draw menu trany}
x = mitemx(mtrany)+menuxl
y = mitemy(mtrany)+menuyb
colour(poly); enable(poly)
fill(x-mtscale, y-mtscale3, x+mtscale, y+mtscale3)
colour(diff); enable(diff)
fill(x-mtscale3, y-mtscale, x+mtscale3, y+mtscale)
{draw menu ptranx}
x = mitemx(mptranx)+menuxl
y = mitemy(mptranx)+menuyb
colour(pwell); enable(pwell)
fill(x-mtscale3, y-mtscale3, x+mtscale3, y+mtscale3)
colour(poly); enable(poly)
fill(x-mtscale3, y-mtscale, x+mtscale3, y+mtscale)
colour(diff); enable(diff)
fill(x-mtscale, y-mtscale3, x+mtscale, y+mtscale3)
{draw menu ptrany}
x = mitemx(mptrany)+menuxl
y = mitemy(mptrany)+menuyb
colour(pwell); enable(pwell)
fill(x-mtscale3, y-mtscale3, x+mtscale3, y+mtscale3)
colour(poly); enable(poly)
fill(x-mtscale, y-mtscale3, x+mtscale, y+mtscale3)
colour(diff); enable(diff)
fill(x-mtscale3, y-mtscale, x+mtscale3, y+mtscale)
{draw menu pwell}
x = mitemx(mpwell)+menuxl
y = mitemy(mpwell)+menuyb
colour(pwell); enable(pwell)
fill(x-mtscale3, y-mtscale3, x+mtscale3, y+mtscale3)
{draw zoom icon}
colour(contact); enable(contact)
x = mitemx(mzoom)+menuxl
y = mitemy(mzoom)+menuyb
outline(x-mwscale, y-mwscale, x+mwscale, y+mwscale)
outline(x-mtscale, y-mtscale, x+mtscale, y+mtscale)
{draw 'input' text}
x = mitemx(minput)+menuxl
y = mitemy(minput)+menuyb
textat(x, y)
showstring("in")
{draw 'output' text}
x = mitemx(moutput)+menuxl
y = mitemy(moutput)+menuyb
textat(x, y)
showstring("out")
{outline current cursor type}
colour(contact); enable(contact)
outline(mitemxl(curtype)+menuxl, mitemyb(curtype)+menuyb,
mitemxr(curtype)+menuxl, mitemyt(curtype)+menuyb)
end
{------------------------------------------------------------------------------}
routine erasemenu
{erase menu area}
colour(0)
enable(alllayers+menuback)
fill(menuxl, menuyb, menuxr, menuyt)
redrawdesign
curgx = mousex//scale6
curgy = mousey//scale6
drawcursor
end
{------------------------------------------------------------------------------}
routine drawcursor
integer x, y, xl, yb, xr, yt, layer
switch cur(1:mitems)
->cur(curtype)
cur(mpoly):layer = poly
->wirecursor
cur(mdiff):layer = diff
->wirecursor
cur(mmetal1):layer = metal1
->wirecursor
cur(mmetal2):layer = metal2
->wirecursor
wirecursor:{draw cursor box for wires}
x = gridx(curgx)
xl = x-scale
xr = x+scale
y = gridy(curgy)
yb = y-scale
yt = y+scale
colour(layer); enable(layer)
clipfill(xl, yb, xr, yt)
->drawout
cur(mcontact):drawcontact(curgx, curgy)
->drawout
cur(msubcon):drawsubcon(curgx, curgy)
->drawout
cur(mtranx):drawtranx(curgx, curgy)
->drawout
cur(mtrany):drawtrany(curgx, curgy)
->drawout
cur(mptranx):drawpwell(curgx, curgy)
drawtranx(curgx, curgy)
->drawout
cur(mptrany):drawpwell(curgx, curgy)
drawtrany(curgx, curgy)
->drawout
cur(mpwell):drawpwell(curgx, curgy)
->drawout
cur(mzoom):
x = gridx(curgx)
xl = x-scale2
xr = x+scale2
y = gridy(curgy)
yb = y-scale2
yt = y+scale2
colour(contact); enable(contact)
clipoutline(xl, yb, xr, yt)
->drawout
drawout:{draw cursor outline)
colour(contact); enable(contact)
x = gridx(curgx)
y = gridy(curgy)
clipoutline(x+curxl(curtype)*scale, y+curyb(curtype)*scale,
x+curxr(curtype)*scale, y+curyt(curtype)*scale)
end
{------------------------------------------------------------------------------}
routine erasecursor
integer x, y
x = gridx(curgx)
y = gridy(curgy)
colour(0); enable(alllayers)
clipfill(x-scale3, y-scale3, x+scale3, y+scale3)
redrawgridpoint(curgx, curgy)
end
{------------------------------------------------------------------------------}
routine flash
integer i
cmap(0) = flashcolour
updatecolourmap(cmap(0))
for i = 1,1,20000 cycle
repeat
cmap(0) = backgroundcolour
updatecolourmap(cmap(0))
end
{------------------------------------------------------------------------------}
endofprogram