anchor.diff:      ets:insert(TableId, list_to_tuple([Id,O,element(2,OldRow)|Fields])),
       State1.
   
  -int_min(A,B) when A=<B -> A;
  -int_min(_,B) -> B.
  -
  -int_max(A,B) when A>=B -> A;
  -int_max(_,B) -> B.
  -
  -serve_stack(_SN, #state{stack=undefined}=State) -> State;
  -serve_stack(SN, #state{stack={Tab,button,'>',RT}}=State0) ->
  -    State1 = serve_fwd(Tab,SN,State0#state{replyTo=RT}),
  -    State1#state{stack=undefined};
  -serve_stack(SN, #state{bufBot=BufBot,stack={Tab,button,Target,RT}}=State0) when is_integer(Target), (BufBot>=Target) ->
  -    State1 = serve_target(Tab,SN,Target,State0#state{replyTo=RT}),
  -    State1#state{stack=undefined};
  -serve_stack(completed, #state{stack={Tab,button,_,RT}}=State0) ->
  -    State1 = serve_last(Tab,complete,State0#state{replyTo=RT}),
  -    State1#state{stack=undefined};
  -serve_stack(tailing, #state{stack={Tab,button,'>|',RT}}=State0) ->
  -    State1 = serve_last(Tab,tailing,State0#state{replyTo=RT}),
  -    State1#state{stack=undefined};
  -serve_stack(tailing, #state{bl=BL,bufBot=BufBot,rawBot=RawBot,stack={Tab,button,'>|...',RT}}=State0) ->
  -    if
  -        (BufBot == RawBot) ->
  -            State0#state{stack={Tab,button,'>|...',RT}}; 
  -        (RawBot >= BufBot-BL) ->
  -            gui_append(Tab, RawBot+1, BufBot, #gres{state=tailing,loop='>|...'},State0#state{stack=undefined}); 
  -        (BufBot >= BL) ->
  -            gui_replace(Tab, BufBot-BL+1, BufBot, #gres{state=tailing,loop='>|...'},State0#state{stack=undefined});
  -        true ->
  -            gui_replace(Tab, 1, BufBot, #gres{state=tailing,loop='>|...'},State0#state{stack=undefined})
  -    end;
  -serve_stack(_ , State) -> State.
  -
  -serve_empty(Tab,SN,true,State0) ->
  -    State1 = prefetch(SN,State0),          %% only when filling
  -    gui_nop(Tab,#gres{state=SN,beep=true},State1);
  -serve_empty(Tab,SN,false,State0) ->
  -    State1 = prefetch(SN,State0),          %% only when filling
  -    gui_nop(Tab,#gres{state=SN},State1).
  -
  -serve_fwd(Tab,SN,#state{bl=BL,bufBot=BufBot,rawBot=RawBot}=State0) ->
  -    if
  -      (BufBot == 0) ->
  -          serve_empty(Tab,SN,false,State0);
  -      (BufBot =< BL) ->
  -          serve_first(Tab,SN,State0);
  -      (BufBot >= RawBot+BL+BL) ->
  -          gui_append(Tab,RawBot+1,RawBot+BL,#gres{state=SN},State0);
  -      (BufBot >= RawBot+BL) ->
  -          State1 = prefetch(SN,State0),          %% only when filling
  -          gui_append(Tab,RawBot+1,RawBot+BL,#gres{state=SN},State1);
  -      (BufBot == RawBot) ->
  -          State1 = prefetch(SN,State0),          %% only when filling
  -          gui_nop(Tab,#gres{state=SN},State1);
  -      true ->
  -          State1 = prefetch(SN,State0),          %% only when filling
  -          gui_append(Tab,RawBot+1,BufBot,#gres{state=SN},State1)
  -    end.
  -
  -serve_ffwd(Tab,SN,#state{bl=BL,bufBot=BufBot,rawBot=RawBot,replyTo=ReplyTo}=State0) ->
  -    if
  -      (BufBot == 0) ->
  -          serve_empty(Tab,SN,false,State0);
  -      (BufBot =< BL) ->
  -          serve_fwd(Tab,SN,State0);
  -      (RawBot =< BL) ->
  -          serve_fwd(Tab,SN,State0);
  -      (RawBot+RawBot+BL =< BufBot) ->
  -          gui_replace(Tab,RawBot+RawBot-BL+1,RawBot+RawBot,#gres{state=SN},State0);
  -      (RawBot+RawBot =< BufBot) ->
  -          State1 = prefetch(SN,State0),          %% only when filling
  -          gui_replace(Tab,RawBot+RawBot-BL+1,RawBot+RawBot,#gres{state=SN},State1);
  -      true ->
  -          State1 = prefetch(SN,State0),          %% only when filling
  -          State1#state{stack={Tab,button,RawBot+RawBot,ReplyTo}}
  -    end.
  -
  -serve_first(Tab,SN,#state{bl=BL,bufBot=BufBot,rawTop=RawTop,rawBot=RawBot}=State0) ->
  -    if
  -      (BufBot == 0) ->
  -          serve_empty(Tab,SN,false,State0);
  -      (BufBot >= BL+BL) and (RawTop == 1) and (RawBot >= BL) ->
  -          gui_nop(Tab,#gres{state=SN},State0);
  -      (BufBot >= BL+BL) and (RawTop > 1) and (RawTop =< BL+1) ->
  -          gui_prepend(Tab,1,RawTop-1,#gres{state=SN},State0);
  -      (BufBot >= BL+BL) ->
  -          gui_replace(Tab,1,BL,#gres{state=SN},State0);
  -      (BufBot >= BL) and (RawTop == 1) and (RawBot >= BL) ->
  -          State1 = prefetch(SN,State0),          %% only when filling
  -          gui_nop(Tab,#gres{state=SN},State1);
  -      (BufBot >= BL) and (RawTop =< BL) ->
  -          State1 = prefetch(SN,State0),          %% only when filling
  -          gui_replace(Tab,1,BL,#gres{state=SN},State1);
  -      (BufBot >= BL) ->
  -          State1 = prefetch(SN,State0),          %% only when filling
  -          gui_replace(Tab,1,BL,#gres{state=SN},State1);
  -      (BufBot < BL) and (RawTop == 1) and (RawBot == BufBot) ->
  -          State1 = prefetch(SN,State0),          %% only when filling
  -          gui_nop(Tab,#gres{state=SN},State1);
  -      (BufBot < BL) ->
  -          State1 = prefetch(SN,State0),          %% only when filling
  -          gui_replace(Tab,1,BufBot,#gres{state=SN},State1)
  -    end.
  -
  -serve_last(Tab,SN,#state{bl=BL,bufBot=BufBot,rawTop=RawTop,rawBot=RawBot}=State0) ->
  -    State1 = prefetch(SN,State0),          %% only when filling
  -    if
  -      (BufBot == 0) ->
  -          serve_empty(Tab,SN,false,State1);
  -      (RawBot == BufBot) ->
  -          gui_nop(Tab,#gres{state=SN},State1);
  -      (BufBot =< BL) ->
  -          gui_replace(Tab,1,BufBot,#gres{state=SN},State1);
  -      (RawBot >= BufBot-BL+1) ->
  -          gui_append(Tab,RawBot+1,BufBot,#gres{state=SN},State1);
  -      true ->
  -          gui_replace(Tab,BufBot-BL+1,BufBot,#gres{state=SN},State1)
  -    end.
  -
  -serve_bwd(Tab,SN,#state{bl=BL,bufBot=BufBot,rawTop=RawTop}=State0) ->
  -    if
  -      (BufBot == 0) ->
  -          serve_empty(Tab,SN,true,State0);
  -      (BufBot =< BL) ->
  -          serve_first(Tab,SN,State0);
  -      (RawTop > BL) ->
  -          gui_prepend(Tab,RawTop-BL,RawTop-1,#gres{state=SN},State0);
  -      true ->
  -          serve_first(Tab,SN,State0)
  -    end.
  -
  -serve_fbwd(Tab,SN,#state{bl=BL,bufBot=BufBot,rawTop=RawTop}=State0) ->
  -    if
  -      (BufBot == 0) ->
  -          serve_empty(Tab,SN,true,State0);
  -      (RawTop >= BL+BL) and (RawTop div 2+BL == RawTop-1)  ->
  -          gui_prepend(Tab,RawTop div 2+1,RawTop div 2+BL,#gres{state=SN},State0);
  -      (RawTop >= BL+BL) ->
  -          gui_replace(Tab,RawTop div 2+1,RawTop div 2+BL,#gres{state=SN},State0);
  -      true ->
  -          serve_first(Tab,SN,State0)
  -    end.
  -
  -serve_target(Tab,SN,Target,#state{bl=BL,bufBot=BufBot,rawTop=RawTop,rawBot=RawBot,replyTo=ReplyTo}=State0) ->
  -    if
  -      (BufBot == 0) and (SN == complete) ->
  -          serve_empty(Tab,SN,true,State0);
  -      (BufBot == 0) ->         
  -          %% no_data now, com back later 
  -          State1 = prefetch(SN,State0),          %% only when filling
  -          % gui_nop(Tab,#gres{state=SN,loop=Target},State1);
  -          State1#state{stack={Tab,button,Target,ReplyTo}};
  -      (Target =< 0) and (BufBot+Target > 0) ->
  -          %% target given relative to BufBot, retry with absolute target position 
  -          serve_target(Tab,SN,Target,State0);
  -      (Target =< 0)  ->
  -          serve_first(Tab,SN,State0);
  -      (Target =< BufBot) and (BufBot < BL) ->
  -          serve_first(Tab,SN,State0);
  -      (Target =< BufBot) and (RawTop > Target) ->
  -          %% serve block backward
  -          gui_replace(Tab,Target,Target+BL-1,#gres{state=SN},State0);
  -      (Target =< BufBot) and (RawBot < Target) and (Target > BufBot-BL-BL) ->
  -          %% serve block forward
  -          State1 = prefetch(SN,State0),          %% only when filling
  -          gui_replace(Tab,Target-BL+1,Target,#gres{state=SN},State1);
  -      (Target =< BufBot) and (RawBot < Target) ->
  -          %% serve block forward
  -          gui_replace(Tab,Target-BL+1,Target,#gres{state=SN},State0);
  -      (Target > BufBot) and (SN == completed) ->
  -          serve_last(Tab,SN,State0);
  -      (Target > BufBot) ->
  -          State1 = prefetch(SN,State0),          %% only when filling
  -          gui_nop(Tab,#gres{state=SN,loop=Target},State1);
  -      true ->
  -          %% target should be in GUI already
  -          gui_nop(Tab,#gres{state=SN,message="target row already in gui"},State0)
  -    end.
  +
   
   %% TESTS ------------------------------------------------------------------
   
   -include_lib("eunit/include/eunit.hrl").
   
  --define(button(__Button), gui_req(raw, button, __Button, self())).
  +-define(button(__Button), gui_req(button, __Button, self())).
   
   setup() -> 
       ?imem_test_setup().
  
positive.code:         ]).
  
  -export([ rows/2        %% incoming rows from database
          , gui_req/5     %% button '>' '>>' '>|' '>|...' '<' '<<' '...'
                          %% 
                          %% update List of change records [Id,Op,Col1,Col2....Coln] Op=ins|upd|del|nop
          ]).
  
negative.code: %%          {stop, Reason, NewStateData}
  %% --------------------------------------------------------------------
  
  handle_event({button, '>', ReplyTo}, empty, State0) ->
      State1 = fetch(none,none, State0#state{tailMode=false}),
      {next_state, filling, State1#state{stack={button,'>',ReplyTo}}};
  handle_event({button, '>', ReplyTo}, SN, State0) ->
      State1 = reply_stack(SN, ReplyTo, State0),
      {next_state, SN, serve_fwd(SN, State1)};
  handle_event({button, '>>', ReplyTo}, SN, State0) ->
      State1 = reply_stack(SN, ReplyTo, State0),
      {next_state, SN, serve_ffwd(SN, State1)};
  handle_event({button, '|<', ReplyTo}, SN, State0) ->
      State1 = reply_stack(SN, ReplyTo, State0),
      {next_state, SN, serve_top(SN, State1)};
  handle_event({button, '<', ReplyTo}, SN, State0) ->
      State1 = reply_stack(SN, ReplyTo, State0),
      {next_state, SN, serve_bwd(SN, State1)};
  handle_event({button, '<<', ReplyTo}, SN, State0) ->
      State1 = reply_stack(SN, ReplyTo, State0),
      {next_state, SN, serve_fbwd(SN, State1)};
  handle_event({button, Target, ReplyTo}, SN, State0) when is_integer(Target) ->
      State1 = reply_stack(SN, ReplyTo, State0),
      {next_state, SN, serve_target(SN, Target, State1)};
  handle_event({update, ChangeList, ReplyTo}, SN, State0) ->
      State1 = reply_stack(SN, ReplyTo, State0),
      State2 = data_update(SN, ChangeList, State1),
      {next_state, SN, State2};
  handle_event({button, commit, ReplyTo}, SN, State0) ->
      State1 = reply_stack(SN, ReplyTo, State0),
      State2 = data_commit(SN, State1),
      {next_state, SN, State2};
  handle_event({button, rollback, ReplyTo}, SN, State0) ->
      State1 = reply_stack(SN, ReplyTo, State0),
      State2 = data_rollback(SN, State1),
      {next_state, SN, State2};
  handle_event({button, close, ReplyTo}, SN, #state{dirtyCnt=DC}=State0) when DC==0 ->
      State1 = reply_stack(SN, ReplyTo, State0),
      State2 = fetch_close(State1),
      State3 = gui_close(#gres{state=SN},State2),
      {stop, normal, State3};
  handle_event({button, close, ReplyTo}, SN, State0) ->
      State1 = reply_stack(SN, ReplyTo, State0),
      State2 = gui_nop(#gres{state=SN,beep=true,message=?MustCommit},State1),
      {next_state, SN, State2}.
  
  
  %% --------------------------------------------------------------------
  %% Func: handle_sync_event/4 handling sync "send_all_state_event""
  