[comp.windows.news] NeWS Molecules

don@BRILLIG.UMD.EDU (Don Hopkins) (03/11/89)

This is a new version of the Pseudo-Scientific Visualizer.  It
projects hallucinations of a NeWS molecules onto the screen.  (These
things don't really exist, so they're not prohibited by law.)  Once
it's done virtualizing the hallucination, there is a shudder, a puff
of smoke comes out of the back of the CPU, and then all the little
bits and pieces are made synesthetically mouse sensative!

Composite objects (arrays and dictionaries) highlight when you point
at them, and their printed name is show in the text item at the bottom
of the window. When you click the point (left) button on a highlighted
object, it is selected (in PrimarySelection). When you click the point
button on the background, it highlights *all* mouse sensative objects.
When you click with the adjust button on a highlighted object, it zoom
into that object.  Select the menu item "Thing... Top" to get back to
the original object.)  When you change something with the menu, it
takes effect immediatly while it's drawing. If you make changes after
it's finished painting, you should redraw (menu "paint") the window to
see them.

If there is an argument to psh, it executes it and grows a molecule
with the resulting object. Otherwise it just installs its class in
systemdict, for later use.

Use it like this:

psh molecule.ps rootmenu

psh molecule.ps '[ [1 2 3 4] [1 2 3] [1 2] [1] ]'

psh molecule.ps '10 dictbegin /foo LiteMenu def /bar LiteItem def dictend'

	-Don

%!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 
% The NeWS Pseudo-Scientific Visualizer
%   -- the class browser for the other half of your brain.
% Copyright (C) 1988 by Don Hopkins (don@brillig.umd.edu)
% 
% You are free to redistribute this program.  Please leave the comments
% intact, add your own views and hallucinations, and pass it on to
% friends!  The author is not responsible for any time or brain cells
% wasted with this software.  (Has anybody ever actually gotten sued for
% that?)
% 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% We've got to have the classes PieMenu and PulloutPieMenu are defined.
systemdict /PieMenu known not {
  (NeWS/piemenu.ps) LoadFile not {
    currentcursorlocation
    [(Need) (piemenu.ps)] popmsg pop
    currentprocess killprocess
  } if
} if

systemdict /PulloutPieMenu known not {
  (NeWS/pullout.ps) LoadFile not {
    currentcursorlocation
    [(Need) (pullout.ps)] popmsg pop
    currentprocess killprocess
  } if
} if

systemdict begin

/PSVisualizerWindow DefaultWindow
dictbegin
  /hfrob .3 def
  /sfrob .5 def
  /bfrob .3 def

  /procs 1 def
  /maxprocs 10 def
  /maxdrawdepth 0 def
  /maxtargetdepth 0 def

  /thing null def

  /highmark 10 def

  /pp null def

  /FrameLabel (The NeWS Pseudo-Scientific Visualizer!) def
  /IconLabel (PS Visualizer) def
  /IconImage /eye def

  /Canvases null def

  /Items null def

  /BorderBottom 32 def

  /Top null def
dictend
classbegin

  /new {
    /new super send begin
      /Top 1 index def
      /thing exch def
      /maxdrawdepth countdictstack 3 add def
      /maxtargetdepth countdictstack 999 add def
      currentdict
    end
  } def

  /destroy { % clean up
    drain
    pp type /processtype eq { 
      pp killprocessgroup
      /pp null def
      /thing null def
    } if
    Canvases null ne {
	Canvases {pop /Interests get
	dup length 0 eq {(zip ) [] dbgprintf} if % XXX
	{revokeinterest} forall} forall
    } if
    /destroy super send
  } def

  /drain {
      maxdrawdepth
      /maxdrawdepth 0 def
      50 { pause procs 0 eq {exit} if } repeat
      /maxdrawdepth exch def
  } def

  /PaintClient {
    gsave ClientCanvas setcanvas
     {
      clear
      newprocessgroup
      drain
      pp null ne {
	pp killprocessgroup % why doesn't this kill all of 'em???
      } if
      /pp currentprocess def
      Canvases dup type /dicttype eq {
	Canvases { pop
	  dup /Interests get
	  dup length 0 eq {(zip ) [] dbgprintf} if % XXX
	  {revokeinterest} forall
	  /Mapped false put
        } forall
      } if
      /Canvases 2048 dict def
      erasepage
      random random random sethsbcolor
      /highmark countdictstack def
      /procs 1 def
      clippath pathbbox scale pop pop
      .5 .5 translate .05 .05 scale
      {/thing load visualize} fork waitprocess pop
      300 { procs 1 le {exit} if .1 sleep } repeat
      ClientCanvas setcanvas
      [ Canvases { pop
	  [ PointButton AdjustButton MenuButton /EnterEvent /ExitEvent ]
	  /target-event null 4 -1 roll eventmgrinterest
        } forall
	PointButton /point-background null ClientCanvas eventmgrinterest
      ] forkeventmgr
      /pp exch def
    } fork pop
   grestore
  } def

  /PaintFrame {
    /PaintFrame super send
    Items paintitems
  } def

  /activate {
    /Items 10 dict dup begin
      /message_item () () /Right
        nullproc
        FrameCanvas /new MessageItem send
        BorderLeft 4 330 0 /reshape 5 index send def
      end def
      Items forkitems pop
      map
      ClientCanvas /Retained true put
  } def

  /reshape {
    /reshape super send
    Items null ne {
      BorderLeft 4 /move Items /message_item get send
    } if
  } def

  /toggle-can {
    setcanvas
    0 setgray  5 setrasteropcode
    clippath fill
  } def

  /point-background {
    gsave
      Canvases { pop toggle-can } forall
    grestore
  } def

  /target-event-names 10 dict def
  target-event-names begin
    PointButton {
      CurrentEvent /Action get /DownTransition eq {
	Canvases
	CurrentEvent /Canvas get get /obj get
	select-object
      } {
      } ifelse
    } def
    AdjustButton {
      CurrentEvent /Action get /DownTransition eq {
	Canvases
	CurrentEvent /Canvas get get /obj get
	/thing exch store
	PaintClient
      } {
      } ifelse
    } def
    MenuButton {
      CurrentEvent /Action get /UpTransition eq {
      } {
      } ifelse
    } def
    /EnterEvent {
      Canvases 
      CurrentEvent /Canvas get
      dup toggle-can
      get /obj get (%) sprintf /printstring Items /message_item get send
    } def
    /ExitEvent {
      CurrentEvent /Canvas get toggle-can
    } def
  end

  /target-event {
    gsave
      target-event-names CurrentEvent /Name get get exec
    grestore
  } def

  /ignorekeys 20 dict def
  ignorekeys begin
    /TopCanvas dup def
    /BottomCanvas dup def
    /CanvasAbove dup def
    /Parent dup def
    /FrameMenu dup def
    /IconMenu dup def
    /ParentDict dup def
    /ParentDictArray dup def
  end

  /cvfixed {
    16384 mul floor cvi -14 bitshift
  } def

  /wrap {
    dup floor sub cvfixed
  } def

  % This is useful for finding core leaks ... (Really!)
  /context-string { % => (string)
    ()
    currentprocess /DictionaryStack get 
    dup length 2 sub 2 exch getinterval
    { dup /obj known {
	begin i obj 3 -1 roll (%/%:%) sprintf end
      } {pop} ifelse
    } forall
    1 index exch (%	=	%) sprintf
  } def

  /make-target {
    countdictstack maxtargetdepth lt {
      /can ClientCanvas newcanvas def
      0 0 1 0 360 arc can reshapecanvas
      can /Transparent true put
      can /Mapped true put
      Canvases can currentdict put
    } if
  } def

  /visualize { % obj => -
%     count 5 gt {/foo dbgbreak} if
    pause
    countdictstack maxdrawdepth ge {
       countdictstack highmark gt {
% Uncomment this to hunt for core leaks. 
% 	context-string (High water: %\n) [3 -1 roll] dbgprintf
	 /highmark countdictstack store
       } if
       pop
    } { 
     { gsave
      currenthsbcolor
      3 -1 roll random hfrob mul add wrap
      3 -1 roll random sfrob mul add wrap
      sqrt % Crank up the saturation!
      3 -1 roll random bfrob mul add wrap
      sqrt % Crank up the brightness!

      sethsbcolor
      dup type {
  %      /canvastype
	/dicttype {
	  newpath
	  0 0 1 0 360 arc closepath
	  0 0 .9 0 360 arc closepath
	  0 0 .2 0 360 arc closepath
	  eofill
	  10 dict begin
	      make-target
	      /obj exch cvlit def
	      /pieces obj length def
	      pieces 0 ne {
		/step 360 pieces div def
		obj {
		  pause
		  countdictstack maxdrawdepth ge {pop pop exit} if
		  /thing exch cvlit def
		  /i exch cvlit def
		  gsave
		    2.5 0 translate
		    .6 .6 scale
		    i visualize
		    2.5 0 translate
		    ignorekeys i known not { thing } { /triangle } ifelse
		    visualize
		  grestore
		  step rotate
		} forall
	      } if
	  end
	} 
	/arraytype {
	  newpath
	  0 0 1 0 360 arc closepath
	  0 0 .9 0 360 arc closepath
	  eofill
	  10 dict begin
	      make-target
	      /obj exch cvlit def
	      /pieces obj length def
	      pieces 0 ne {
		/step 360 pieces div def
		/i -1 def
		obj {
		  pause
		  countdictstack maxdrawdepth ge {pop exit} if
		  /thing exch cvlit def
		  /i i 1 add def
		  gsave
		    2.5 0 translate
		    .6 .6 scale
		    thing visualize
		  grestore
		  step rotate
		} forall
	      } if
	  end
	}
	/stringtype {
	  length 1 add
	  newpath
	  -.5 -.1 % x y
	  3 -1 roll 5 div .5 add .2 % x y w h
	  rectpath
	  fill
	} 
	/realtype /integertype {
	  dup 100 div wrap  1 index 10 div wrap  3 -1 roll wrap
	  setrgbcolor
	  -.4 -.4 .8 .8 rectpath
	  fill
	}
	/eventtype {
	  pop
	  -.8 -.8 1.6 1.6 rectpath
	  -.8 .8 moveto
	  0 0 lineto
	  -.8 -.8 lineto
	  stroke
	}
	/nulltype {
	  pop
	  gsave
	    -90 rotate
	    -1 -.3 translate
	    2 2 scale
	    newpath % Nick Turner's finger
	    .2 0 moveto
	    0 .3 lineto
	    .1 .5 lineto
	    .2 .5 lineto
	    .2 .55 lineto
	    .3 .6 lineto
	    .4 .55 lineto
	    .4 .95 lineto
	    .5 1 lineto
	    .6 .95 lineto
	    .6 .55 lineto
	    .7 .6 lineto
	    .8 .55 lineto
	    .8 .5 lineto
	    .9 .55 lineto
	    1 .5 lineto
	    1 .3 lineto
	    .8 0 lineto
	    closepath
	    fill
	  grestore
	}
	/operatortype {
	  pop
	  -.2 -.2 .4 .4 rectpath
	  0 0 .5 0 360 arc
	  eofill
	}
	/processtype {
	  pop
	  newpath
	  -.5 -.5 moveto
	  1 -.4 lineto
	  1 -.2 lineto
	  .8 -.2 lineto
	  1 .4 lineto
	  1 1 lineto
	  .5 .3 lineto
	  -.5 .5 lineto
	  closepath
	  eofill
	}
% 	/canvastype {
% 	  -.5 -.5 translate
% 	  imagecanvas
% 	}
	/Default {
	  pop
	  newpath
  % 	-.5 -.5 1 1 rectpath
	  0 -.5 moveto
	  1 0 lineto
	  0 .5 lineto
	  closepath
  %         stroke
  % 	-.4 -.4 .8 .8 rectpath
	   eofill
	}
      } case
     grestore } % A verb, Senator Kennedy, we need a verb!
     random .6 lt  procs maxprocs lt and {
       /procs procs 1 add store
       { exec
	 /procs procs 1 sub store
       } fork pop pop pop
     } {
       exec 
     } ifelse % mumble frotz ...
    } ifelse
  } def

% Menu definitions

  /ColorFrobMenu [
    [(0.0) (0.02) (0.05)
     (0.1) (0.2) (0.3) (0.4) (0.5) (0.6) (0.7) (0.8) (0.9) (1.0) (99)]
  ] [
    (HueFrob) { ThisWindow /hfrob getmenuarg cvr put }
    (BrightnessFrob) { ThisWindow /bfrob getmenuarg cvr put }
    (SaturationFrob) { ThisWindow /sfrob getmenuarg cvr put }
  ] /new PulloutPieMenu send def

  /ThingMenu [
    (SendContexts) {
      ThisWindow /thing currentprocess /SendContexts get put }
    (UI_private) {
      ThisWindow /thing UI_private put }
    (Top) {
      {/thing /Top load def } ThisWindow send }
    (rootmenu) {
      ThisWindow /thing rootmenu put }
    (DefaultMenu) {
      ThisWindow /thing DefaultMenu put }
    (userdict) {
      ThisWindow /thing userdict put }
    (bar) {
      ThisWindow /thing /bar load put }
    (Item) {
      ThisWindow /thing Item put }
  ] /new PieMenu send def

  /ClientMenu [
    []
    [(1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (9999)]
    [(1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (9999)]
    []
    [(1) (2) (3) (4) (5) (6) (7) (8) (9) (10)
     (11) (12) (13) (14) (15) (16) (17) (18) (19) (20)]
    []
  ] [
    (Thing...) ThingMenu
    (DrawDepth) { 
      getmenuarg cvi 
      { countdictstack add /maxdrawdepth exch def } ThisWindow send }
    (TargetDepth) { 
      getmenuarg cvi 
      { countdictstack add /maxtargetdepth exch def } ThisWindow send }
    (ColorFrob...) ColorFrobMenu
    (MaxProcs) { ThisWindow /maxprocs getmenuarg cvi put }
    (paint) { /paint ThisWindow send }
  ] /new PulloutPieMenu send def

  % Hurray for you -- you're reading the source code!
  % You can run a psh, and change foo and bar in systemdict to whatever
  % you want to look at! (warning: systemdict gets "unregistered" errors!)
  % To find core leaks, visualize objects in your application's userdict, 
  % and look for the infinite regression of circular references.
  systemdict /foo ClientMenu put
  systemdict /bar UserProfile put

classend def

/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

/start_visualizer { % thing =>
  { framebuffer setcanvas
    newprocessgroup
    framebuffer /new PSVisualizerWindow send
    /reshapefromuser 1 index send
    /activate exch send
  } fork pop pop
} def

end % systemdict

% visualize command line args, if any.
{ clear
  { ($1 $2 $3 $4 $5 $6 $7 $8 $9) cvx exec } errored not {
    count 0 ne {
      start_visualizer
    } if
  } if
} fork pop