anchor.diff:    end;
   
   procedure TEdgeMenuI.LoadData;
  -  begin _edges := _node.ie; smudge;
  +  begin if assigned(_node) then _edges := _node.ie; smudge;
     end;
   
   procedure TEdgeMenuO.LoadData;
  -  begin _edges := _node.oe; smudge;
  -  end;
  -
  --
  +  begin if assigned(_node) then _edges := _node.oe; smudge;
  +  end;
   
   //  todo: simplify by just having per-column callbacks
  -function TEdgeMenuI.RenderCell(gx,gy:integer) : TStr;
  +function TEdgeMenuI.RenderCell(gx,gy:word) : TStr;
     begin result := boolstr(gx=0, _edges[gy].sub.s, _edges[gy].rel.s)
     end;
   
  -function TEdgeMenuO.RenderCell(gx,gy:integer) : TStr;
  +function TEdgeMenuO.RenderCell(gx,gy:word) : TStr;
     begin result := boolstr(gx=0, _edges[gy].rel.s, _edges[gy].obj.s)
     end;
  --
  -function prepstr(s : string; len : byte) : TStr;
  -  begin result := rfit(replace(replace(cstrip(s), ^M, ''), ^J, ''), len)
  -  end;
  -
  -procedure TEdgeMenu.Render;
  -  var gy : word; bar : byte; gh : word = 0;
  -  begin bg(0); fg('w'); clrscr;
  -    if _focused then bar := udv.hibar else bar := udv.lobar;
  -    if assigned( node ) then begin
  -      LoadData; gh := self.count;
  -      if gh = 0 then _igy := 0 else _igy := xpc.min(_igy, gh-1);
  -      if gh > 0 then for gy := 0 to gh-1 do begin
  -	gotoxy(0,gy); if gy = _igy then bg(bar) else bg(0);
  -	write(prepstr(RenderCell(0,gy), _cellw[0]));
  -	fg('k'); emit('│'); fg('w');
  -	write(prepstr(RenderCell(1,gy), _cellw[1]));
  -      end;
  -    end;
  -    if gh = 0 then begin
  -      bg(bar); clreol; fg('k');
  -      write(chntimes(' ', _cellw[0]), '|');
  -    end;
  -  end;
  -
  -procedure TEdgeMenu.RestoreCursor;
  -  var i : word; cx : word = 0;
  -  begin { show the cursor on the current cell }
  -    if _igx > 0 then for i:= 0 to _igx-1 do inc(cx, _cellw[i]);
  -    if assigned(node) and (count > 0) then begin
  -      gotoxy(_x+cx, _y+_igy); ShowCursor;
  -    end
  -  end;
  -
    
   type
  
positive.code: 
  type
    TEdgeMenu = class (utv.TView)
      protected _base : IBase; _node : INode; _igx, _igy : cardinal;
        _edges : TEdges; _cellw : TBytes; _gw, _gh : byte;
      public
        constructor Create( aOwner : TComponent ); override;
        procedure Render; override;
        procedure RestoreCursor; override;
        procedure LoadData; virtual; abstract;
        function RenderCell(gx,gy :integer) : TStr; virtual; abstract;
        function count : word;
      published
        procedure Handle(msg : umsg.TMsg); override;
        property base : IBase read _base write _base;
        property node : INode read _node write _node;
      end;
  
negative.code:     public
        constructor Create( aOwner : TComponent ); override;
        procedure LoadData; override;
        function RenderCell(gx,gy :word) : TStr; override;
      end;
    TEdgeMenuO = class (TEdgeMenu)
      public
        constructor Create( aOwner : TComponent ); override;
        procedure LoadData; override;
        function RenderCell(gx,gy :word) : TStr; override;
      end;
  
  constructor TEdgeMenu.Create( aOwner : TComponent );
    begin inherited;
      _gw := 2; _deleteAt := self.DeleteAt;
      _GetRowCount := EdgeCount;
      _RenderCell := RenderCell;
    end;
  
  function TEdgeMenu.EdgeCount : word;
    begin if assigned(node) then result := length(_edges) else result := 0
    end;
  
  procedure TEdgeMenu.DeleteAt(gx,gy : word );
    begin
      if assigned(_edges) then begin
        _edges[_igy].del; self.LoadData
      end else ok
    end;
  
  constructor TEdgeMenuI.Create( aOwner : TComponent );
  