%! %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % PostScript Structure CyberSpace % Copyright (C) 1989 % By Don Hopkins % All rights reserved. % % WARNING WARNING! DANGER! DANGER WILL ROBINSON! DANGER! % This is *gross* code. I mean UUUUUGLY! I wrote it the week before Usenix. % You're damn right it needs to be rewritten. But you get the idea, ehe? systemdict begin statusdict begin 0 setjobtimeout end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Load necessary stuff systemdict /NeWSScrollbar known not { (/usr/NeWS/clientsrc/client/nterm/NeWSSbar.ps) LoadFile } if systemdict /TextCanvas known not { (/usr/NeWS/clientsrc/client/nterm/textcan.ps) LoadFile } if %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % StructItem class definition /StructItem LabeledItem dictbegin %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Instance variables /Shrink .8 def /Pad 3 def /StartPoint 14 def /Point StartPoint def /x 0 def /y 0 def /Levels 0 def /DL null def /UpdateDL? true def /ItemFrame 2 def /ItemRadius 5 def /ItemBorder 6 def /ItemButton [PointButton MenuButton] def /StackI null def /LayoutLock null def /LastX 0 def /LastY 0 def /LastTime 0 def /DX 0 def /DY 0 def /TabX 0 def /TabY 0 def /TabWidth 0 def /TabHeight 0 def /PinX 0 def /PinHeight 0 def /DropShadow 6 def dictend classbegin %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Class variables /DoubleClickTime 1 60 div def /CanvasYFudge 2 store /Sort? true def /SlidePower .4 store /SlideSpeed .05 60 div store /MaxV .1 store /LineGap 30 def /ItemLabelFont /Helvetica-Bold findfont 14 scalefont def /ItemFont /Courier findfont def /ItemXFont /Courier-Oblique findfont def /Icon? false def /SortBy /by-name def /View /layout-struct def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Initialization stuff /new { % Collection Index notifyproc parentcanvas => instance 4 2 roll 2 copy get type (% \267) sprintf % notify parent cont ind label 5 1 roll 2 array astore % label notify parent object 3 1 roll /Right % label object notify parent loc 3 1 roll % label object loc notify parent /new super send begin ItemCanvas /Transparent false put ItemCanvas /Retained true put /LayoutLock createmonitor def currentdict end } def /ensure-DL { UpdateDL? { Collection Index Levels grow-struct /DL exch store /ObjectWidth 0 store /ObjectHeight 0 store /UpdateDL? false store } if ObjectWidth 0 eq ObjectHeight 0 eq or { perform-layout } if } def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Event handlers /ClientDown { CurrentEvent update-shifts CurrentEvent /Name get MenuButton eq { event-in-tab? { show-tab-menu } { show-struct-menu } ifelse } if } def /show-tab-menu { userdict /it self put CurrentEvent /showat TabMenu send } def /show-struct-menu { ItemBegin userdict /it self put do-search ob null ne { CurrentEvent /showat StructMenu send } if ItemEnd } store /ClientUp { CurrentEvent update-shifts CurrentEvent /Name get PointButton eq { NotifyUser } if StopItem } def /click-point { ItemBegin event-in-tab? { point-tab } { point-struct } ifelse ItemEnd } def /point-tab { DL begin gsave /Icon? Icon? not def Icon? { /OW ObjectWidth def /OH ObjectHeight def Font setfont Str stringbbox points2rect /IconH exch def /IconW exch def /ObjectWidth IconW store /ObjectHeight IconH store } { /ObjectWidth OW store /ObjectHeight OH store } ifelse grestore end redo-shape /LastTime 0 store } def /point-struct { ItemCanvas setcanvas CurrentEvent begin LastX XLocation sub dup mul LastY YLocation sub dup mul add end 4 lt currenttime LastTime sub DoubleClickTime lt and not { % first click /it self store do-search userdict /ob get null ne { Shift { % Shift to select the index ob /I get } { ob /Obj get } ifelse /LastTime currenttime store Control { exec-it /LastTime 0 store } { select-object } ifelse } if ItemCanvas setcanvas CurrentEvent begin /LastX XLocation store /LastY YLocation store end } { % double clicks ob null ne { DL begin Icon? end { point-tab } { open-struct } ifelse } if /LastTime 0 store } ifelse } store /event-in-tab? { ItemBegin newpath label-bbox rectpath CurrentEvent begin XLocation YLocation end pointinpath ItemEnd } def /ClientExit { StopItem } def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Menu definitions /PointMenu [ (2) (4) (6) (8) (10) (12) (14) (16) (18) (20) (22) (24) (28) (32) ] [ {currentkey cvi {/StartPoint exch def redo-layout} it send} ] /new DefaultMenu send def /LocationMenu [ (LeftBelow) (LeftAbove) (AboveLeft) (AboveRight) (RightAbove) (RightBelow) (BelowRight) (BelowLeft) ] [ { currentkey cvn {/ObjectLoc exch def location 10 10 reshape damage-view} it send} ] /new DefaultMenu send store LocationMenu /PieInitialAngle 360 16 div put /ShrinkMenu [ (.1) (.2) (.3) (.4) (.5) (.6) (.7) (.8) (.9) (1) ] [ {currentkey cvr {/Shrink exch def redo-layout} it send} ] /new DefaultMenu send def /TabMenu [ (Point...) PointMenu (---) {} (Print) {/write-DL it send} (Zap) {/Free it send} (Shrink...) ShrinkMenu (---) {} (Location...) LocationMenu (Pack) {/pack it send} ] /new DefaultMenu send store /ChangeMenu [ (toke in) { /token-obj it send } (executable){ /cvx-obj it send } (name) { /cvn-obj it send } (string) { /cvs-obj it send } (toke out) { /tokout-obj it send } (literal) { /cvlit-obj it send } (integer) { /cvi-obj it send } (real) { /cvr-obj it send } ] /new DefaultMenu send def /EditMenu [ (undef) { /undef-obj it send } (emacs) {} % tokout to emacs (nulldef) { /nulldef-obj it send } (primary) {} % tokout to Primary selection ] /new DefaultMenu send def EditMenu /PieInitialAngle 45 put /StructMenu [ (push) {/push-obj it send} (load&push) {/load&push-obj it send} (load) {/load-obj it send} (edit...) EditMenu (exec) {/exec-obj it send} (change...) ChangeMenu (paste) {/paste-obj it send} (open) {/open-obj it send} ] /new DefaultMenu send def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Menu callbacks /token-obj { { clear Externals begin ob /Obj get { { token { exch } { exit } ifelse } loop } errored { clear ob /Obj get } { count array astore cvx } ifelse end } fork waitprocess replace-obj } def /cvx-obj { { ob /Obj get cvx } errored {pop} { replace-obj } ifelse } def /cvn-obj { { ob /Obj get cvn } errored {pop} { replace-obj } ifelse } def /cvs-obj { { ob /Obj get 256 string cvs } errored {pop} { replace-obj } ifelse } def /tokout-obj { ob /Obj get tokout replace-obj } def /cvlit-obj { { ob /Obj get cvlit } errored {pop} { replace-obj } ifelse } def /cvi-obj { { ob /Obj get cvi } errored {pop} { replace-obj } ifelse } def /cvr-obj { { ob /Obj get cvr } errored {pop} { replace-obj } ifelse } def /load&push-obj { ob /Obj get load&push-it } def /load&push-it { % [ exch cvlit {dup load} /errored cvx { pop (%% ) (%Load: % is not defined!\n) printf } { exch 1 index exch (%% ) (%Load: % Push: %\n) printf } /ifelse cvx ] cvx execute-it } def /load-obj { ob /Obj get load-it } def /load-it { % [ exch cvlit {dup load} /errored cvx { pop (%% ) (%Load: % is not defined!\n) printf } { exch 1 index exch (%% ) (%Load: % Select: %\n) printf select-object } /ifelse cvx ] cvx execute-it } def /open-obj { open-struct } def /push-obj { ob /Obj get push-it } def /push-it { [ exch [ exch ] 0 /get cvx /dup cvx (%% ) (%Push: %\n) /printf cvx ] cvx execute-it } def /nulldef-obj { ob /Obj get dup type /dicttype ne { pop } { selected-object dup null eq { pop } { 2 copy null put 0 grow-struct ob begin Branches null ne { /Branches [ Branches { dup /I get counttomark 2 add index /I get eq {pop} if } forall counttomark 3 add -1 roll ] Sort? {SortBy quicksort} if def } if end redo-layout } ifelse } ifelse } store /undef-obj { ob /Obj get dup type /dicttype ne { pop } { selected-object dup null eq { pop } { 2 copy known { 2 copy undef ob begin Branches null ne { /Branches [ Branches { begin /C load /I load known { currentdict } if end } forall ] def } if end redo-layout } if } ifelse } ifelse } store /exec-obj { ob /Obj get exec-it } def /exec-it { % obj => - { [ exch cvlit /cvx cvx /dup cvx (%% ) (%Exec: %\n) /printf cvx cvx /exec cvx ] cvx execute-it } fork pop pause } def /paste-obj { selected-object replace-obj } def /replace-obj { % obj => - ob begin replace-struct end redo-layout } def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Moving and shaping /just-reshape { /ItemHeight exch def /ItemWidth exch def ItemWidth 0 eq ItemHeight 0 eq and { /UpdateDL? true store } if ensure-DL adjust-geometry ItemWidth ItemHeight /reshape super send gsave ItemCanvas setcanvas ItemFillColor fillcanvas grestore } def /reshape { % x y w h just-reshape location move } def /just-move { /move super send } def /move { % x y label-bbox /lh exch def /lw exch def % x y lx ly 2 index add /ly exch def % x y lx 2 index add /lx exch def % x y ly 0 max /ClientHeight win send lh sub min ly sub add exch lx 0 max /ClientWidth win send lw sub min lx sub add exch /move super send snaps-here? pop Index ThisI eq {/paint-hilite win send} if StackI null ne StackI Index ne and { /MoveMe TellStack } if } store /redo-layout { perform-layout redo-shape } def /redo-shape { location 10 10 just-reshape damage-view } def /label-bbox { % x y w h TabX TabY TabWidth TabHeight } def /tab-top { % - => y location TabY add TabHeight add exch pop } def /tab-bottom { % - => y location TabY add exch pop } store /label-rect { % X Y w h location TabY add exch TabX add exch TabWidth TabHeight } def /pin-rect { % X Y w h location exch PinX add 3 sub exch % x y PinHeight 0 lt { PinHeight add } if ItemHeight PinHeight abs add 6 exch } def /object-bbox { % x y w h ObjectX ItemBorder sub ObjectY ItemBorder sub % x y ObjectWidth ItemBorder dup add add % w ObjectHeight ItemBorder dup add add % h } def /ItemPath { ItemRadius label-bbox rrectpath ItemRadius object-bbox rrectpath } def /AdjustItemSize { % - => - [uses item context] ObjectLoc [ /Right /Left /RightBelow /RightAbove /LeftBelow /LeftAbove { /ItemWidth ItemBorder 3 mul ItemGap add LabelWidth add ObjectWidth add def /ItemHeight ItemBorder 2 mul LabelHeight ObjectHeight max add def } /Top /Bottom /AboveLeft /AboveRight /BelowLeft /BelowRight { /ItemWidth ItemBorder 2 mul LabelWidth ObjectWidth max add def /ItemHeight ItemBorder 3 mul ItemGap add LabelHeight add ObjectHeight add def } ] case } store /CalcObj&LabelXY { % - => - [uses item context] ObjectLoc { /RightAbove { /LabelX ItemBorder def /LabelY ItemBorder def /ObjectX ItemBorder dup add LabelWidth add ItemGap add def /ObjectY ItemHeight ObjectHeight sub 2 div def /TabX LabelX ItemBorder sub def /TabY LabelY ItemBorder sub def /TabWidth ItemBorder LabelWidth add ItemGap add ItemRadius dup add add def /TabHeight LabelHeight ItemBorder dup add add def } /RightBelow /Right { /LabelX ItemBorder def /LabelY ItemHeight ItemBorder sub LabelHeight sub def /ObjectX ItemBorder dup add LabelWidth add ItemGap add def /ObjectY ItemHeight ObjectHeight sub 2 div def /TabX LabelX ItemBorder sub def /TabY LabelY ItemBorder sub def /TabWidth ItemBorder LabelWidth add ItemGap add ItemRadius dup add add def /TabHeight LabelHeight ItemBorder dup add add def } /LeftAbove { /LabelX ItemBorder dup add ItemGap add ObjectWidth add def /LabelY ItemBorder def /ObjectX ItemBorder def /ObjectY ItemHeight ObjectHeight sub 2 div def /TabX LabelX ItemGap sub ItemRadius dup add sub def /TabY LabelY ItemBorder sub def /TabWidth ItemRadius dup add ItemGap add LabelWidth add ItemBorder add def /TabHeight LabelHeight ItemBorder dup add add def } /LeftBelow /Left { /LabelX ItemBorder dup add ItemGap add ObjectWidth add def /LabelY ItemHeight ItemBorder sub LabelHeight sub def /ObjectX ItemBorder def /ObjectY ItemHeight ObjectHeight sub 2 div def /TabX LabelX ItemGap sub ItemRadius dup add sub def /TabY LabelY ItemBorder sub def /TabWidth ItemRadius dup add ItemGap add LabelWidth add ItemBorder add def /TabHeight LabelHeight ItemBorder dup add add def } /AboveRight /Top { /LabelX ItemBorder def /LabelY ItemBorder def /ObjectX ItemWidth ObjectWidth sub 2 div def /ObjectY ItemBorder dup add LabelHeight add ItemGap add def /TabX LabelX ItemBorder sub def /TabY LabelY ItemBorder sub def /TabWidth LabelWidth ItemBorder dup add add def /TabHeight ItemBorder LabelHeight add ItemGap add ItemRadius dup add add def } /AboveLeft { /LabelX ItemWidth ItemBorder sub LabelWidth sub def /LabelY ItemBorder def /ObjectX ItemWidth ObjectWidth sub 2 div def /ObjectY ItemBorder dup add LabelHeight add ItemGap add def /TabX LabelX ItemBorder sub def /TabY LabelY ItemBorder sub def /TabWidth LabelWidth ItemBorder dup add add def /TabHeight ItemBorder LabelHeight add ItemGap add ItemRadius dup add add def } /BelowRight /Bottom { /LabelX ItemBorder def /LabelY ItemBorder dup add ObjectHeight add ItemGap add def /ObjectX ItemWidth ObjectWidth sub 2 div def /ObjectY ItemBorder def /TabX LabelX ItemBorder sub def /TabY LabelY ItemGap sub ItemRadius dup add sub def /TabWidth LabelWidth ItemBorder dup add add def /TabHeight ItemRadius dup add ItemGap add LabelHeight add ItemBorder add def } /BelowLeft { /LabelX ItemWidth ItemBorder sub LabelWidth sub def /LabelY ItemBorder dup add ObjectHeight add ItemGap add def /ObjectX ItemWidth ObjectWidth sub 2 div def /ObjectY ItemBorder def /TabX LabelX ItemBorder sub def /TabY LabelY ItemGap sub ItemRadius dup add sub def /TabWidth LabelWidth ItemBorder dup add add def /TabHeight ItemRadius dup add ItemGap add LabelHeight add ItemBorder add def } } case /PinX LabelX LabelWidth add 2 sub def } def /adjust-geometry { /ItemLabel Collection Index get type (% \267) sprintf store LabelSize /LabelHeight exch def /LabelWidth exch def AdjustItemSize CalcObj&LabelXY } def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Display /PaintItem { ItemRadius label-bbox rrectpath ItemFillColor setcolor fill ItemFrame 0 gt { ItemFrame ItemRadius label-bbox rrectframe ItemBorderColor setcolor eofill } if ItemRadius object-bbox rrectpath ItemFillColor setcolor fill ItemFrame 0 gt { ItemFrame ItemRadius object-bbox rrectframe ItemBorderColor setcolor eofill } if ShowLabel paint-struct } store /paint-struct { gsave ensure-DL ItemTextColor setcolor ObjectX ObjectY ObjectHeight add translate DL draw-struct grestore } def /damage-view { gsave %ItemParent setcanvas bbox rectpath extenddamage paint grestore } def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Accessers /Collection { ItemObject 0 get cvlit } def /Index { ItemObject 1 get cvlit } def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Structure stuff /old-search-struct { % proc x y dict => proc x y begin dup Y ge { dup Y H add lt { % Path setpath newpath X Y W H rectpath %(x % y % X % Y % W % H % \n)[3 index 3 index X Y W H ]dbgprintf 2 copy pointinpath { 2 index exec } { Branches null ne { Branches { search-struct } forall } if } ifelse } if } if end } def /do-search { DL begin Icon? end { /obs [ DL ] store /ob DL store } { gsave ItemCanvas setcanvas ObjectX ObjectY ObjectHeight add translate DL CurrentEvent begin XLocation YLocation end search-struct /obs exch store obs length 0 eq { null } { obs dup length 1 sub get } ifelse /ob exch store grestore } ifelse } def % Return the path down the display list to the substructure enclosing (x,y). /search-struct { % dict x y => [ dl1 dl2 ... dln ] 10 dict begin /ssy exch def /ssx exch def [ exch { do-search-struct % unsucessful search exit } loop % catch possible exit ] end } def /do-search-struct { % dl => dl dl' dl'' dl''' ... begin ssx X ge { ssy Y ge { ssx X W add le { ssy Y H add le { currentdict Branches end dup null eq { pop } { { do-search-struct } forall } ifelse exit % skip past all the ends on the execution stack } if } if } if } if end } store /open-struct { gsave DL /Icon? undef ItemCanvas setcanvas ObjectX ObjectY ObjectHeight add translate ob begin L 0 eq Shift or { L 1 add grow-substruct } { /L 0 def /Branches null def } ifelse end % ob Meta not { redo-layout } if grestore } def % (dl on dictstack) /replace-struct { % obj => - C I 3 -1 roll put C I 0 grow-struct begin /Branches Branches /C dup load /I dup load /L L /Obj dup load /Str Str /X X /Y Y /W W /H H end def def def def def def def def def def def } def /grow-substruct { % l => - /L exch def /forbidden? {pop false} def /Branches C I L grow-struct 1 index get def currentdict /forbidden? undef } def /composite? { % obj => bool type { /arraytype /dicttype /canvastype /processtype /eventtype /fonttype {true} /Default {false} } case } def /forbidden-dict 50 dict def forbidden-dict begin /Interests null def /Process null def /BuildChar null def /Encoding null def /WidthArray null def /ParentDictArray null def /ParentDict null def /TopCanvas null def /BottomCanvas null def /TopChild null def /CanvasAbove null def /CanvasBelow null def /Parent null def end % forbidden-dict /forbidden? { forbidden-dict exch known } def % Collection Index Levels => dict /grow-struct { /xcurs /xcurs_m ItemCanvas setstandardcursor LayoutLock { /hourg /hourg_m ItemCanvas setstandardcursor do-grow-struct } monitor /ptr /ptr_m ItemCanvas setstandardcursor } def /do-grow-struct { pause 32 dict begin /L exch def cvlit /I exch def cvlit /C exch def /Obj C I get def /Str /Obj load I (% = %) sprintf def /X 0 def /Y 0 def /W 0 def /H 0 def /StrY 0 def /LineX 0 def /Obj load composite? I forbidden? not and L 0 gt and { /Obj load dup type /arraytype eq { /Branches exch [ exch { pop /Obj load counttomark 1 sub L 1 sub do-grow-struct } forall ] def } { /Branches exch [ exch { pop /Obj load exch L 1 sub do-grow-struct } forall ] Sort? {SortBy quicksort} if def } ifelse } { /Branches null def } ifelse currentdict end } def % /SortBy default: /by-name { /Str get exch /Str get lt } def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Layout /perform-layout { /xcurs /xcurs_m ItemCanvas setstandardcursor LayoutLock { /hourg /hourg_m ItemCanvas setstandardcursor /ItemLabel Collection Index get type (% \267) sprintf store init-format DL do-layout /ObjectHeight DL /Y get neg store adjust-geometry } monitor /ptr /ptr_m ItemCanvas setstandardcursor } def /init-format { /Point StartPoint def /x 0 def /y 0 def /ObjectWidth 0 def /ObjectHeight 0 def } def /LineHeight { currentfont fontheight 1 add } def /do-layout { % dict => - begin /View load cvx exec end pause } def /layout-struct { % - => - /Str /Obj load I (% = %) sprintf def /Obj load xcheck Point 10 ge and { /Font ItemXFont Point scalefont def } { /Font ItemFont Point scalefont def } ifelse Font setfont /X x def /Y y def /W Str stringwidth pop LineGap add def Branches null eq { % Icon? or /H LineHeight def } { /x x W add store /Point Point Shrink mul store Branches { do-layout } forall /Point Point Shrink div store /x x W sub store 0 0 % w h Branches { begin exch W max exch H add end } forall % W H LineHeight max 1 max /H exch def /LineX X W add LineGap sub def W add /W exch def } ifelse /Y Y H sub def /StrY Y Font fontdescent add H LineHeight sub 2 div add def /y Y store /ObjectWidth ObjectWidth x W add LineGap sub max store } store % dict => - /draw-struct { pause begin Icon? { gsave Font setfont 0 Font fontdescent IconH sub 2 copy moveto Str show translate -2 ItemRadius Str stringbbox points2rect insetrrect rrectpath 0 setlinewidth 0 setgray stroke grestore } { show-obj Branches null ne Icon? not and { LineX Y H 2 div add Branches length 0 ne { Branches 0 get begin 2 copy moveto X Pad sub Y H add lineto W 0 rlineto stroke end Branches { begin 2 copy moveto X Pad sub Y lineto Pad dup add 0 rlineto stroke currentdict end draw-struct } forall Branches dup length 1 sub get begin 2 copy moveto X Pad sub Y lineto W 0 rlineto stroke end } if pop pop } if } ifelse end } store /show-obj { Font setfont X StrY moveto Str show } def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Printing % This needs to be brought up to date... /write-DL { % { /f (DL.ps) (w) file def f (%!\n) writestring f (gsave 0 setgray 0 setlinewidth 20 20 translate\n) writestring DL begin f H W (%%) (%BoundingBox: 0 0 % %\n) sprintf writestring end /cur-font-name null def /cur-font-size 0 def DL print-struct f (grestore showpage\n) writestring f closefile } stopped pop } def /print-struct { % dict => - pause begin Font /FontMatrix get 0 get /Obj load xcheck ItemXFont ItemFont ifelse /FontName get 1 index cur-font-size eq 1 index cur-font-name eq and { pop pop } { 2 copy /cur-font-name exch store /cur-font-size exch store (/% findfont % scalefont setfont\n) sprintf f exch writestring } ifelse Font setfont Font fontdescent StrY ObjectHeight add X (% % moveto ) sprintf f exch writestring Str ( (%) show\n) sprintf f exch writestring Branches null ne Icon? not and { X W add LineGap sub Y H 2 div add ObjectHeight add Branches { begin 2 copy exch (% % moveto ) sprintf f exch writestring X Pad sub Y ObjectHeight add exch (% % lineto ) sprintf f exch writestring Pad 2 mul 0 exch (% % rlineto ) sprintf f exch writestring f (stroke\n) writestring currentdict end print-struct } forall Branches length 0 ne { Branches dup length 1 sub get begin 2 copy exch (% % moveto ) sprintf f exch writestring X Pad sub Y H add ObjectHeight add exch (% % lineto ) sprintf f exch writestring Pad 2 mul 0 exch (% % rlineto ) sprintf f exch writestring f ( stroke\n) writestring end } if pop pop } if end } def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Stack stuff /execute-it { % obj => - /exec-and-update items StackI null eq ThisI StackI ifelse get send } def /TellStack { % message => - createevent begin /Name exch def /ClientData Index def /Action StackI def /Canvas ItemParent def currentdict end sendevent } def /pack { StackI null ne { /PackStack items StackI get send } if } def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Snap dragging /pinned? { % y h => bool location pop PinX add 3 1 roll % x y h 6 exch % x y w h pin-rect rectsoverlap } store % items backgroundcolor => - (interactively move item) /moveinteractive { ItemBegin 10 dict begin /GA_constraint 0 def /GA_value /calc_GA_value load def currentcursorlocation /DY exch def /DX exch def currentcanvas mapcanvas false dragcanvas end ItemEnd } store /SnapIn { ThisI StackI ne { StackI null ne { /PopMe TellStack } if /StackI ThisI store /PushMe TellStack } if } def /SnapOut { StackI null ne StackI Index ne and { /PopMe TellStack /StackI null store } if } def /snaps-here? { % - => bool ThisI null eq ThisI Index eq or {false} { /pin-rect items ThisI get send label-rect rectsoverlap dup { SnapIn } { SnapOut } ifelse } ifelse } def /calc_GA_value { StackI Index eq { currentcursorlocation pop % cx } { StackI null eq { snaps-here? { location pop DX add % ix } { currentcursorlocation pop % cx } ifelse } { location TabY add TabHeight /pinned? items StackI get send not { SnapOut pop currentcursorlocation pop % cx } { % ix { location pop PinX add } items StackI get send % ItemX PinX PinX sub % ItemX ItemGoal exch 1 index exch sub % ItemGoal ItemDelta currentcursorlocation pop % ItemGoal ItemDelta CurX' 2 index exch sub % ItemGoal ItemDelta CurDelta DX add dup abs TabWidth gt { SnapOut pop pop pop currentcursorlocation pop DX sub } { 1 index abs 1 index abs gt {exch} if % ItemGoal Close Far pop % ItemGoal Close .2 mul sub } ifelse DX add } ifelse } ifelse } ifelse } store /NextPos { % - => x y location % x y label-bbox % X Y x y w h exch pop add % X Y x y+h 3 -1 roll add % X x Y+y+h exch 3 -1 roll add exch % X+x Y+y+h exch PinX add exch } def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Storage managment /Free { SnapOut ItemCanvas /Retained false put unmap ItemLock { /free-items [ free-items aload pop Index ] store } monitor } def /init-attributes { {/ObjectWidth /DL /UpdateDL? /Shrink /StartPoint /PinHeight} { InstanceVarDict 1 index get store } forall /ObjectLoc /Right store adjust-geometry } store % obj => - /Reuse { Collection Index 3 -1 roll put ItemCanvas /Retained true put ItemCanvas canvastotop init-attributes ensure-DL redo-layout } store classend def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % TextStructItem class definition /TextStructItem StructItem dictbegin %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Instance variables /I null def /MyStack null def /MyProcess null def /Scroller null def /ScrollerWidth 16 def /Notifier null def /NotifierHeight 16 def /SubItemGap 2 def /SubItemMgr null def /DeferedUpdateEvent null def /DeferedStack null def /UpdateDelay .25 60 div def dictend classbegin %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Class Variables /TextWidth 600 def /TextHeight 150 def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % /new { /new super send begin /MyStack [] def /ItemLabel (processtype) def currentdict end } def /kbd-reset { /dialog-buf () store /dialog-string () store {(\n%% Reset!\n) print} execute-it } def /shut-down { { psh-socket (\ndbgstop\nquit\n) writestring psh-socket flushfile } errored pop null {{dbgstop} errored exit} send-exec-event 1 60 div sleep } def /kbd-reboot { { /dialog-buf () store /dialog-string () store [ () (%% Reboot!) () ] true /writeatcaret dialog-text send shut-down psh-socket closefile /psh-socket null store ensure-DL % { EventMgr null ne { EventMgr killprocess } if % /EventMgr Interests forkeventmgr store % KeyboardEventMgr null ne { KeyboardEventMgr killprocess } if % /KeyboardEventMgr { KeyboardHandler } fork store % } dialog-text send start-event-mgrs } fork waitprocess pop } def /select-process { selected-object dup type /processtype eq { set-process } if } def /adjust-geometry { LabelSize /LabelHeight exch def /LabelWidth exch def AdjustItemSize CalcObj&LabelXY } def /DialogMenu [ (pack) {/PackStack it send} (reset) {/kbd-reset it send} (reboot) {/kbd-reboot it send} (process) {/select-process it send} ] /new DefaultMenu send def /SelectionMenu [ (push) {{Collection Index get push-it} it send} (load) {{Collection Index get load-it} it send} (exec) {{Collection Index get exec-it} it send} (change...) /ChangeMenu StructItem send ] /new DefaultMenu send def /replace-obj { % obj => - Collection Index 2 index put select-object } def /show-tab-menu { userdict /it self put CurrentEvent /showat DialogMenu send } def /show-struct-menu { userdict /it self put userdict /ob 20 dict put ob begin /C Collection def /I Index def /Obj Collection Index get def end CurrentEvent /showat SelectionMenu send } def /exec-and-update { % func => - { exec count array astore aload createevent begin /Name /UpdateStack def /ClientData exch def /Canvas _ViewCanvas def currentdict end sendevent } send-exec-event } def /send-exec-event { % data action 6 { % wait up to 3 seconds if no process MyProcess null eq { .5 60 div sleep } { exit } ifelse } repeat MyProcess null eq { pop pop gsave framebuffer setcanvas currentcursorlocation [(No process!)] popmsg pop grestore } { createevent begin /Name /ExecIt def /Process MyProcess def /Action exch def /ClientData exch def currentdict end sendevent } ifelse } def /UpdateStack { % DeferedUpdateEvent null ne { DeferedUpdateEvent recallevent } if /DeferedUpdateEvent CurrentEvent store DeferedUpdateEvent begin /Name /DeferedUpdate def /TimeStamp currenttime UpdateDelay add def end % event DeferedUpdateEvent sendevent } def /DeferedUpdate { % /DeferedUpdateEvent null store [ /getcaretpos dialog-text send pop 1 gt { () } if dialog-string dialog-buf CurrentEvent /ClientData get length (NeWS[%]> %%) sprintf { (\n) search { % chop string up at newlines exch pop exch } { exit } ifelse } loop ] true /writeatcaret dialog-text send pause CurrentEvent /ClientData get SetStack } def /ProcessReady { CurrentEvent dup /ClientData get exch /Action get set-process } def /set-process { % stack process => - /MyProcess exch def SetStack { currentprocess (%% ) (%Hello, my name is %!\n) printf } execute-it } def /SelectionChanged { CurrentEvent /Action get /PrimarySelection eq { CurrentEvent /ClientData get dissect-selection Collection Index 2 index put (%: %) [ 3 -1 roll dup type exch ] /printf Notifier send } if } def /makestartinterests { /makestartinterests super send [ exch aload pop /ProcessReady {/ProcessReady /Self GetFromCurrentEvent send} null ItemCanvas eventmgrinterest dup /Self self PutInEventMgrInterest /UpdateStack {/UpdateStack /Self GetFromCurrentEvent send} null ItemCanvas eventmgrinterest dup /Self self PutInEventMgrInterest /DeferedUpdate {/DeferedUpdate /Self GetFromCurrentEvent send} null ItemCanvas eventmgrinterest dup /Self self PutInEventMgrInterest /SelectionChanged {/SelectionChanged /Self GetFromCurrentEvent send} null null eventmgrinterest dup /Self self PutInEventMgrInterest /PushMe {/DoPushMe /Self GetFromCurrentEvent send} Index ItemParent eventmgrinterest dup /Self self PutInEventMgrInterest /PopMe {/DoPopMe /Self GetFromCurrentEvent send} Index ItemParent eventmgrinterest dup /Self self PutInEventMgrInterest /MoveMe {/DoMoveMe /Self GetFromCurrentEvent send} Index ItemParent eventmgrinterest dup /Self self PutInEventMgrInterest ] } def /DoPushMe { CurrentEvent /ClientData get PushMe } def /DoPopMe { CurrentEvent /ClientData get PopMe } def /DoMoveMe { LayoutLock { SortStack ReplaceStack } monitor } def /PushMe { % index => - LayoutLock { /I exch def /MyStack [ MyStack { dup I eq {pop} if } forall I ] store SortStack GetStack {count 1 roll count 1 sub {pop} repeat aload pop} [ {Collection Index get} items I get send (%% ) (%Drag Push: %\n) sprintf /print cvx] append cvx send-exec-event } monitor } def /SortStack { MyStack { /tab-top exch items exch get send exch /tab-top exch items exch get send lt } quicksort pop } store /PopMe { % index => - LayoutLock { /I exch def /MyStack [ MyStack { dup I eq {pop} if } forall ] store GetStack {count 1 roll count 1 sub {pop} repeat aload pop} [ {Collection Index get} items I get send (%% ) (%Drag Pop: %\n) sprintf /print cvx] append cvx send-exec-event } monitor } def /ReplaceStack { GetStack {count 1 roll count 1 sub {pop} repeat aload pop} send-exec-event } def % To do: % Make this premptable: Each pass it does one thing to make the % display look more like MyStack. (bottom to top priority) /SetStack { % stack => - LayoutLock { ItemBegin 10 dict begin /NewStack exch def /OldStack 200 dict def MyStack { items 1 index get {Collection Index get} exch send OldStack 3 1 roll put } forall /MyStack [] store NewStack { % new pause /I null def OldStack { % new ind old dup 3 index eq { % new ind old xcheck 2 index xcheck eq { % new ind /I exch def exit % new } { pop } ifelse % new } { pop pop } ifelse % new } forall % new pause /I load null ne { pop % OldStack /I load undef /MyStack [ MyStack aload pop /I load ] store } { % new /MyStack [ MyStack aload length 3 add -1 roll % /MyStack [ ... new create-struct % /MyStack [ ... newind ] store % } ifelse } forall pause OldStack { % ind old pop % ind items exch get % item dup /StackI null put % XXX /Free exch send % pause } forall pause /Y tab-top def MyStack { % ind items exch get % item Y { % PrevTop dup tab-bottom exch sub % PrevTop below dup 0 lt { location 2 index sub just-move pause } if pop pop tab-top } 3 -1 roll send % NextTop /Y exch def % } forall % pin-rect % x y w h exch pop add exch pop % PinTop Y lt { % if we ran off the top of the stack, then pack it down. PackStack } if pause ItemEnd end } monitor } store /create-struct { % obj => i ItemLock { 20 dict begin /Obj exch def NextStackPos /NextY exch def /NextX exch def free-items length 0 eq { Stack SP /Obj load put Stack SP {click-point} can /new StructItem send /It exch def /items [ items aload pop It ] store /I SP def /SP SP 1 add store It /StackI Index put createevent begin /Name /UpdateInterests def /Canvas ItemParent def /ClientData I def currentdict end sendevent } { /I free-items dup length 1 sub get def /It items I get def /free-items [ free-items aload pop pop ] store It /StackI Index put /Obj load /Reuse It send } ifelse NextX NextY { 2 copy 20 20 just-reshape exch PinX sub exch just-move map damage-view } It send I pause pause end } monitor } store /GetStack { % Don't use [ ... ] in case there are marks on the stack!! MyStack { {Collection Index get} exch items exch get send } forall MyStack length array astore } def /PackStack { 10 dict begin /Y tab-top def MyStack { items exch get Y { % PrevTop dup tab-bottom exch sub % PrevTop below location 2 index sub just-move pause pause pop pop tab-top } 3 -1 roll send /Y exch def pause pause } forall end pause } def /NextStackPos { % - => x y MyStack length 0 eq { NextPos } { MyStack dup length 1 sub get items exch get /NextPos exch send } ifelse } store /ClientExit { CurrentEvent /KeyState get { dup PointButton eq { { ItemBegin /StackI Index store /ThisI Index store ItemCanvas setcanvas location TabY add TabHeight 2 div add exch PinX add exch ItemParent createoverlay setcanvas { 2 setlinewidth exch pop x0 exch lineto } getanimated waitprocess aload pop % x y exch pop location exch pop sub dup 0 gt {ItemHeight sub 0 max} if /PinHeight exch store /paint-hilite win send ItemEnd } fork pop exit } if } forall StopItem } def /paint-struct { gsave ensure-DL /paint Scroller send /paint Notifier send dialog-can setcanvas /fixdamage dialog-text send grestore } def /DrawHilite { gsave can setcanvas location CanvasYFudge add translate ItemRadius object-bbox 4 -1 roll DropShadow add 4 -1 roll DropShadow sub 4 2 roll rrectpath .5 setgray fill -3 ItemRadius label-bbox insetrrect rrectpath 2 setlinewidth 0 setgray stroke PinHeight 0 ne { 1 setlinecap 2 setlinewidth 0 setgray PinX 0 dup PinHeight add min 6 sub moveto 0 ItemHeight PinHeight abs add 12 add rlineto stroke 1 setlinecap 6 setlinewidth 0 setgray PinX 0 dup PinHeight add min moveto 0 ItemHeight PinHeight abs add rlineto gsave stroke grestore 2 setlinewidth 1 setgray stroke } if grestore } store /reshape { /reshape super send gsave ensure-DL ItemCanvas setcanvas ObjectX ScrollerWidth add SubItemGap add ObjectY translate 0 0 ObjectWidth ScrollerWidth sub SubItemGap sub ObjectHeight NotifierHeight sub SubItemGap sub rectpath dialog-can reshapecanvas dialog-can /Mapped true put /reshape dialog-text send ItemCanvas setcanvas { [ 1 0 1 TextHeight div dup CanHeight floor 1 sub mul null ] } dialog-text send /setrange Scroller send ObjectX ObjectY ScrollerWidth ObjectHeight NotifierHeight sub SubItemGap sub /reshape Scroller send /paint Scroller send ObjectX ObjectY ObjectHeight add NotifierHeight sub ObjectWidth NotifierHeight /reshape Notifier send /paint Notifier send /SubItemMgr dictbegin /Scroller Scroller def /Notifier Notifier def dictend forkitems store grestore } def /ensure-DL { /ObjectWidth TextWidth def %XXX /ObjectHeight TextHeight def %XXX dialog-text null eq { /dialog-can ItemCanvas newcanvas store /dialog-text 200 dialog-can /new TextCanvas send store { /KeyDict 200 dict def KeyDict begin 127 { (erase character) comment % Rubout dialog-string length 0 ne { getcaretpos exch dup 1 gt { 1 sub exch movecaret getcaretpos 1 3 1 roll deletestring /dialog-string dialog-string dup length 1 sub 0 max 0 exch getinterval store } if } if } def 8 127 load def % Backspace 23 { (erase word) comment % ^W dialog-string length 0 ne { { getcaretpos exch dup 1 gt { 1 sub exch movecaret getcaretpos 1 3 1 roll deletestring /dialog-string dialog-string dup length 1 sub 0 max 0 exch getinterval store dialog-string length 0 eq { exit } if dialog-string dup length 1 sub 1 getinterval ( ) eq { exit } if } { exit } ifelse } loop } if } def 24 { (erase line) comment % ^X getcaretpos exch dialog-string length sub 1 max exch 2 copy movecaret dialog-string length 3 1 roll deletestring /dialog-string () store } def 21 24 load def % ^U 13 { (exec line) comment % Return [ () () ] true writeatcaret dialog-string /dialog-enter dialog-item send /dialog-string () store } def 10 { (select line) comment % Newline [ () () ] true writeatcaret dialog-string select-object /dialog-string () store prompt } def 10 128 add { (input line) comment % Meta-Newline [ () () ] true writeatcaret dialog-string /dialog-newline dialog-item send /dialog-string () store prompt } def 19 { (insert selection) comment % ^S selected-object (%) sprintf [ 1 index ] true writeatcaret /dialog-string exch dialog-string exch append store } def 11 { (stack to selection) comment % ^K { (%% Stack to selection\n) print select-object } /execute-it dialog-item send } def 25 { (selection to stack) comment % ^Y { (%% Selection to stack\n) print selected-object } /execute-it dialog-item send } def 3 { (reset input) comment % ^C /kbd-reset dialog-item send } def 4 { (reboot process) comment % ^D /kbd-reboot dialog-item send } def /FunctionR9 { (page up) comment /ScrollPageForward /FakeScroll dialog-scroll send } def /FunctionR15 { (page down) comment /ScrollPageBackward /FakeScroll dialog-scroll send } def /FunctionR7 { (scroll down) comment /ScrollLineForward /FakeScroll dialog-scroll send } def /FunctionR13 { (scroll up) comment /ScrollLineBackward /FakeScroll dialog-scroll send } def /FunctionR11 { (scroll to bottom) comment 1 /ScrollTo dialog-scroll send } def /FunctionF10 { (help) comment % Alternate [ () (Key Bindings:) ()] true writeatcaret [ KeyDict { comment-string exch key-name (%: %) sprintf } forall ] /gt quicksort [()] append true writeatcaret prompt } def /FunctionR1 { (describe key) comment [ () (Describe key: ) ] true writeatcaret /DescribingKey? true store } def /FunctionR2 { (bind selection to key) comment [ () selected-object (Bind % to key: ) sprintf ] true writeatcaret /BindingKey? true store } def end % KeyDict /typein { [1 index] true writeatcaret /dialog-string exch dialog-string exch append store } def /DescribingKey? false def /BindingKey? false def /key 0 def /KeyHitCallback { % event => dup update-shifts /Name get dup type /integertype eq { Meta {128 add} if } { Meta { (Meta%) sprintf } if Shift { (Shift%) sprintf } if Control { (Control%) sprintf } if cvn } ifelse /key exch def BindingKey? DescribingKey? or { BindingKey? { selected-object KeyDict key known { KeyDict key get } { null } ifelse select-object dup null eq { pop KeyDict key undef } { KeyDict exch key exch put } ifelse } if [ () KeyDict key known { KeyDict key get comment-string } { key type /integertype eq (self insert) (unbound) ifelse } ifelse key key-name (%: %) sprintf () ] true writeatcaret /BindingKey? false store /DescribingKey? false store prompt } { KeyDict key known { { KeyDict key get cvx exec } fork pop pause } { key type /integertype eq { key cvis typein } { % beep } ifelse } ifelse } ifelse } def /s null def /newlines 0 def /i 0 def /a null def /pre null def /InsertValueCallback { % string => - dialog-string /dialog-enter dialog-item send /s exch store /newlines 0 store 0 1 s length 1 sub { /i exch store s i get 13 eq { s i 10 put } if s i get 10 eq { /newlines newlines 1 add store } if } for /a newlines 1 add array store 0 1 newlines 1 sub { /i exch store s (\n) search pop /pre exch store pop /s exch store a i pre put pre (\n) append /dialog-enter dialog-item send } for a newlines s put /dialog-string s store a true writeatcaret } def /KeyboardHandler { % - => - % --- Handler for keyboard, InsertValue, and Deselect events /KeyboardInterest [ % Can addkbdinterests aload pop % Can addselectioninterests aload pop % % Get rid of LiteUI's mouse interests % revokeinterest % Can addfunctionnamesinterest % dup /Action /DownTransition put can addkbdinterests aload pop % XXX can=ClientCanvas can addselectioninterests aload pop % Get rid of LiteUI's mouse interests revokeinterest can addfunctionnamesinterest dup /Action /DownTransition put ] def /dialog-proc currentprocess store { awaitevent dup /Name get { /DeSelect { dup /Action get /PrimarySelection eq { false DrawSelection /SelectionPath null store } if /Action get /InputFocus eq { InactivateCaret } if } /RestoreFocus { pop ReactivateCaret } /InsertValue { /Action get InsertValueCallback } /Ignore { pop } /Default { KeyHitCallback } if } case } loop } def /destroy { % - => - KeyboardInterest null ne { KeyboardInterest can revokekbdinterests % XXX can=ClientCanvas } if KeyboardEventMgr null ne { % added! -deh KeyboardEventMgr killprocess } if EventMgr null ne { EventMgr killprocess } if DelayedMoveProc null ne { % added! -deh DelayedMoveProc killprocess } if MouseDragEventMgr null ne { MouseDragEventMgr killprocess } if } def /CaretBlinkTime 3 def /CaretDutyCycle 0.95 def % Percentage on % This doesn't work: /FontHeight 12 def /FontName FontName def [ () (%% Ready!) () ] true writeatcaret oncaret } dialog-text send /Scroller [1 0 .005 .05 null] 1 {} ItemCanvas /new NeWSScrollbar send def /dialog-scroll Scroller store { /NotifyUser { null ItemValue /moveviewport dialog-text send } def /ClientDrag { DoScroll null ItemValue /moveviewport dialog-text send } def /FakeScroll { % motion => - ItemBegin /ScrollMotion exch def DoScroll EraseBox PaintBox NotifyUser ItemEnd } def /ScrollTo { % val => - ItemBegin /ItemValue exch def EraseBox PaintBox NotifyUser ItemEnd } def } Scroller send /Notifier (Selection:) () /Right {} ItemCanvas /new MessageItem send def { /ItemFont /Screen-Bold findfont 13 scalefont def /ItemFrame 1 def } Notifier send } if psh-socket null eq { MyProcess null ne { MyProcess killprocess } if /MyProcess null store incoming null ne { incoming killprocess } if /incoming null store systemdict /_ViewCanvas ItemCanvas put /psh-socket { socket-file (r) file } errored { { newprocessgroup framebuffer setcanvas 500 500 [(Could not establish connection)] popmsg pop } fork pause pause pop currentprocess killprocessgroup } if store /incoming { { { psh-socket 255 string readline false eq { [() (Lost it!) ()] true writeatcaret % 1 60 div sleep % /kbd-reboot dialog-item send /incoming null store currentprocess killprocess } if [ exch getcaretpos pop 1 ne { () exch } if () ] true writeatcaret psh-socket bytesavailable 0 eq { prompt } if } loop } dialog-text send } fork store psh-socket (systemdict/dbgstart known not{(NeWS/debug.ps)run}if dbgstart\n_InitProcess\n) writestring psh-socket flushfile } if } def /dialog-newline { % str => - psh-socket exch writestring psh-socket 10 write psh-socket flushfile } def /dialog-enter { % str => - /dialog-buf exch dialog-buf (%%\n) sprintf store { dialog-buf { token } errored { [(%% Syntax error!)] true /writeatcaret dialog-text send kbd-reset exit } { { exch /dialog-buf exch store [ exch ] cvx execute-it } { dialog-buf ( _FOO_) append token { % Ignore white space exch pop /_FOO_ eq { /dialog-buf () store } if } if exit } ifelse } ifelse } loop } def /destroy { shut-down SubItemMgr null ne { SubItemMgr killprocess /SubItemMgr null store } if dialog-text null ne { % {{destroy} errored pop} dialog-text send /destroy dialog-text send /dialog-text null store } if } def classend def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Icky system globals and merciless kludges /comment { pop } def % Reap dead debuggers /rd { [ DbgDicts {pop} forall ] { dup /State get /zombie eq { DbgDicts 1 index undef killprocess } { pop } ifelse } forall } def systemdict /DbgDicts known { rd } if /dirname { ob begin uniquecid dup 3 -1 roll (dir2dict % % | psh) sprintf forkunix [exch cidinterest1only] forkeventmgr waitprocess replace-struct end redo-layout } store /filename { (file2dict % | psh) sprintf forkunix } def /_ViewCanvas null def /_InitProcess { createevent begin /Canvas _ViewCanvas def /Name /ProcessReady def /Action currentprocess def count array astore aload /ClientData exch def currentdict end sendevent createevent begin /Name /ExecIt def currentdict end expressinterest { awaitevent dup /ClientData get exch /Action get exec {currentfile flushfile} errored {exit} if } loop quit } def /revokekbdinterests { % [ int1 int2 ... intn ] can => - removefocusinterest % aload pop revokeinterest revokeinterest revokeinterest {revokeinterest} forall } store systemdict /old-setselection known not { /old-setselection /setselection load def /setselection { % dict rank 2 copy old-setselection createevent begin /Name /SelectionChanged def /Action exch def /ClientData exch def currentdict end sendevent } def } if /select-object { % obj => - 20 dict begin /ContentsPostScript 1 index def /ContentsAscii exch (%) sprintf def /SelectionObjSize 1 def /SelectionResponder null def /Canvas currentcanvas def % XXX? /SelectionHolder currentprocess def % XXX? currentdict end /PrimarySelection setselection } def /dissect-selection { % seldict => obj dup null ne { dup /ContentsPostScript known { dup /ContentsPostScript get % seldict obj 1 index /SelectionStartIndex known { 1 index /SelectionLastIndex known { exch dup /SelectionStartIndex get % obj seldict start exch /SelectionLastIndex get % obj start last 1 index sub % obj start len getinterval % subobj } { exch /SelectionStartIndex get get % subobj } ifelse } { exch pop } ifelse % obj } { dup /ContentsAscii known { /ContentsAscii get } if } ifelse } if } def /selected-object { % - => obj /PrimarySelection getselection dissect-selection } def % NeWS-print 0.996 % Written by Josh Siegel % Munged by Don Hopkins /Externals 512 dict def /ExternalsBack 512 dict def Externals /Count 0 put /string-magic dictbegin (\b) 0 get (\\b) def (\f) 0 get (\\f) def (\n) 0 get (\\n) def (\r) 0 get (\\r) def (\t) 0 get (\\t) def (\() 0 get (\\\() def (\)) 0 get (\\\)) def (\\) 0 get (\\\\) def dictend def /fixstring { 10 dict begin /len 0 def /out 1 index length 3 mul string def { dup string-magic exch known { string-magic exch get } { cvis } ifelse out len 2 index putinterval /len exch length len add def } forall out 0 len getinterval dup length string copy end } def /stringer { % proc => string dup type cvlit { /arraytype { pause /arraylvl arraylvl 1 add store dup xcheck { /the_string the_string ( {\n) append store { stringer } forall /the_string the_string ( }\n) append store } { /the_string the_string ( [\n) append store { stringer } forall /the_string the_string ( ]\n) append store } ifelse /arraylvl arraylvl 1 sub store } /nametype { dup xcheck { the_string arraylvl 0 eq (% /% cvx ) (% %) ifelse sprintf /the_string exch store } { the_string (% /%) sprintf /the_string exch store } ifelse } /operatortype { 255 string cvs dup length 2 sub 1 exch getinterval the_string arraylvl 0 eq (% /% cvx ) (% %) ifelse sprintf /the_string exch store } /stringtype { fixstring the_string (% \(%\)) sprintf /the_string exch store } /marktype { (mark ) % [ DANGER! ] } /booleantype /integertype /realtype /nulltype { the_string (% %) sprintf /the_string exch store } /Default { dup type /dicttype ne dictlvl 0 ne or arraylvl 0 ne or { ExternalsBack 1 index known { ExternalsBack exch get % name } { Externals begin Count /Count Count 1 add def end % obj count 1 index type (&%_%) sprintf % obj name Externals 1 index 3 index put % obj name ExternalsBack 3 -1 roll 2 index put % name } ifelse the_string ( //) append exch append /the_string exch store } { /dictlvl dictlvl 1 add store /the_string the_string ( dictbegin\n) append store { pause /the_string the_string (\t) append store exch stringer stringer /the_string the_string ( def\n) append store } forall /the_string the_string ( dictend \n) append store /dictlvl dictlvl 1 sub store } ifelse } def } case } def /tokout { % obj => string 10 dict begin /cnt Externals /Count get def /dictlvl 0 def /arraylvl 0 def /the_string () def stringer the_string cnt Externals /Count get ne { (Externals begin\n%\nend\n) sprintf } def end } def end % systemdict %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Nasty userdict variables /dialog-text null def /dialog-can null def /dialog-proc null def /dialog-string () def /dialog-buf () def /dialog-item null def /dialog-scroll null def (NEWSSERVER) getenv (;) search pop (.) search pop pop pop /socket-port exch def pop /socket-host exch def /socket-file (%socketc) socket-port append socket-host append def /psh-socket null def /SP 0 def /Stack 256 array def /Pallets 100 dict def Stack 0 Pallets put Stack 1 (Nothing!) put /ThisI null def /it null def /ob null def /obs null def /FillColor 1 1 1 rgbcolor def /ItemLock createmonitor def /items [] def /free-items [] def /Meta false def /Control false def /Shift false def /win null def /can null def /slidemgr null def /itemmgr null def /incoming null def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % User Utilities % % quicksort by Don Woods at Sun Microsystems, Inc. % /quicksort { % array proc => array (sorted, reuses same storage) 10 dict begin /Bigger? exch cvx def % a b bigger? => t if a -- sorts array in place, using Bigger? for comparisons dup length dup 2 gt { % A N % the next lines (until but not incl /Key...) subsort three elements % so we can use the median as the partitioning element; this improves % performance for the case where the array is initially nearly sorted, % but is not strictly necessary for the algorithm to work (it does % seem to improve average runtime by about 10%) 2 copy 1 sub 2 copy 2 idiv 1 index 0 % A N A N-1 A (N-1)/2 A 0 6 copy get 5 1 roll get 3 1 roll get % above & A[N-1] A[(N-1)/2] A[0] 2 copy Bigger? {exch} if % subsort for three elements 3 1 roll 2 copy Bigger? {exch} if % ... (call them min mid max) 3 -1 roll 2 copy Bigger? {exch} if % ... subsort finished 9 index % A N A N-1 A (N-1)/2 A 0 min mid max N 3 eq { 5 2 roll put 4 1 roll put put % store min/mid/max back pop pop % pop A & N } { % else store mid at 0, max at N-1, min at (N-1)/2, then partition 3 -1 roll 5 2 roll put exch 4 1 roll put put % A N /Key 2 index 0 get def % partitioning value 0 % A N 0, also known as A j i { % main partitioning loop % incr i until i=j or A[i]>=A[0]; note A[j] is rangecheck { 1 add 2 copy gt { % i++; A j i j>i? dup 3 index exch get % A j i A[i] Key exch Bigger? not {exit} if } {exit} ifelse } loop % decr j until A[j]<=A[0]; happens at j=i-1 if not sooner exch { % A i j 1 sub dup 3 index exch get % A i j A[j] Key Bigger? not {exit} if } loop 2 copy gt {exit} if % if i>=j, finished partition % swap A[j] & A[i]; stack has: A i j 2 index 4 copy exch get % A i j A A i A[j] 4 1 roll get % A i j A[j] A A[i] 3 index exch put % A i j A[j] 4 copy exch pop put pop exch % A j i } loop % finish partition by exchanging A[j] with A[0]; stack has: A i j exch pop 2 copy 4 copy get % A j A j A j A[j] exch pop 0 exch put Key put % A j % now recur on A[0..j-1] and A[j+1..N-1] 2 copy 1 add 1 index length 1 index sub % A j A j+1 N-1 getinterval 3 1 roll 0 exch getinterval % A[j+1..N-1] A[0..j-1] 2 copy length exch length gt {exch} if % put smaller on top quickrecur quickrecur % tail recursion avoids deep stack } ifelse % =3 or >3 elements } { % handle 1- and 2-element cases specially for efficiency 2 eq { dup aload pop Bigger? {aload 3 1 roll exch 3 -1 roll astore} if } if pop % pop the array } ifelse } def % quickrecur % end of quicksort /shift-names 10 dict def shift-names begin /Meta false def /Shift false def /Control false def end % shift-names /update-shifts { shift-names {store} forall /KeyState get { shift-names 1 index known { true store } { pop } ifelse } forall } store /key-names 40 dict def key-names begin 8 (Backspace) def 9 (Tab) def 10 (Newline) def 13 (Return) def 27 (Escape) def 127 (Delete) def end % key-names /key-name { % key => string dup type /integertype eq { dup 127 and key-names 1 index known { key-names exch get } { dup 32 lt { 64 add cvis (^%) sprintf } { cvis } ifelse } ifelse exch 128 ge { (Meta-%) sprintf } if } { (%) sprintf } ifelse } store /comment-string { % obj => string dup type /arraytype eq { dup length 2 ge { dup 1 get /comment eq { 0 get } if } if } if (%) sprintf } def /destroy { % dummy destroy method } def % Forward messages on to stack /prompt { {} execute-it } def /execute-it { /execute-it dialog-item send } def /exec-it { /exec-it dialog-item send } def /push-it { /push-it dialog-item send } def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Pallets of useful functions Pallets begin /Debug dictbegin /dlb /dbglistbreaks cvx def /de /dbgenter cvx def /dx /dbgexit cvx def /dk /dbgkill cvx def /dc /dbgcontinue cvx def /dcc {dbgcopystack dbgcontinue} def /dw /dbgwhere cvx def /execstack {DbgImplicitBreak DbgGetExecStack} def /exec /exec cvx def /stack /stack cvx def /clear /clear cvx def /typo { % undefined (select correct spelling) => - userdict begin dup cvlit [ get-selection (%) sprintf cvn cvx ] cvx def end exec } def dictend def /Number dictbegin 0 {10 mul} def 1 {10 mul 1 add} def 2 {10 mul 2 add} def 3 {10 mul 3 add} def 4 {10 mul 4 add} def 5 {10 mul 5 add} def 6 {10 mul 6 add} def 7 {10 mul 7 add} def 8 {10 mul 8 add} def 9 {10 mul 9 add} def /Back {10 div floor} def /Reset {0 mul} def /Enter {0} def dictend def currentautobind false setautobind /Math { {add sub mul div idiv mod} {neg abs min max} {ceiling floor round truncate} {cos sin tan arcsin arccos arctan atan exp ln log sqrt} {random rand} { % Sort this stuff out: append astore copy getinterval putinterval arrayinsert arraydelete pickarray arrayop modifyproc LoadFile run and or xor not bitshift begin end currentdict forall for loop repeat case exit if ifelse stopped stop errored userdict systemdict cleartomark count counttomark index roll pop dup exch exec cvas cvad cvi cvis cvlit cvn cvr cvrs cvs cvx litstring array dict string dictbegin dictend length maxlength extend fork killprocess waitprocess currentprocess newprocessgroup killprocessgroup forkunix getenv putenv type xcheck nullproc nullarray nullstring nulldict eq ne gt lt ge le true false null printf print = == sprintf stack pstack po file readstring writestring read write readline flushfile token closefile readhexstring writehexstring bytesavailable fprintf currentfile status flush writeobject readcanvas writecanvas eowritecanvas writescreen eowritescreen movecanvas getcanvaslocation reshapecanvas eoreshapecanvas erasepage fillcanvas get put def store load undef known where send self super classbegin classend setautobind currentautobind pause sleep bind newpath closepath moveto lineto currentpath eocurrentpath setpath rlineto rmoveto currentpoint emptypath pointinpath extenddamage eoextenddamage dashpath strokepath flattenpath pathbbox pathforall pathforallvec stroke fill matrix concat concatmatrix currentmatrix setmatrix initmatrix defaultmatrix identmatrix rotate translate scale currentcursorlocation setcursorlocation getcanvascursor setcanvascursor setstandardcursor getcanvasshape setcanvasshape setgray setcolor currentcolor contrastwithcurrent currentgray setshade rgbcolor setrgbcolor currentrgbcolor hsbcolor sethsbcolor currenthsbcolor countdictstack countexecstack dictstack execstack awaitevent createevent CurrentEvent countinputqueue sendevent recallevent redistributeevent eventmgrinterest forkeventmgr forkitems getanimated getclick getfbclick getrect getwholerect expressinterest revokeinterest globalinterestlist createmonitor monitor monitorlocked currenttime lasteventtime localhostname vmstatus gsave grestore grestoreall initgraphics save restore dtransform transform itransform idtransform currentdash setdash currentflat setflat currentlinecap setlinecap currentlinejoin setlinejoin currentlinequality setlinequality currentlinewidth setlinewidth currentmiterlimit setmiterlimit currentprintermatch setprintermatch currentrasteropcode setrasteropcode currentstate setstate currentfont setfont findfont scalefont definefont findfilefont makefont fontascent fontdescent fontheight arc arcn arcto curveto rcurveto controlpoint rcontrolpoint ashow widthshow awidthshow cshow rshow show kshow showcursor showicon stringbbox stringwidth clip eoclip clipcanvas eoclipcanvas clipcanvaspath clippath eoclippath initclip framebuffer copyarea eocopyarea setcanvas currentcanvas buildimage newcanvas createcanvas createoverlay image imagecanvas imagemask imagemaskcanvas canvasabove canvasbelow topchildcanvas parentcanvas canvastotop canvastobottom insertcanvasabove insertcanvasbelow search anchorsearch rect rrect rectpath rrectpath insertrect insetrrect ovalpath ovalframe rectframe rrectframe points2rect rect2points rectsoverlap popmsg } } cvlit def /Stack { dup pop exch clear load def store get put aload forall [ ] } cvlit def setautobind end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Item managment /createitems { ItemLock { /items [ Stack 0 {click-point} can /new StructItem send 20 10 0 0 /reshape 5 index send Stack 1 {} can /new TextStructItem send 20 50 0 0 /reshape 5 index send ] def /SP items length store /dialog-item items 1 get store {/PinHeight 600 def /StackI 1 def} dialog-item send /ThisI 1 store } monitor } def /slideitem { % items fillcolor item => - gsave dup 4 1 roll % item items fillcolor item {ItemCanvas canvastotop moveinteractive location move} exch send % item grestore } def /update-slide-interests { CurrentEvent /ClientData get % Index items exch get % item dup /ItemCanvas get % item can MiddleMouseButton [items FillColor % item can name [ dict color 6 -1 roll /slideitem cvx] cvx % can name proc DownTransition % can name proc action 4 -1 roll eventmgrinterest % interest expressinterest } def /update-start-interests { CurrentEvent /ClientData get % Index items exch get % item mark [/makestartinterests 3 index send aload pop] {dup xcheck {exec} {expressinterest} ifelse} forall cleartomark pop } def /start-event-mgrs { % Create event manager to slide around the items. % Create a bunch of interests to move the items. % Note we actually create toe call-back proc to have the arguments we need. % The proc looks like: {items color "thisitem" slideitem}. % We could also have used the interest's clientdata dict. slidemgr null ne {slidemgr killprocess} if /slidemgr [ items { % key item dup /ItemCanvas get % item can MiddleMouseButton [items FillColor % item can name [ dict color 6 -1 roll /slideitem cvx] cvx % can name proc DownTransition % can name proc action 4 -1 roll eventmgrinterest % interest } forall /UpdateInterests /update-slide-interests null can eventmgrinterest ] forkeventmgr store itemmgr null ne {itemmgr killprocess} if /itemmgr [ items iteminterests aload pop /UpdateInterests /update-start-interests null can eventmgrinterest ] forkeventmgr store } def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Window class definition /CyberWindow DefaultWindow dictbegin /FrameLabel (PostScript Structure CyberSpace) def /IconLabel (PS CyberSpace) def /IconImage /galaxy def dictend classbegin /PaintClient { paint-hilite items paintitems } def /paint-hilite { ClientCanvas setcanvas erasepage /DrawHilite dialog-item send } def /ClientMenu [ (Break Stack) { clear /BrokenStack /dbgbreak dialog-item send } (Credits) { /display-credits win send } (Break Window) { clear /BrokenWindow /dbgbreak win send } (KeyDict) { /KeyDict dialog-text send select-object } ] /new DefaultMenu send def /display-credits { gsave framebuffer setcanvas currentcursorlocation [ (NeWS CyberSpace:) ( by Don Hopkins) (----------------) (Code stolen from:) ( Josh Siegel) ( Don Woods) ] popmsg pop grestore } def /DestroyClient { itemmgr type /processtype eq { itemmgr killprocess } if slidemgr type /processtype eq { slidemgr killprocess } if items { /destroy exch send } forall /items null store /_ViewCanvas null store /PrimarySelection clearselection % XXX? /DestroyClient super send } def classend def %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Create objects /win framebuffer /new CyberWindow send store % Create a window 0 0 900 900 /reshape win send /can win /ClientCanvas get store % BOO HISS can /Transparent false put can /Retained true put createitems % /reshapefromuser win send /map win send start-event-mgrs