(ObjectEdit.JaM) =
(December 9, 1982 10:28 am) = % Michael Plass
% Written by John Warnock
%This file contains the commands that capture all graphics commands with parameters and
%store the commands in an Array (Display List).

(ObjectEditJaM) .loadbcd

%MakeOb enables a dictionary that captures all graphics commands.

(MakeOb)
 {$makeob .begin (nextindex) 0 .def}.cvx .def

%StopOb ends the MakeOb context (if it is in the MakeOb context) and returns an
%Array representing all the graphics commands on the stack.

(StopOb)
 {(No corresponding "makeob")=}.cvx .def

%DrawOb takes an array constructed with MakeOb and StopOb, and executes it.

(DrawOb)
 {.pushdc .dup pushOb .cvx .exec popOb .popdc}.cvx .def

%pushOb, popOb, topOb support DrawOb

(pushOb)
 {(obIndex) obIndex 1 .add .store obArray .exch obIndex .exch .aput}.cvx .def

(popOb)
 {(obIndex) obIndex 1 .sub .store}.cvx .def

(topOb)
 {obArray obIndex .aget }.cvx .def

(obArray)
 .dup .where .not {20 .array .store}.cvx{.pop .pop}.cvx .ifelse

(obIndex)
 0 .def

(olderase)(.erase) .load .def
(.erase){.pushdc .true .setopaque olderase .popdc}.cvx .def

(greyEdit){.false .setopaque 0 0 .5 .hsvcolor EditObject}.cvx .def

%begin dictionary that will hold all the graphics definitions

($makeob) .dup .where .not {128 .dict .store}.cvx{.pop .pop}.cvx .ifelse

(graphicsdict) (.initdc) .where {.def}.cvx{(No graphics loaded)= .end}.cvx .ifelse
graphicsdict (DrawOb) .dup .load .put
$makeob .begin

(StopOb)
 {(at) nextindex .array .def
 0 1 nextindex 1 .sub {.dup temparray .exch .aget at 3 1 .roll .aput}.cvx .for at .end}.cvx .def

(MakeOb)
 {(makeob is illegal here "makeob" in progress)=}.cvx .def


(save)
 {app apc agp 1 .sub -1 0 {.index putparam}.cvx .for aglc putparam agc .exec}.cvx .def

(saveg)
 {app apc agp 1 .sub -1 0 {.index putparam}.cvx .for aglc putparam agc
 .end .exec $makeob .begin}.cvx .def

(savep)
 {app apc agp 1 .sub -2 0 {putpoint}.cvx .for aglc putparam agc .exec}.cvx .def

(savet)
 {app apc agp 1 .sub -2 0 {puttrans}.cvx .for aglc putparam agc .exec}.cvx .def

(putpoint)
 {nextindex (ni) .exch .def .dup 1 .add .index putparam 1 .sub .index putparam ni putparam
 (pointname) .load .cvx putparam}.cvx .def

(puttrans)
 {nextindex (ni) .exch .def .dup 1 .add .index putparam 1 .sub .index putparam ni putparam
 (transname) .load .cvx putparam}.cvx .def

(app)
 {local .exch 0 .exch .aput }.cvx .def %puts parameter count in local.

(apc)
 {0 .aget local .exch 1 .exch .aput }.cvx .def %puts command in local.

(agp)
 {local 0 .aget }.cvx .def %gets parameter count.

(aglc)
 {local 1 .aget }.cvx .def %gets the definition of command.

(agc)
 {local 1 .aget graphicsdict .exch .get }.cvx .def %gets the definition of command.

(local) 2 .array .def

(temparray)
.dup .where .not {2000 .array .store}.cvx{.pop .pop}.cvx .ifelse

(nextindex)
0 .def

(putparam)
 {temparray .exch nextindex .exch .aput (nextindex) nextindex 1 .add .store}.cvx .def


(.initdc)  {{.initdc} 0 save}.cvx .def
(.pushdc)  {{.pushdc} 0 save}.cvx .def
(.popdc)  {{.popdc} 0 save}.cvx .def
(.setview)  { }.cvx .def
(.translate)  {{.translate} 2 savet}.cvx .def
(.scale)   {{.scale} 2 save}.cvx .def
(.rotate)   {{.rotate} 1 save}.cvx .def
(.sixpoint)  {{.sixpoint} 6 save}.cvx .def
(.concat)  { }.cvx .def
(.setpos)  {{.setpos} 2 save}.cvx .def
(.moveto)  {{.moveto} 2 savep}.cvx .def
(.movetonext){{.movetonext} 2 savep}.cvx .def
(.rmoveto)  {{.rmoveto} 2 savep}.cvx .def
(.drawto)  {{.drawto} 2 savep}.cvx .def
(.rdrawto)  {{.rdrawto} 2 savep}.cvx .def
(.drawbox)  {{.drawbox} 4 savep}.cvx .def
(.cover)  { }.cvx .def
(.setinvert)  {{.setinvert} 1 save}.cvx .def
(.setfat)   {{.setfat} 1 save}.cvx .def
(.setopaque) {{.setopaque} 1 save}.cvx .def
(.erase)   {{.erase} 0 save}.cvx .def
(.setfont)  {{.setfont} 1 save}.cvx .def
(.drawcchar) {{.drawcchar} 1 save}.cvx .def
(.drawcstring){{.drawcstring} 1 save}.cvx .def
(.drawchar) {{.drawchar} 1 save}.cvx .def
(.drawtext)  {{.drawtext} 1 save}.cvx .def
(.charbox)  { }.cvx .def
(.textbox)  { }.cvx .def
(.initboxer)  { }.cvx .def
(.stopboxer) { }.cvx .def
(.pushbox)  { }.cvx .def
(.popbox)  { }.cvx .def
(.knot)   {{.knot} 2 savep}.cvx .def
(.spline)  {{.spline} 0 save}.cvx .def
(.cspline)  {{.cspline} 0 save}.cvx .def
(.cliparea) {{.cliparea} 0 save}.cvx .def
(.clipbox)  {{.clipbox} 0 save}.cvx .def
(.clipeoarea) {{.clipeoarea} 0 save}.cvx .def
(.clipxarea)  {{.clipxarea} 0 save}.cvx .def
(.clipxbox)  {{.clipxbox} 0 save}.cvx .def
(.lineto)  {{.lineto} 2 savep}.cvx .def
(.curveto)  {{.curveto} 6 savep}.cvx .def
(.rect)   {{.rect} 4 savep}.cvx .def
(.drawarea)  {{.drawarea} 0 save}.cvx .def
(.draweoarea) {{.draweoarea} 0 save}.cvx .def
(.drawpath) {{.drawpath} 1 save}.cvx .def
(.drawstroke) {{.drawstroke} 2 save}.cvx .def
(.drawstrokeclosed) {{.drawstrokeclosed} 1 save}.cvx .def
(.bitmap)  { }.cvx .def
(.getymode) { }.cvx .def
(.setymode) { }.cvx .def
(.settarget)  { }.cvx .def
(.hsvcolor) {{.hsvcolor} 3 save}.cvx .def
(DrawOb) {{DrawOb} 1 saveg}.cvx .def
.end

%TextOb takes an array an constructs the equivalent text program from the Object.

(TextOb)
 {.mark .exch
 ({ ) .print {.dup .type $atypes .exch .get .exec}.cvx .arrayforall ( }) = .clrtomrk }.cvx .def

($atypes) .dup .where .not {20 .dict .store}.cvx{.pop .pop}.cvx .ifelse
($pntnames) .dup .where .not {20 .dict .store}.cvx{.pop .pop}.cvx .ifelse

$pntnames .begin
 (point) {}.cvx .def
 (trans) {}.cvx .def
.end

$atypes .begin
 (.nulltype) {.pop /cr}.cvx .def
 (.integertype){}.cvx .def
 (.realtype) {}.cvx .def
 (.booleantype){PrintSp}.cvx .def
 (.nametype) {.dup $pntnames .exch .known {.pop .pop}.cvx {.cvlit (cname) .exch .store
     DumpStk cname =}.cvx .ifelse}.cvx .def
 (.stringtype) {/lp .print /rp /cr}.cvx .def
 (.streamtype) {.pop /cr}.cvx .def
 (.commandtype){.commandname PrintSp}.cvx .def
 (.arraytype) {({) .print TextOb (}) =}.cvx .def
 (.marktype) {.pop /cr}.cvx .def
 (.exectype) {.pop /cr}.cvx .def
 (.looptype) {.pop /cr}.cvx .def
 (.scopetype) {.scopename =}.cvx .def
.end

(PrintSp)
 {( ).cvis .print ( ) .print}.cvx .def

(DumpStk)
 {.cnttomrk 1 .sub -1 0 {.index PrintSp}.cvx .for .cnttomrk {.pop}.cvx .rept}.cvx .def


%The following routines are for editing objects that have been constructed.

%EditObject accepts an array (constructed with MakeOb and StopOb) on the stack
 %The yellow button selects a point the red button moves it.


(EditObject)
 {(eobj) .exch .def
 (editInstance) NIL .def
 (obIndex) 0 .store
 (instance) 0 .def
 (point) (pointshow) .load .def
 (trans) (transshow) .load .def
 eobj DrawOb
 ButtonsDef}.cvx .def

(SetView)
 {.touch 2 .copy .screencoords .pop .touch .screencoords .pop .exch .sub 590 .exch .div .dup .scale
 .neg .exch .neg .exch .translate
 (point) (pointshow).load .store
 .erase eobj DrawOb}.cvx .def

(Horizontal)
 {OldButtonsDef
 (teditPoint) editPoint .def
 .touch FindNearest
 (hzy) yMin .def
 .touch FindNearest
 (hzx) xMin .def
 hzx hzy PointUpdate
 ButtonsDef}.cvx .def

(Vertical)
 {OldButtonsDef
 (teditPoint) editPoint .def
 .touch FindNearest
 (vtx) xMin .def
 .touch FindNearest
 (vty) yMin .def
 vtx vty PointUpdate
 ButtonsDef}.cvx .def

%Congruent takes four touches and moves the last point touched so that its distance
% from the third point is equal to the distance between the first two points.

(Congruent)
 {OldButtonsDef
 (teditPoint) editPoint .def
 .touch FindNearest
 (cgx1) xMin .def (cgy1) yMin .def
 .touch FindNearest
 (cgx2) xMin .def (cgy2) yMin .def
 .touch FindNearest
 (cgx3) xMin .def (cgy3) yMin .def
 .touch FindNearest
 (cgx4) xMin .def (cgy4) yMin .def
 cgx2 cgy2 cgx1 cgy1 v2sub v2mag (cgs).exch .store
 cgx4 cgy4 cgx3 cgy3 v2sub v2norm cgs v2scale cgx3 cgy3 v2add PointUpdate
 ButtonsDef}.cvx .def

%Split takes four touches and moves 2nd and last point touched so that the distances
% between the third and fourth is equal to the distance between the first two points.

(Split)
 {OldButtonsDef
 (teditPoint) editPoint .def
 .touch FindNearest
 (cgx1) xMin .def (cgy1) yMin .def
 .touch FindNearest
 (cgx2) xMin .def (cgy2) yMin .def
 (cgedloc) editLoc .def (cgedin) editInstance .def (cgmnob) minObject .def
 .touch FindNearest
 (cgx3) xMin .def (cgy3) yMin .def
 .touch FindNearest
 (cgx4) xMin .def (cgy4) yMin .def
 cgx2 cgy2 cgx1 cgy1 v2sub v2mag (cgs1).exch .store
 cgx4 cgy4 cgx3 cgy3 v2sub v2mag (cgs2) .exch .store
 cgs1 cgs2 .add 2. .div (cgs) .exch .def
 cgx4 cgy4 cgx3 cgy3 v2sub v2norm cgs v2scale cgx3 cgy3 v2add PointUpdate
 (xMin) cgx2 .def (yMin) cgy2 .def
 (editLoc) cgedloc .def (editInstance) cgedin .def (minObject) cgmnob .def
 cgx2 cgy2 cgx1 cgy1 v2sub v2norm cgs v2scale cgx1 cgy1 v2add PointUpdate
 ButtonsDef}.cvx .def


(PrintPoint)
 {editPoint .dup 0 .aget PrintSp 1 .aget =}.cvx .def

(StorePoint)
 {editPoint .exch 1 .exch .aput
 editPoint .exch 0 .exch .aput}.cvx .def



(MinDist)
{2 .copy !eox !eoy v2sub v2mag .dup mindist .lt
 { (mindist) .exch .def
  (minLoc) loc .def  
  (minInstance) instance .def
  (minObject) topOb .def
  (yMin) .exch .def (xMin) .exch .def}.cvx
 {.pop .pop .pop}.cvx
 .ifelse }.cvx .def

(v2add)
 {3 -1 .roll .exch .add 3 1 .roll .add .exch} .cvx .def

(v2sub)
 {3 -1 .roll .exch .sub 3 1 .roll .sub .exch} .cvx .def

(v2mag)
 {.dup .mul .exch .dup .mul .add .sqrt}.cvx .def

(v2neg)
 {.neg .exch .neg .exch}.cvx .def

(v2scale)
 {.dup v2mul}.cvx .def

(v2mul)
 {3 -1 .roll .mul 3 1 .roll .mul .exch} .cvx .def

(v2norm)
 {v2dup v2mag .dup 3 1 .roll .div 3 1 .roll .div .exch}.cvx .def

(v2dup)
 {2 .copy} .cvx .def


(crosstoken)
 {.pushdc .translate
 0 0 0 .hsvcolor
 0 4 .usercoords 0 0 .usercoords v2sub 2 .copy .setpos v2neg .drawto
 4 0 .usercoords 0 0 .usercoords v2sub 2 .copy .setpos v2neg .drawto
 -1 -1 .usercoords 0 0 .usercoords v2sub 2 .copy v2neg .drawbox
 .popdc}.cvx .def

(BumpInstance)
 {(instance) instance 1 .add .store}.cvx .def

(pointtest)
 {(loc) .exch .def 2 .copy .screencoords MinDist BumpInstance}.cvx .def

(pointshow)
 {(myLoc) .exch .store
 editInstance instance .eq {.pop .pop !eox !eoy .usercoords 2 .copy editPoint .astore .pop
 firstInstance {(redraw) .true .store}.cvx .if}.cvx .if
 2 .copy .dottoken BumpInstance myLoc editLoc .eq {(firstInstance) .true .def}.cvx .if }.cvx .def

(pointnil)
 {.pop}.cvx .def

(pointname)
 {point} 0 .aget .cvlit .def

(transtest)
 {(loc) .exch .def 2 .copy .screencoords MinDist BumpInstance}.cvx .def

(transshow)
 {(myLoc) .exch .store
 editInstance instance .eq {.pop .pop !eox !eoy .usercoords 2 .copy editPoint .astore .pop
 firstInstance {(redraw) .true .store}.cvx .if}.cvx .if
 2 .copy crosstoken BumpInstance myLoc editLoc .eq {(firstInstance) .true .def}.cvx .if }.cvx .def

(transnil)
 {.pop}.cvx .def

(transname)
 {trans} 0 .aget .cvlit .def

(NIL)
 20000 .def

%The following definitions enable the editing functions:
%the Red button controls the moving of points.
%the Yellow button selects a point.

(ButtonsDef)
 {(editPoint) editPointArray .def %initialize editPoint.
 (.redup){.screencoords PointUpdate}.cvx .def
 (.yellowup){FindNearest}.cvx .def
(.blueup){.pop .pop OldButtonsDef
   (point) (pointnil) .load .def
   (trans) (transnil) .load .def
   .erase
   eobj DrawOb
   (editPoint) editPointArray .def
   (editInstance) NIL .store
   (editLoc) NIL .store
   (eobj) nilObject .store }.cvx .def
}.cvx .def

(OldButtonsDef)
 {(.reddown){.pop .pop}.cvx .def
 (.redup){.pop .pop}.cvx .def
 (.yellowdown){.pop .pop}.cvx .def
 (.yellowup){.pop .pop}.cvx .def
 (.blueup){.pop .pop}.cvx .def
 (.bluedown){.pop .pop}.cvx .def
 }.cvx .def

(!eox)
 0 .def
(!eoy)
 0 .def

(editPointArray)
  [ 0 0 ] .def % initial value of editPoint

%The following are useful utilities
(FindNearest)
 {.screencoords (!eoy) .exch .store (!eox) .exch .store
 (point)(pointtest).load .def
 (trans)(transtest).load .def
 (mindist) 10000 .def
 (instance) 0 .def
 eobj DrawOb
 (editLoc) minLoc .def
 (editInstance) minInstance .def
 minObject minLoc 2 .subarray (editPoint) .exch .def
 (point)(pointnil).load .def
 (trans)(transnil).load .def
  }.cvx .def

(PointUpdate)
 {(!eoy) .exch .store (!eox) .exch .store
(instance) 0 .store
(firstInstance) .false .store
(redraw) .false .store
.erase
(point) (pointshow) .load .def
(trans) (transshow) .load .def
 eobj DrawOb
redraw {.erase eobj DrawOb}.cvx .if  
}.cvx .def
  
(point)
 (pointnil) .load .def
  
(trans)
 (transnil) .load .def

(editLoc)
NIL .def

(minLoc)
NIL .def

(minInstance)
NIL .def

(nilObject)
 [ ] .def