#!/usr/NeWS/bin/psh 

% unmap version 1.1
%
% Written by Josh Siegel (Wed Jun 29 1988)
% last modified Tue Oct  4 01:10:38 MDT 1988

% This programs purpose is to unmap windows.  All you do
% is click on a canvas and it will vanish.  Useful for those
% windows that have failed to garbage collect.
%

% getxyloc returns the position of the next left-button
% mouse up event.  It passes all other events.

/getxyloc { %  => x y
    10 dict 
    begin
        createevent
        dup /Priority 20 put
        dup /Name /LeftMouseButton put
        dup /Action /UpTransition put
        /foobar exch def
        foobar expressinterest
        {
            awaitevent
            dup /Name get /LeftMouseButton eq { 
                exit 
            } if
            redistributeevent
        } loop
        foobar revokeinterest
        dup /XLocation get
        exch /YLocation get
    end
} def

% find_tree traverses the canvas tree passed to it and calls
% check_canvas to check to see if the point is in the
% canvas.   It is also a example of a recursive NeWS routine.

/find_tree { % canvas =>
    dup null eq {
        pop 
    } {
        dup check_canvas 
        {
            dup [ exch ] answer exch append /answer exch def
        } if
        dup /TopChild get find_tree
        {
            /CanvasBelow get
            dup null eq { 
                pop exit 
            } if
            dup check_canvas 
            {
                dup [ exch ] answer exch append /answer exch def
            } if
        } loop
    } ifelse
} def

% Check canvas checks to see if the point is inside of the
% clipping path of the canvas.  This is VERY important for things
% like the clock where the clipping path is round.
%

/check_canvas { % canvas => boolean
    dup /Mapped get {
        dup getcanvaslocation % can xwin ywin
        ypnt exch sub % can xwin ypnt-ywin
        exch xpnt exch sub exch % can xpnt-xwin ypnt-ywin
        3 -1 roll setcanvas clipcanvaspath pointinpath % boolean
        framebuffer setcanvas
    } {
        pop false
    } ifelse
} def

% find_canvas is a convient front end to the whole system.
% I use a local dictionary to help in garbage collected in case
% this routine is later used as part of a larger piece of code.

/find_canvas { % x y => [canvas]
    10 dict 
    begin
        /answer [ ] def
        /ypnt exch def
        /xpnt exch def
        framebuffer find_tree
        answer
    end
} def

getxyloc find_canvas dup 
length 1 le % Do we only have the framebuffer in the list?
{ 
    pop 
} % if so, just clear the stack and finish.
{ 
    1 get /Mapped false put 
} ifelse % unmap the canvas.
